diff --git a/samples/100_Expressions.noja b/samples/100_Expressions.noja index fe58d3f..7ecc965 100644 --- a/samples/100_Expressions.noja +++ b/samples/100_Expressions.noja @@ -3,15 +3,18 @@ # --- 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: +# 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 +# - 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: diff --git a/samples/150_Branches.noja b/samples/150_Branches.noja index 62844e2..50d5ca0 100644 --- a/samples/150_Branches.noja +++ b/samples/150_Branches.noja @@ -33,6 +33,18 @@ 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 is a were to be higher or equal to 2, it wouldn't +# be defined and the runtime would return an error. # # ------------------------------------------------------------------------- # # ------------------------------------------------------------------------- # diff --git a/samples/200_Loops.noja b/samples/200_Loops.noja index d292d47..b5f1e6a 100644 --- a/samples/200_Loops.noja +++ b/samples/200_Loops.noja @@ -32,6 +32,8 @@ do } while i < 10; +# Like for if-else statements, variables defined inside the loop +# body are shared with the parent's context. # # ------------------------------------------------------------------------- # # ------------------------------------------------------------------------- # diff --git a/samples/250_Functions.noja b/samples/250_Functions.noja new file mode 100644 index 0000000..875a053 --- /dev/null +++ b/samples/250_Functions.noja @@ -0,0 +1,114 @@ + +# ------------------------------------------------------------------------- # +# --- Functions ----------------------------------------------------------- # +# +# Functions can be defined using the following syntax: + +fun say_hello_to(name) + print('Hello, ', name, '!\n\n'); + +# and now we can call it by doing + +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(); + +# ------------------------------------------------------------------------- # +# --- Returns ------------------------------------------------------------- # +# +# 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'); + +# ------------------------------------------------------------------------- # +# --- Scopes -------------------------------------------------------------- # +# +# Functions are always "pure", in the sense that the only values that the +# function body can access are the ones provided as arguments. Usually in +# other languages, functions can access the global scope and the parent +# scope (closures). There's no such mechanism in this language (at the +# moment). +# +# The only exception is made for the "built in" variables, which are +# provided by the runtime of the language and can't be modified by the +# user. The print function is one of these variables. One may override +# these variables but the effect only lasts for the local context. +# + +# Overwrite the print variable inside the global scope.. +print = 5; + +fun test() + { + # Now call print from inside the function. + print('Not overwritten here!\n'); + + # If the previous assignment were to overwrite the print function + # globally, the previous statement would fail because the value 5 + # isn't a function. + } + +test(); + +# Now that i think about it, we lost the reference to the print function +# inside this scope. But we can take it back by returning it from a +# function! + +fun get_print_back() + return print; + +print = get_print_back(); + +print('Hei! Print is back!\n'); + +# +# ------------------------------------------------------------------------- # +# ------------------------------------------------------------------------- #