fixed bug and added a little documentation
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
|
||||
# ------------------------------------------------------------------------- #
|
||||
# --- Introduction -------------------------------------------------------- #
|
||||
#
|
||||
# This language was written as a personal study of how interpreters
|
||||
# and compilers work. For this reason, the language is very basic and
|
||||
# not innovative.
|
||||
# One of the main inspirations was the CPython's source code since
|
||||
# it's extremely readable and has a very simple clean architecture.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------------- #
|
||||
# --- Implementation ------------------------------------------------------ #
|
||||
#
|
||||
# The interpreter works by compiling the provided source to a bytecode
|
||||
# format and executing it. The bytecode is very high level since it
|
||||
# does things like:
|
||||
#
|
||||
# - explicitly referring to variables by name.
|
||||
#
|
||||
# - treating values as atomic things: from the perspective of the
|
||||
# bytecode, a list and an integer occupy the same space on the
|
||||
# stack, which is 1.
|
||||
#
|
||||
# - referring to instructions by their index.
|
||||
#
|
||||
# For example, by compiling the following snippet
|
||||
|
||||
define = true;
|
||||
|
||||
if define:
|
||||
a = 33;
|
||||
|
||||
print(a, '\n');
|
||||
|
||||
# one would obtain the following bytecode:
|
||||
#
|
||||
# 0: PUSHTRU
|
||||
# 1: ASS [define]
|
||||
# 2: POP 1
|
||||
# 3: PUSHVAR [define]
|
||||
# 4: JUMPIFNOTANDPOP 8
|
||||
# 5: PUSHINT 33
|
||||
# 6: ASS [a]
|
||||
# 7: POP 1
|
||||
# 8: PUSHSTR [\n]
|
||||
# 9: PUSHVAR [a]
|
||||
# 10: PUSHVAR [print]
|
||||
# 11: CALL 2
|
||||
# 12: POP 1
|
||||
# 13: RETURN
|
||||
#
|
||||
# as you can see, there are instructions like ASS and PUSHVAR that
|
||||
# assign to and read from variables by specifying names, and jumps
|
||||
# that refer to other points of the "executable" by specifying indices
|
||||
# (like JUMPIFNOTANDPOP) instead of raw addresses.
|
||||
#
|
||||
# All values (objects) are allocated on a garbage-collected heap.
|
||||
# For this reason all variables are simply references to these objects.
|
||||
# The garbage collection algorithm is a copy-and-compact one. It
|
||||
# behaves as a bump-pointer allocator until there is space left,
|
||||
# and when space runs out, it creates a new heap, copies all of the
|
||||
# alive object into it, calls the destructors of the dead objects
|
||||
# and frees the old one.
|
||||
#
|
||||
# ------------------------------------------------------------------------- #
|
||||
# ------------------------------------------------------------------------- #
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
# ------------------------------------------------------------------------- #
|
||||
# --- 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:
|
||||
#
|
||||
# - function declaractions
|
||||
# - expressions
|
||||
# - if-else branches
|
||||
# - while loops
|
||||
# - do-while loops
|
||||
# - return statements
|
||||
# - composit statements
|
||||
#
|
||||
# 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, '\n');
|
||||
|
||||
# ------------------------------------------------------------------------- #
|
||||
# --- Variables and 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:
|
||||
|
||||
# (Uncomment the following line and run this file to get the error)
|
||||
# p = 5 + 'hello';
|
||||
|
||||
# And 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.
|
||||
#
|
||||
# ------------------------------------------------------------------------- #
|
||||
# ------------------------------------------------------------------------- #
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
# ------------------------------------------------------------------------- #
|
||||
# --- 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');
|
||||
}
|
||||
#
|
||||
# ------------------------------------------------------------------------- #
|
||||
# ------------------------------------------------------------------------- #
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------- #
|
||||
# --- 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;
|
||||
|
||||
#
|
||||
# ------------------------------------------------------------------------- #
|
||||
# ------------------------------------------------------------------------- #
|
||||
+19
-1
@@ -1,5 +1,23 @@
|
||||
|
||||
if 'hello' == 'hello':
|
||||
a = 'Francesco';
|
||||
b = 'Gennaro';
|
||||
|
||||
print('Are ', a, ' and ', b, ' the same name?\n');
|
||||
|
||||
if a == b:
|
||||
print('Yup!\n');
|
||||
else
|
||||
print('Nop!\n');
|
||||
|
||||
|
||||
# Now they are!
|
||||
|
||||
a = 'Francesco';
|
||||
b = 'Francesco';
|
||||
|
||||
print('Are ', a, ' and ', b, ' the same name?\n');
|
||||
|
||||
if a == b:
|
||||
print('Yup!\n');
|
||||
else
|
||||
print('Nop!\n');
|
||||
@@ -1,5 +1,7 @@
|
||||
|
||||
if false:
|
||||
define = true;
|
||||
|
||||
if define:
|
||||
a = 33;
|
||||
|
||||
print(a, '\n');
|
||||
+15
-14
@@ -1,25 +1,26 @@
|
||||
|
||||
p = true;
|
||||
# ------------------------------------- #
|
||||
# -- While loop ----------------------- #
|
||||
|
||||
while p:
|
||||
i = 0;
|
||||
|
||||
while i < 3:
|
||||
{
|
||||
print('Hello!\n');
|
||||
p = false;
|
||||
print('Hello from the while loop!\n');
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
# ------------------------------------- #
|
||||
# -- Do-Wile loop --------------------- #
|
||||
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
print('Hello 2!\n');
|
||||
}
|
||||
while false;
|
||||
|
||||
# ------------------------------------- #
|
||||
|
||||
i = 0;
|
||||
while i < 10:
|
||||
{
|
||||
print('i = ', i+1, '\n');
|
||||
print('Hello from the do-while loop!\n');
|
||||
i = i + 1;
|
||||
}
|
||||
while i < 3;
|
||||
|
||||
# ------------------------------------- #
|
||||
# ------------------------------------- #
|
||||
|
||||
Reference in New Issue
Block a user