NewLang v0.2.0

Attention!!!
This article contains a description of the syntax of the previous version of NewLang.
The current version of the language syntax can be viewed here.
NewLang is a high-level programming language in which one can combine standard algorithmic constructs with declarative programming and tensor computations for machine learning tasks.
The main feature of the language is a simple, logical and non-contradictory syntax, which is based not on the use of reserved keywords, but on a strict system of grammar rules using punctuation marks (the list of which also includes the operators of the language).
NewLang is in the process of active development, and this is the second public release, in which substantial new capabilities have been added and some changes have occurred compared to the previous version.
Language features:
- The ability to work both in interpreter and compiler mode*.
- Dynamic and static typing with the ability to specify types explicitly.
- Static typing is conditionally strict (there is no automatic type casting, but conversion between some data types is allowed, for example, an integer can be automatically converted to a real or rational one, but not vice versa).
- Automatic memory management.
- OOP in the form of explicit class inheritance and “duck” typing.
- At the syntax level, support for several types of functions (ordinary and pure functions without side effects).
- Optional and named function parameters.
- Inserts of code in the implementation language (C/C++) are possible*.
- Simple integration with already existing software libraries (including the import of native variables and functions from C/C++).
New global features:
- Macros added. Now one can make one’s own language dialects and use a more familiar notation of algorithmic constructs with keywords. For example, the loop
[ cond ] <-> {
loop body
};
can be written in a more familiar notation
\while (cond) {
loop body
};
- Iterators added for iterating over the elements of dictionaries or for queries to other containers (for example, to databases). At the level of the base syntax, data filtering is supported, including a functional analog of LINQ through the use of callback functions as a filter condition.
- A new data type added — rational numbers with unlimited precision. They are written in the form of an ordinary fraction whose separator is a backslash, for example one can be written as
1\1, and the number 0.5 as1\2. - The dictionary unpacking operator … (ellipsis) has been implemented, which can be used to pass several arguments in a function call or to assign a value to several variables at once.
- Now the assignment operator supports setting values to several variables at once. On the right side of the assignment operator there can be one or several values or the dictionary unpacking operator. Moreover, the dictionary can also be specified on the left side of the assignment operator, and thus one can write the simplest way to iterate over all its elements, when in the loop the first element of the dictionary is saved to the variable item and is removed from the dictionary itself:
[ dict ] <-> {
item, dict := ... dict;
};
Changes in the syntax:
- The notation of loops has changed. Instead of two different types with a precondition and a postcondition, a unified notation form is now used, and the type of the loop is determined by the relative position of the condition and its body.
- The names of arithmetic and some other data types have been changed to more logical ones. The names of arithmetic types now indicate their size (Int8, Int16 … Float32, Float64, etc.).
- Multiline comments have become nested
Detailed information about the language:
Code examples
Definition of the hello function
hello(str) := {
# Import of a standard C function
printf := :Pointer('printf(format:FmtChar, ...):Int32');
# Calling a C function with type checking of the arguments against the format string
printf('%s', $str);
# Returning a value from the hello function
$str;
};
hello(‘Hello, world!’); # Call the function
Output (the first line is output by printf, and the second is the return value of the hello function):
Hello, world!
Hello, world!
<spoiler title="Example script for computing factorial 1000">
#!../output/nlc –eval
@fact := 1\1; # A rational number without precision limitation @mult := 1000..1..-1?; # Make an iterator from the range for the factors from 1000 to 2 [mult ?!] <-> { # Loop until the iterator data runs out # Get the current factor and move to the next element of the iterator fact *= mult !; }; fact # Output the final result
Output:
402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\1
## How to view?
- To run the binary files, the shared libraries libLLVM-13 and libtorch are required: [archive with only the necessary libraries](https://github.com/afteri-ru/trust-lang/releases/download/v0.2.0/nlc_so.tar.xz).
- Also everything can be built directly from the sources according to the instructions in the [repository](https://github.com/afteri-ru/trust-lang)