The prototype consists of an online text editor (based on Monaco Editor).
Computed types are printed as lenses (above each definition). In case of error, the error message is printed instead (see the caveat section for the printing format).
A program is a sequence of toplevel statements:
prog ::= stmt*
stmt ::= type tid tvar* = t [and ...]
| atoms id+
| let gid : t = e
| let [rec] gid param* = e
| let [rec] (gid : t) param* = e
param ::= pat [: t, ...,t]
A statement can be either
Identifiers come in several flavours :
gid ::= id | ( op )
id ::= [a-z_][a-zA-Z0-9_']*
tid ::= [A-Z][a-zA-Z0-9_']*
tvar ::= '[a-z_][a-zA-Z0-9_]*
t ::= simple_type
| t -> t
| t , t
| [ tregex ]
| { id =[?] t,..., id =[?] t [..]}
| t | t
| t & t
| t \\ t
| ~ t
| t where tid tvar* = t [and ...]
simple_type ::= b
| tid [t ... t]
| tvar
| (t)
b ::= ()
| lit
| int--int | (--int) | int--) | (--)
| Any | Empty | True | False | Bool | Int | Char | Unit | String | List | Nil
Types are the usual set-theoretic types with product and arrow and record constructors and union, intersection, difference and negation operators. A sequence type constructor is provided as well. The content of a sequence type can be a regular expression over types, using the usual operators (*, + and ?). For instance, the type [ 'a* (Bool|Int)? ] is equivalent to the type definition
type t 'a = ('a, t) | s
and s = Nil | (Bool | Int, Nil)
Record types are given by the list of their fields, that is labels associated with a type. A label may be absent (denoted by =?). Open record types end their field list with ... Polymorphic types can be instantiated by giving a list of type parameters. Basic types consists of literals (which denote their own singleton type), augmented with integer interval types, and set of builtin type identifiers.
e ::= lit
| gid
| magic
| (e : t ; ... ; t )
| (e :> t ; ... ; t )
| { [e with] id=e,...,id=e}
| [ e; ... ;e ]
| e,e
| fun param ... param -> e
| let gid = e in e
| let (pat) = e in e
| if e [is t] then e else e
| fst e | snd e
| match e with [|] pat -> e | ... | pat -> e end
lit ::= [0-9]+
| 'char'
| "char*"
| float
| () | unit | false | true | nil
Expressions can be
pat ::= :simple_type
| id
| pat,pat | pat|pat | pat&pat
| (pat)
| [ pat; ... ;pat ]
| { id =[?] pat,..., id =[?] pat [..]}
| id = lit
Patterns are essentially types with capture variables. For instance, the following expression
match y with
| :[ Int* ] -> false
| ( x & :Bool, :Int ) | x = false -> x
end
First checks whether y is a list of integers, in which case it returns false. Or, it tests whether either y is a pair of a Boolean and an integer, and captures the Boolean in x, or defines x to the constant false, and then returns x.