A C implementation of the Monkey programming language defined in Thorsten Ball's book "Writing A Interpreter In Go".
gcc -o monkey main.c
Compile the interpreter and perform tests of the different statements and expressions available in tests/repl.c
.
gcc -o monkey main.c; valgrind --leak-check=full --show-leak-kinds=all ./monkey test
(...)
==5256== Command: ./monkey test
==5256==
[PASSED] REPL Test | 90 out of 90 passed
==5256==
==5256== HEAP SUMMARY:
==5256== in use at exit: 0 bytes in 0 blocks
==5256== total heap usage: 13,549 allocs, 13,549 frees, 293,249 bytes allocated
==5256==
==5256== All heap blocks were free
d -- no leaks are possible
(...)
The language currently supports closures, conditional statements, boolean expressions, integers, strings, arrays, and hash maps. Prefix and infix operations are available for some types.
The identifiers let
and return
define statements
and do not produce values. The aforementioned type are called expressions
since they produce values. For example, let x = 5
does not produce a value, but 5
does.
When the code is parsed and evaluated, x
will refer to the name of an Object
type containing a reference to an IntegerObject
type containing the integer literal value of 5
.
Access the REPL by providing repl
as an argument as in ./monkey repl
.
Type '\h' for help and '\q' to quit
>>> let a = 5;
5
>>> a + 10;
15
>>> \h
Commands:
Display environment: ... \e
Open file: ............. \o
>>> \e
[10] a: 0x557f0a1bd290,
>>> \q
Bye!
Open the file examples/count.in
from within the REPL using \o
:
let c = fn(x, g) {
if(x < g) {
return c(x + 1, g);
} else {
return x * 2;
}
};
let fib = fn(x) {
if(x == 0) {
return 0;
} else {
if(x == 1) {
return 1;
} else {
return fib(x - 1) + fib(x - 2);
}
}
};
c(0, 1000);
fib(10);
Type '\h' for help and '\q' to quit
>>> \o
*** Open file: examples/count.in
File "examples/count.in" opened
2000
55
>>> \q
Bye!
The language supports a few built-in functions: len
, find
, str
, push
, first
, last
, rest
, and type
.
>>> len("abcde")
5
>>> len([1, 2, "z"]) + 1
4
>>> find("abc", "c")
2
>>> find("abc", "d")
-1
>>> str([1, 2]) + " (string)"
'[1, 2] (string)'
>>> let a = [1];
[1]
>>> push(a, 2);
NULL
>>> a
[1, 2]
>>> first(["a", "b"])
'a'
>>> last([1, 2])
2
>>> rest([1,2,3])
[2, 3]
>>> type({'a': 1})
'HASHMAP'
>>> type([1])
'ARRAY'
>>> type(fn(x) { return false; })
'FUNCTION'
- Implement mark-and-sweep garbage collection
- Include support for more control flow statements
- Add custom type support
- Finish the compiler implementation in Thorsten Ball's "Writing A Compiler In Go"