This implements a dictionary-lowering compilation pass.
In front of that pass, there's a small, typed functional language written using s-expressions.
After lowering is done, the result is sent to a simple tree-walking interpreter.
This depends on Python 3.
make installdeps
to install the python tools used for development.
make test
to test, make check
to run some basic lints.
Run main.py, e.g.
python3 ./main.py examples/using_superclasses_in_instance.lisp
The file run must contain a main
function.
(class (Parent p)
(:: parent (Fn p Int)))
(class (Child c)
superclasses (Parent)
(:: child (Fn c Int)))
(instance (Parent String)
(fn parent (s)
(length s)))
(instance (Child String)
(fn child (s)
(inc (parent s))))
(fn use-child-class (x)
(child x))
Functions can be given explicit types, e.g.
(fn use-child-class (x)
(=> ((Child a)) (Fn a Int))
(child x))
Expressions can also be typed by wrapping them in a (:: <expression> <type>)
annotation, e.g.
(+ (:: foo Int) (:: bar Int))
This has a parser front-end that uses an ml-like lisp-based syntax.
The next steps are:
- Write brief documentation explaining how the language works
- Add enum/tagged union types (e.g. Some(x) | None)
- Add an actual list type
- Add enough built-in functions to make this usable (e.g. file IO, sockets, processes)
- Add another lowering pass that removes lambdas
Things that would be nice to add:
- A bytecode VM
- Add a kinds system to ensure types are correctly constructed
- Compilation to x86?
Some cleanup I want to do at some point:
- Rip out the
__str__
code on all the syntax classes and replace it with justrender_lisp(self.to_lisp())
. - Rename
scope
andlocals
in the lowering context because those names (especially locals) are confusing. - When lowering uses of class methods on concrete types (e.g.
show 123
), instead of making the entire instance dictionary then accessing one method out of that dictionary, it makes more sense to hard-code a reference to that particular function instead. Doing this requires making stand-alone functions for the instance methods instead of them being lambda functions in the dictionary constructor. - Add line/column numbers to the syntax objects and to error messages.
- Support more than one error message at once.