# milly milly is an hobby, and should not be taken seriously. Interpreter for a Minimal ML-like language whose ideal goal is to be used for bootstrapping compilers and interpreters. ## How to build milly's interpreter is written in portable ISO C11, sources are in `src/` and header files are in `include/`. In order to build it, you must have **GNU Make** installed (in the future i'll try to remove this dependency) and you just have to run: > $ make in the project root to obtain the executable `milly`. ## The language milly is a minimal dialect of Standard ML and Haskell, here is a list of the features (or better, limitations) I want to introduce: - Keep the implementation <5000 LOC - Eager evaluation (call by value) - Algebraic Datatypes (pretty useful for representing syntax trees) - First class functions - Pattern patching (pretty useful for analyzing syntax trees) - Integers, booleans, strings - Mutable `ref` cell - FFI to C - Polymorphic types à la Hindley Milner (probably unfeasible) - Automatic currying of functions, with optimised partial evaluation (unfeasible) - Delimited continuations (this is an overkill) - Easy syntax allowing easy kakoune support - A formal specification (this should be quite manageable to do, and also a good way to learn denotational semantics) milly's full grammar is specified as a pair of lex and yacc files in `ref_parser/`. kakoune plugin for milly is in `extra/milly.kak`. Here is a small example of the syntax: ``` # Helpers datatype 'a list { Cons of ('a, 'a list), Empty } datatype 'a maybe { Just of 'a, Nothing } # Lambda calculus term, nameless representation datatype term { Var of int, Int of int, Abs of term, App of (term, term) } # Result of the evaluation datatype value { Int of int, Closure of (env, term) } alias env = value list typecheck add_binding : value -> env -> env def add_binding v env = Cons v env typecheck lookup : int -> env -> value maybe def lookup _ = Nothing | lookup 0 = Just x | lookup n = lookup (subtract n 1) xs typecheck eval : env -> term -> value def eval e = match lookup idx e { case -> v case -> abort "Variable out of scope" } | eval e = Int x | eval e = Closure e t | eval e = let def new_env = add_binding (eval e t2) e in eval new_env t1 ```