______ @ @
| | _ ___ _
| /\/\ | | | | _ | | |
|/ \| |_| |/ \| |_|
Mini is a WIP functional (ML-style) programming language that has Scheme-like aspects. Currently, it features:
- GADTs
- HM-style type inference
- compilation to C via CPS conversion
- a module system
And some planned features are:
- first-class modules
- record types
- modular implicits
Mini syntax is fairly spartan, being a toy compiler; the only constructs it offers are fix, let, ind (datatype declaration), match, type annotation, lam, and function application.
(fix (fn1 args def) (fn2 args def) expr)defines the (recursive) functionsfn1andfn2with arguments (like(a b c)) inexpr.(let (name1 def) (name2 def) expr)evaluates bothdefs, then evaluatesexprwithname1andname2referring to the output of the relevantdef. You can omitnamein favour of_ifnameis unused inexpr.(match x (case1 -> branch1) (case2 -> branch2))matchesxwith one of the cases of thematch, and performs the correspondingbranch- you can omit the outermost brackets on cases.(lam (x y) expr)denotes a lambda with (curried) argumentsxandy, which evaluatesexprwith those arguments when called.(a :: t)declares to the compiler that the (bracketed) expressionais of typet.
(ind Name (case1 :: type1) (case2 :: type2))declares a GADT with (capitalised) nameNamewhich has constructorscase1of typetype1, andcase2of typetype2.(fix (fn1 args def) (fn2 args def))is like the expression-levelfix, except the resultant expression is ommitted.(let (name1 def) (name2 def))is like the expression-levellet, except the resultant expression is ommitted.(fn1 args def)is shorthand for(fix (fn1 args def))
(fix ((f :: a -> b -> a) (a b) a) exp)annotates the created lambdas whenfis elaborated.(let ((a :: b) b) exp)is equivalent to(let (a (b :: b)) exp).
Here is the factorial function in Mini:
(fac x match (eq x 0)
(true -> 1)
(false -> * x (fac (- x 1))))
(let
(_ putint (fac 6)))i.e. fac is a function that takes one argument, x, and checks if x equals 0:
- if it does,
facreturns1 - if it doesn't,
facreturns x times the factorial ofx's predecessor
The program then calculates fac 6, and outputs it.
This demonstrates some of Mini's key features;
- tail-call optimisation (a Mini program will never* stack overflow)
- pattern matching
- top-level expressions are executed when the module is called
The (let (_ putint (fac 6))) top-level expression shows how anonymized - hence the _ - let-expressions can be used to perform side-effecting operations without having to use sequencing operators like (seq (a b) b).
* - provided my garbage collector works!