6.2 KiB
The Noja language
This file was intended for people who already program in other high level languages (such as Python, Javascript, Ruby) and don't need to be introduced to basic programming concepts (variables, expressions and branches). This way, there is more space for the comparison of the language's features with the mainstream languages.
Table of contents
The first program
The sintax is similar to Python's but is more C-like. A Noja script is a list of statements that can be of multiple kinds:
- function declaractions
- expressions
- if-else branches
- while loops
- do-while loops
- return statements
- composit statements
In general, unless it's inside strings, whitespace is ignored and
comments start with the # character.
The most basic yet interesting program is:
print('Hello, world!\n');
as in other languages, this kind of statement is an expression. Expression statements require a ';' to determine their end.
The print function can take any number of arguments of any type and doesn't add any spaces or newlines to the output.
print(1, 2, 3, true, '\n');
Expressions
You can set variables without declaring them first by using the assignment operator:
a = 5;
which is similar to Python's assignment, but is a little different. In this language, assignments are considered as expressions, in fact you can do things like
a = (b = 1) + 1;
# The value resulting from an assignment is the assigned value.
# After this expression, b's value is 1 and a's value is 2.
print('b = ', b, '\n'); # b = 1
print('a = ', a, '\n'); # a = 2
all of the basic arithmetic operators are available:
x = 1 + 1;
y = 1 - 2;
z = 3 * 2;
w = 10 / 3;
print('x = ', x, '\n'); # x = 2
print('y = ', y, '\n'); # y = -1
print('z = ', z, '\n'); # z = 6
print('w = ', w, '\n'); # w = 3
Note how the division returns the rounded down version of the result. This is because the division was performed on integers. By making one of the operands a floating point value, also a floating point result is returned:
w = 10 / 3.0;
print('w = ', w, '\n');
Arithmetic operators are only available for numeric types of objects. If you try to apply them on other kinds of types, you get a runtime error.
Relational operators are also available:
print(1 < 2, '\n'); # true
print(1 > 2, '\n'); # false
print(1 >= 0, '\n'); # true
print(1 <= 0, '\n'); # false
print(1 == 5, '\n'); # false
print(6 == 6, '\n'); # true
print(1 != 5, '\n'); # true
print(6 != 6, '\n'); # false
The equal and not equal operators are available on every type of object, while the others are only available for numeric types.
Branches
It's possible to make the execution of a statement optional, based on the result of an expression. Like in other languages, you do this using if-else statements:
if 1 < 2:
print('Took the branch!\n'); # This is executed!
if 1 > 2:
print('Didn\'t take the branch\n'); # This isn't!
..or you can specify an alternative branch, which is executed when the condition isn't true:
if 1 > 2:
print('Not executed..\n');
else
print('Executed!\n');
You can have multiple statements inside a branch by having them inside a compound statement. Compound statements are statement lists wrapped inside curly brackets, like this:
{ print('Hello from a '); print('compound statement!\n'); }
This way they count as one statement.
if 1 == 1:
{
print('Executed\n');
print('Also executed\n');
}
Variables defined inside an if-else statement's branch are defined in the parent's context. This implies that variables may or may not be defined when you access them, based on which branch is taken.
a = 1;
if a < 2:
x = 100;
# Now x is defined, but if "a" were to be higher or equal to 2, it
# wouldn't be defined and the runtime would return an error.
Loops
Looping constructs are available in the form of while and do-while statements. The while statement checks the condition before each iteration:
i = 0;
while i < 10:
i = i + 1;
This loop runs for 10 times. As for the if-else statement, a single statement is expected as the body of the while statement. You can provide it a compound statement tho.
i = 0;
while i < 10:
{
print('While iteration no. ', i, '\n');
i = i + 1;
}
The do-while statement checks the condition at the end of each iteration. This means that at least one iteration is performed!
i = 0;
do
{
print('Do-while iteration no. ', i, '\n');
i = i + 1;
}
while i < 10;
Like for if-else statements, variables defined inside the loop body are shared with the parent's context.
Functions
Functions can be defined using the following syntax:
# Define it
fun say_hello_to(name)
print('Hello, ', name, '!\n\n');
# .. and then call it.
say_hello_to('Francesco');
Functions can have an arbitrary amount of arguments. If the function is called with more arguments than it expected, the extra values are thrown away. If the function is called with less arguments than it expected, the argument set if filled up with none values.
fun test_func(a, b, c)
{
print('a = ', a, '\n');
print('b = ', b, '\n');
print('c = ', c, '\n\n');
}
test_func();
# a = none
# b = none
# c = none
test_func(1, 2);
# a = 1
# b = 2
# c = none
test_func(1, 2, 3);
# a = 1
# b = 2
# c = 3
test_func(1, 2, 3, 4);
# a = 1
# b = 2
# c = 3
Functions are actually variables like the ones that are be defined using the assignment operator. In fact, you can reassign them new values if you want.
test_func = 5;
# The following line, if executed, returns an error because the test_func
# identifier is now associated to 5, which is not a function.
test_func(); # Error!!
Functions can return values exactly like in other languages:
fun multiply(x, y)
return x * y;
p = 4;
q = 7;
r = multiply(p, q);
print(p, ' * ', q, ' = ', r, '\n');
If the function doesn't return any values, then the none value is returned.
As an example, the print function always returns none
print(print()); # none