Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/schani/simplang

A very simple programming language for teaching interpreter and compiler building.
https://github.com/schani/simplang

Last synced: 24 days ago
JSON representation

A very simple programming language for teaching interpreter and compiler building.

Awesome Lists containing this project

README

        

SimpLang - A Simple Language
============================

All values are signed 64 bit integers. All global definitions are
functions. Calls are not tail recursive. All functions return
values. Functions are not first class.

Some pieces in the language grammar, like `end`, are superfluous.
They are there to make parsing and later extension easier.

# Example program

let fac n =
loop acc = 1 and
i = 2
in
if n < i then
acc
else
recur (acc * i) (i + 1)
end
end
end

let main n =
fac (n)
end

# Control constructs

`let` introduces variable bindings. They are only visible within the
right hand sides of later bindings in the same `let` expression and
the body of the `let` expression. Later bindings can hide earlier
ones:

let a = 1 and
b = a + 1
in
b
end

gives `2`.

let a = 31415
in
let a = 1 and
a = a + 1
in
a
end
end

also gives `2`, because the first `a` in the inner `let` hides the
outer `a`.

`if` works as expected. It must have both `then` and `else` clauses.

`loop` introduces variable bindings like `let`, but it also provides a
jump target for uses of `recur` in the body. `recur` invocations jump
to the innermost `loop` containing that `recur`, giving new values to
the bound variables.

`recur` is only legal within a `loop` and can only occur in a tail
position, i.e., where the continuation is the same as the continuation
of the containing `loop`. In particular, a `recur` can never be the
condition of an `if`, an argument in a function call, an operand to an
operator, the right hand side of a `let` or `loop` binding.

Functions can only be used in their own definitions or in later
definitions. All functions must have different names.

All arguments to function calls and `recur` must be parenthesized,
i.e.,

recur (a) (-b)

is legal, while

recur a -b

is not.

# Values

`if` and all logical operators consider `0` to be false, all other
values to be true. Logical operators return `0` for false and `1` for
true.

# Operators

These are all the operators, in increasing order of precedence:

&&, ||
!
<, ==
+
*
- (unary)
function application

`&&` and `||` are logical operators, using shortcut evaluation. That
means `&&` will not evaluate its right hand side if the left hand side
evaluates to `0`, and `||` will only evaluate its right hand side if
its left hand side evaluates to `0`.

# Miscellaneous

Functions must take at least one argument.

# Syntax

Identifiers can contain only letters, digits, and the underscore, but
cannot start with a digit.

Function calls use ML/Haskell syntax: Function name followed by
arguments.

# Tests

Run the testsuite with

./tests/test.py TEST-SUITE YOUR-EXE [YOUR-EXE-ARG ...]

where `TEST-SUITE` is the name of one of the directories in `tests`,
such as `full`.