# Felix Syntax

assertions.flxh

0003:  syntax assertions
Assertion statements.
0010:    stmt := "assert" sexpr ";"
The usual assert statement.
Abort the program if the argument expression evaluates to false
when control flows through the assert statement.
Cannot be switched off!
0018:    stmt  := "axiom" sdeclname sfun_arg ":" sexpr ";"
Define an axiom with a general predicate.
An axiom is a function which is true for all arguments.
Axioms are core assertions about invariants which
can be used to specify semantics and form the basis
of reasoning about semantics which goes beyond
structure.
0030:    stmt  := "axiom" sdeclname sfun_arg ":" sexpr "=" sexpr ";"
A variant of an axiom which expresses the semantic
equality of two expressions. Do not confuse this
with an expresion containing run time equality (==).
Semantic equality means that one expression could be
replaced by the other without any observable difference
in behaviour in any program, this can be asserted even
if the type does not provide an equality operator (==).
0038:    stmt  := "lemma" sdeclname sfun_arg ":" sexpr ";"
A lemma is a proposition which it is expected could
be proved by a good automatic theorem prover,
given the axioms. This is the predicate form.
0046:    stmt  := "lemma" sdeclname sfun_arg ":" sexpr "=" sexpr ";"
A lemma is a proposition which it is expected could
be proved by a good automatic theorem prover,
given the axioms. This is the equational form.
0059:    stmt  := "theorem" sdeclname sfun_arg ":" sexpr proof? ";"
A theorem is a proposition which it is expected could
NOT be proved by a good automatic theorem prover,
given the axioms.  In the future, we might like to
provide a "proof sketch" which a suitable tool could
fill in. For the present, you can give a proof as
plain text in a string as a hint to the reader.
This is the predicative form.
0073:    stmt  := "theorem" sdeclname sfun_arg ":" sexpr "=" sexpr proof? ";"
A theorem is a proposition which it is expected could
NOT be proved by a good automatic theorem prover,
given the axioms.  In the future, we might like to
provide a "proof sketch" which a suitable tool could
fill in. For the present, you can give a proof as
plain text in a string as a hint to the reader.
This is the equational form.
0098:    stmt  := "reduce" sdeclname sreduce_args ":" sexpr "=>" sexpr ";"
A reduction is a special kind of proposition of equational
form which also directs the compiler to actually replace
the LHS expression with the RHS expression when found.
Reductions allow powerful high level optimisations,
such as eliminating two successive list reversals.
The client must take great care that reductions don't
lead to infinite loops. Confluence isn't required but
is probably desirable.
Reductions should be used sparingly because searching
for patterns to reduce is applied to every sub-expression
of every expression in the whole program, repeatedly
after any reduction is applied, and this whole process
is done at several different places in the program,
to try to effect the reductions. Particularly both
before and after inlining, since that can destroy
or create candidate patterns.
0102:    sreduce_args := "(" stypeparameter_comma_list ")"
assignment.flxh

0002:  syntax assignment
Assignment forms.
0006:    sassignexpr := sexpr sassignop sexpr
Assignment form.
0009:    sassignop:= "="
Assignment.
0012:    sassignop:= "<-"
Store at pointer.
0015:    sassignop:= ":="
Short form val declaration.
0018:    sassignexpr := sexpr srmwop sexpr
0021:    srmwop:= "+="
Increment.
0023:    srmwop:= "-="
Decrement.
0025:    srmwop:= "*="
Multiply.
0027:    srmwop:= "/="
Divide.
0029:    srmwop:= "%="
C remainder.
0031:    srmwop:= "<<="
Left shift.
0033:    srmwop:= ">>="
Right shift.
0035:    srmwop:= "^="
Bitwise exclusive or.
0037:    srmwop:= "|="
Bitwise or.
0039:    srmwop:= "&="
Bitwise and.
0041:    srmwop:= "<<="
Left shift.
0043:    srmwop:= ">>="
Right shift.
0046:    sassignexpr := sexpr sswapop sexpr
Swap operator.
0048:    sswapop := "<->"
Exchange.
0052:    sassignexpr := spreincrop sexpr
0054:    spreincrop:= "++"
Pre-increment.
0056:    spreincrop:= "--"
Pre-decrement.
0059:    sassignexpr := sexpr spostincrop
0061:    spostincrop:= "++"
Post-increment.
0063:    spostincrop:= "--"
Post-decrement.
0072:    sassignexpr := "def" slexpr "=" sexpr
Multiple initialisation/assignment form.
def x, (var y, val z) = 1,(2,3);
allows unpacking a tuple into a pre-existing variable,
creating a new variable, and binding a new value,
in a single form, with nesting.
0073:    slexpr := slexprs
0074:    slexprs := stlelement "," slexprs
0075:    slexprs := stlelement
0077:    slelement := "val" sname
0078:    slelement := "var" sname
0079:    slelement := sname
0080:    slelement := _
0081:    slelement := "(" slexprs ")"
0083:    stlelement := slelement ":" x[sfactor_pri]
0084:    stlelement := slelement
cbind.flxh

0006:  syntax cbind
Technology for binding to C.
The forms in this DSSL are used to lift types and functions
from C into Felix, and, export Felix types and functions
back into C.
0018:    stmt := "export" "fun" ssuffixed_name "as" sstring ";"
Export a Felix function into C.
The function is exported by generating a C wrapper function
given in the "as" phrase.
The function must be identified by a suffixed name
export fun myfun of (int) as "MyFun";
0022:    stmt := "export" "cfun" ssuffixed_name "as" sstring ";"
Export a Felix function with C type into C.
0026:    stmt := "export" "proc" ssuffixed_name "as" sstring ";"
Export a Felix procedure into C.
0030:    stmt := "export" "cproc" ssuffixed_name "as" sstring ";"
Export a Felix procedure with C type into C.
0036:    stmt := "export" "type" "(" sexpr ")" "as" sstring ";"
Export a type into C.
This is done using a typedef that defines the alias
specified in the "as" phase to be the type expression.
0048:    sopt_prec := "is" sname
The optional precedence phase specifies
the C++ precedence of an expression, to allow
the Felix compiler to minimise generated parentheses.
The precedence must be one of:
atom, primary, postfix, unary, cast, pm, mult, add, shift, rel, eq,
band, bxor, bor, and, xor, or, cond, assign, comma

0049:    sopt_prec := sepsilon
0062:    stmt := sadjectives sfun_kind sdeclname fun_return_type sopt_cstring sopt_prec srequires_clause ";"
Define a function by a C expression.
If the optional C string is elided, the function
is taken to be bound to a C function of the same name.
For example:
fun sin : double -> double;
is equivalent to
fun sin : double -> double = "sin($1)"; 0106: stmt := "ctor" stvarlist squalified_name ":" stypeexpr sopt_cstring sopt_prec srequires_clause ";" Define a constructor function by a C expression. 0128: stmt:= stype_qual* "type" sdeclname "=" scode_spec srequires_clause ";" Define a type by a C type expression. 0135: stmt := "callback" "proc" sname ":" stypeexpr srequires_clause ";" Define a special kind of procedure which can be used as a C callback. 0142: stmt := "callback" "fun" sname ":" stypeexpr srequires_clause ";" Define a special kind of function which can be used as a C callback. 0161: stype_qual := "incomplete" The type qualifier incomplete is used to prevent allocation of values of this type. Pointers can still be formed. 0168: stype_qual := "pod" The type qualified pod is used to specify that a type has a trivial destructor. This allows the garbage collector to omit a call to the destructor, which is the default finaliser. 0172: stype_qual := "_gc_pointer" Specify a C types is a garbage collectable pointer type, so it will be tracked by the collector. 0205: stype_qual := "_gc_type" stypeexpr Specify the shape of the type should be taken as the shape of the given type expression. This is required when the type is immobile and represented by a pointer. For example, the C++ RE2 type of Google's RE2 package cannot be used directly as a type because it is not copy assignable. Instead we have to use a pointer. Here is the way this is done: private type RE2_ = "::re2::RE2"; _gc_pointer _gc_type RE2_ type RE2 = "::re2::RE2*"; gen _ctor_RE2 : string -> RE2 = "new (*PTF gcp, @0, false) RE2($1)";
We bind the private type RE2_ to the C type RE2.
It's private so the public cannot allocate it.
Instead we use the type RE2 which is a pointer, and thus
copyable. because it is a pointer we have to specify
_gc_pointer.

Now, the constructor _ctor_RE2 takes a string and returns
a Felix RE2 (C type RE2*) which is a pointer to a heap allocated
object of type _RE2 (C type RE2).

The constructor does the allocation, so it must provde the
shape of the RE2_ object, and this is what the specification
_gc_type RE2_ does. This allows the notation @0 to refer to
the shape of RE2_ instead of RE2 which it would normally.
0208:    stmt:= stype_qual* "ctypes" sbasic_name_comma_list srequires_clause ";"
Define a set of types as C types with the same names.
0212:    stmt:= "code" scode_spec ";"
Embed a C statement into Felix code.
0219:    stmt:= "noreturn" "code" scode_spec ";"
Embed a C statement which does not return normally
into Felix code. For example:
noreturn code "exit(0);";
0221:    sexpr_code_prefix := "code" "[" stypeexpr "]"
0229:    satom := sexpr_code_prefix sstring
Embed a C expression into Felix.
This required giving the Felix type of the expression.
The expression is contained in the string. For example:
code [double] "sin(0.7)"
0235:    satom := sexpr_code_prefix sname
A short form embedding for variables.
code [double] M_PI
0245:    stmt := sadjectives "const" sdeclname ":" stypeexpr "=" scode_spec srequires_clause ";"
Bind a C expression to a name.
Note that despite the binding being called "const",
the C expression does not have to be constant.
For example:
const rand : int = "rand()";
0260:    stmt := sadjectives "const" sdeclname ":" stypeexpr srequires_clause ";"
Short form of const that declares a variable
bound to the same name in C.
Example:
const RAND_MAX: long;
0269:    sdeclnames := sdeclname ("," sdeclname )+
0278:    stmt := sadjectives "const" sdeclnames ":" stypeexpr srequires_clause ";"
Short form of const that declares a list of variables
of the same type to be bound to their C names.
Useful for lifting enumerations. Example:
const a,b,c : int;
0297:    stmt := "cenum" sname "=" sbasic_name_comma_list srequires_clause ";"
Special form for lifting C enumerations.
Specifies the type name and enumeration constants
in a single statement. Names bound to the same names in C.
This form also defined equality and inequality operators
for the type automatically, as an instance of class Eq.
0322:    stmt := "cflags" sname "=" sbasic_name_comma_list srequires_clause ";"
Specifies the type name and enumeration constants
in a single statement. Names bound to the same names in C.
This form automatically defines equality as an instance of class Eq.
Furthermore it defines all the standard bitwise operators,
as an instance of class Bits.
0349:    stmt := sadjectives sproc_kind sdeclname ":" stypeexpr sopt_cstring srequires_clause ";"
Define a Felix procedures as a binding to a
C statement. Only one statement is allowed.
But you can use a block of course!
If the option C text is elided, the procedure
is taken to be bound to a C function returning void
of the same name.
cgram.flxh

0004:  syntax cgram
Embed C into Felix using extern "C" { } style.
Direct name binding.
WORK IN PROGRESS, NOT OPERATIONAL!
0005:    stmt := "extern" '"C"' cstatement
0006:    stmt := "extern" '"C"' "{" cstatement+ "}"
0009:    satom := "extern" '"C"' "(" expression ")"
conditional.flxh

0002:  syntax conditional
Basic conditional statements.
0005:    stmt := "if" sexpr "goto" sname ";"
Short form conditional goto statement.
0008:    stmt := "if" sexpr "return" ";"
Short form conditional return statement.
0009:    stmt := "if" sexpr "return" sexpr ";"
0012:    stmt := "if" sexpr "call" sexpr ";"
Short form conditional call statement.
0016:    stmt := "if" sexpr "do" sstatements "done"
Short form one branch conditional.
0020:    stmt := "if" sexpr "begin" sstatements "end"
Short form one branch conditional.
0025:    stmt := sexpr "??" stmt
Perl style conditional.
0038:    stmt := "if" sexpr "do" sstatements selse_clause "done"
General conditional chain statement.
if condition do
..
elif condition do
.
.
else
..
done
0041:    stmt := "if" sexpr "begin" sstatements selse_clause "end"
0045:    selif_clause := "elif" sexpr "do" sstatements
General elif clause.
0048:    selif_clause := "elif" sexpr "return" ";"?
Short form elif return clause.
0049:    selif_clause := "elif" sexpr "return" sexpr ";"?
0052:    selif_clause := "elif" sexpr "goto" sname ";"?
Short form elif goto clause.
0055:    selif_clauses := selif_clauses selif_clause
0056:    selif_clauses := selif_clause
0057:    selse_clause := selif_clauses "else" sstatements
0065:    selse_clause := "else" sstatements
0066:    selse_clause := selif_clauses
control.flxh

0002:  syntax control
Core control flow operators.
0005:    stmt := "do" sstatements "done"
Just a group of statements.
0006:    stmt := "begin" sstatements "end"
0009:    stmt := "call" sexpr  ";"
Call a procedure (verbose).
0012:    stmt := "return" ";"
Procedure return.
0016:    stmt := "return" "from" sname ";"
Fast procedure return.
Returns immediately from enclosing procedure with given name.
0021:    stmt := "jump" sexpr ";"
Procedure explicit tail call.
Equivalent to a call followed by a return.
0024:    stmt := "return" sexpr ";"
Function return with value.
0030:    stmt := "yield" sexpr ";"
Generator/iterator exchange with value (restart after yield).
Yield is like a return, except that re-entering the generator
will continue on after the yield statement rather that starting
from the top.
0033:    stmt := "loop" sname sexpr
Special short form procedure self-tail call with argument.
0036:    stmt := "loop" sname ";"
Special short form procedure self-tail call without argument.
0039:    stmt := "halt" sstring ";"
Stop the program with prejudice and a message.
0043:    stmt := sname ":>"
Label any statement.
Do not confuse with loop labels.
0046:    stmt := "goto" sname ";"
Unconditional goto label.
0049:    stmt := "goto-indirect" sexpr ";"
Unconditional goto expression.
0064:    stmt := "try" stmt+ catches "endtry"
Exception handling.
try .. catch x : T => handler endtry
can be used to execute code which might throw
an exception, and catch the exception.
This is primarily intended to for wrapping C bindings.
Exceptions do not propage properly in Felix across
multiple function/procedure layers. If you have to use
this construction be sure to keep wrap the try block
closely around the throwing code.
0067:    catch := "catch" sname ":" sexpr  "=>" stmt+
0070:    catches := catch+
executable.flxh

0002:  syntax executable
Special executable forms.
0006:    stmt := "_svc" sname ";"
System service call.
0009:    stmt := sassignexpr ";"
Assignment expression.
0012:    stmt := "trace" sname sstring ";"
Debug trace expression.
0017:    stmt := sexpr ";"
Call expression.
Short form of "call f a;" is just "f a;"
Short form of "call f ();" is just "f"
0020:    stmt := "??" sinteger ";"
Template replacement index.
expressions.flxh

0001:  syntax expressions
0039:    sexpr := x[let_pri]
0040:    stypeexpr:= x[sor_condition_pri]
0043:    x[let_pri] := "let" spattern "=" x[let_pri] "in" x[let_pri]
Let binding.
0046:    x[let_pri] := "let" "fun" sdeclname sfun_arg* fun_return_type "=>" x[let_pri] "in" x[let_pri]
Let fun binding.
0060:    x[let_pri] := sconditional
Conditional expression.
0063:    x[let_pri] := pattern_match
Pattern matching.
0067:    x[sdollar_apply_pri] := x[stuple_pri] "unless" x[let_pri] "then" x[sdollar_apply_pri]
Alternate conditional expression.
0071:    x[sdollar_apply_pri] := x[stuple_pri] "$" x[sdollar_apply_pri] Low precedence right associative application. 0074: x[stuple_cons_pri] := x[>stuple_cons_pri] ",," x[stuple_cons_pri] Tuple formation by cons: right associative. 0077: x[stuple_pri] := x[>stuple_pri] ( "," x[>stuple_pri])+ Tuple formation non-associative. 0080: x[simplies_condition_pri] := x[>simplies_condition_pri] "implies" x[>simplies_condition_pri] Logical implication. 0083: x[sor_condition_pri] := x[>sor_condition_pri] ( "or" x[>sor_condition_pri])+ Logical disjunction (or). 0086: x[sand_condition_pri] := x[>sand_condition_pri] ( "and" x[>sand_condition_pri])+ Logical conjunction (and). 0089: x[snot_condition_pri] := "not" x[snot_condition_pri] Logical negation (not). 0092: x[scomparison_pri]:= x[>scomparison_pri] "<" x[>scomparison_pri] Compare less. 0095: x[scomparison_pri]:= x[>scomparison_pri] "<=" x[>scomparison_pri] Compare less equal. 0098: x[scomparison_pri]:= x[>scomparison_pri] "==" x[>scomparison_pri] Compare equal. 0101: x[scomparison_pri]:= x[>scomparison_pri] "!=" x[>scomparison_pri] Compare not equal. 0104: x[scomparison_pri]:= x[>scomparison_pri] ">=" x[>scomparison_pri] Compare greater equal. 0107: x[scomparison_pri]:= x[>scomparison_pri] ">" x[>scomparison_pri] Compare greater. 0111: x[scomparison_pri]:= x[>scomparison_pri] "in" x[>scomparison_pri] Set membership. 0114: x[scomparison_pri]:= x[>scomparison_pri] "\in" x[>scomparison_pri] Set membership. 0117: x[sas_expr_pri] := x[sas_expr_pri] "as" sname Named temporary value. 0120: x[sas_expr_pri] := x[sas_expr_pri] "as" "var" sname Named variable. 0123: x[ssetunion_pri] := x[ssetunion_pri] "|->" x[>ssetunion_pri] Left assoc, for schannel pipes. 0126: x[ssetunion_pri] := x[>ssetunion_pri] ">->" x[>ssetunion_pri] Non associative, streaming data structure into transducer. 0132: x[sarrow_pri] := x[scase_literal_pri] "!" x[sarrow_pri] List cons, right associative. 0135: x[sarrow_pri] := x[scase_literal_pri] "->" x[sarrow_pri] Function type, right associative. 0138: x[sarrow_pri] := x[scase_literal_pri] "-->" x[sarrow_pri] C function type, right associative. 0141: x[scase_literal_pri] := "case" sinteger Case tag literal. 0144: x[scase_literal_pri] := "case" sinteger "of" x[ssum_pri] Case value. 0147: x[scase_literal_pri] := "case" sname "of" x[ssum_pri] Variant value. 0150: x[sbor_pri] := x[sbor_pri] "\|" x[>sbor_pri] Bitwise or, left associative. 0153: x[sbxor_pri] := x[sbxor_pri] "\^" x[>sbxor_pri] Bitwise or, left associative. 0156: x[sband_pri] := x[sband_pri] "\&" x[>sband_pri] Bitwise exclusive or, left associative. 0159: x[sshift_pri] := x[sshift_pri] "<<" x[>sshift_pri] Bitwise left shift, left associative. 0162: x[sshift_pri] := x[sshift_pri] ">>" x[>sshift_pri] Bitwise right shift, left associative. 0165: x[ssum_pri] := x[>ssum_pri] ("+" x[>ssum_pri])+ Addition: left non-associative. 0168: x[ssubtraction_pri] := x[ssubtraction_pri] "-" x[sproduct_pri] Subtraction: left associative. 0171: x[sproduct_pri] := x[>sproduct_pri] ("*" x[>sproduct_pri])+ multiplication: non-associative. 0174: x[s_term_pri] := x[s_term_pri] "/" x[>s_term_pri] division: left associative. 0177: x[s_term_pri] := x[s_term_pri] "%" x[>s_term_pri] remainder: left associative. 0180: x[sprefixed_pri] := "!" x[spower_pri] Prefix exclaim. 0183: x[sprefixed_pri] := "+" x[spower_pri] Prefix plus. 0186: x[sprefixed_pri] := "-" x[spower_pri] Prefix negation. 0189: x[sprefixed_pri] := "~" x[spower_pri] Prefix complement. 0192: x[spower_pri] := x[ssuperscript_pri] "**" x[sprefixed_pri] Fortran power. 0195: x[ssuperscript_pri] := x[ssuperscript_pri] "^" x[srefr_pri] Superscript, exponential. 0198: x[ssuperscript_pri] := x[ssuperscript_pri] "\circ" x[>ssuperscript_pri] composition 0201: x[srefr_pri] := "*" x[srefr_pri] C dereference. 0204: x[srefr_pri] := "_deref" x[srefr_pri] Deref primitive. 0207: x[srefr_pri] := "new" x[srefr_pri] Operator new. 0210: satom := "(" srecord_mem_decl ("," srecord_mem_decl)* ")" Record type. 0212: srecord_mem_decl := sname ":" stypeexpr 0215: satom := "union" "{" stype_sum_item0* "}" Variant type. 0216: stype_sum_item := sname sopt_value stvarlist "of" sexpr 0217: stype_sum_item := sname sopt_value stvarlist 0219: stype_sum_item0 := sname "of" sexpr 0220: stype_sum_item0 := sname 0222: stype_sum_item1 := stype_sum_item ";" 0224: stype_sum_item2 := "|" stype_sum_item 0225: stype_sum_items2 := stype_sum_item stype_sum_item2* 0226: stype_sum_items2 := stype_sum_item2* 0229: x[sapplication_pri] := x[sapplication_pri] x[scoercion_pri] Operator whitespace: application. 0232: x[sapplication_pri] := "caseno" x[scoercion_pri] Variant index. 0236: x[sapplication_pri] := "likely" x[scoercion_pri] Optimisation hint: likely. Use in conditionals, e.g. if likely(x) do ... 0240: x[sapplication_pri] := "unlikely" x[scoercion_pri] Optimisation hint: unlikely. Use in conditionals, e.g. if unlikely(x) do ... 0243: x[scoercion_pri] := x[scoercion_pri] ":>>" x[sfactor_pri] Suffixed coercion. 0245: x[scoercion_pri] := ssuffixed_name 0247: x[sfactor_pri] := sthe_name 0252: x[sfactor_pri] := x[sfactor_pri] "." "[" sexpr "]" String subscript. 0255: x[sfactor_pri] := x[sfactor_pri] "." "[" sexpr "to" sexpr "]" String substring. 0258: x[sfactor_pri] := x[sfactor_pri] "." "[" sexpr "to" "]" String substring, to end of string. 0261: x[sfactor_pri] := x[sfactor_pri] "." "[" "to" sexpr "]" String substring, from start of string. 0264: x[sfactor_pri] := x[sfactor_pri] "." sthe_name Reverse application. 0268: x[sfactor_pri] := x[sfactor_pri] "*." sthe_name Reverse application with dereference. a *. b same as (*a) . b, like C a -> b. 0272: x[sfactor_pri] := x[sfactor_pri] "&." sthe_name a &. b is similar to &a . b for an array, but can be overloaded for abstract arrays: like a + b in C. Returns pointer. 0275: sbasic_name_comma_list:= sname ("," sname)* 0278: sthe_name := "#" sthe_name High precedence unit application. #f = f (). 0281: sthe_name := "&" sthe_name Felix pointer type and address of operator. 0284: sthe_name := "label_address" sname Felix address of operator. 0288: sthe_name := "@" sthe_name C pointer type. 0291: sthe_name := "noexpand" squalified_name macro expansion freezer. 0294: sthe_name := "?" sname pattern variable. 0297: sthe_name := "?" sinteger Template replacement index. 0299: sthe_name := squalified_name 0300: sthe_name := satom 0303: sreally_qualified_name := squalified_name "::" ssimple_name_parts Qualified name. 0306: squalified_name := sreally_qualified_name 0308: squalified_name := ssimple_name_parts 0311: ssimple_name_parts := sname 0312: ssimple_name_parts := sname "[" sexpr "]" 0315: ssuffixed_name := squalified_name "of" x[sfactor_pri] Suffixed name (to name functions). 0319: satom := "(" rassign ("," rassign )* ")" record value (comma separated). 0322: rassign := sname "=" x[sor_condition_pri] 0327: satom := "struct" "{" vassign+ "}" record value, statement list. this variant is useful for encapsulating a series of var x = y; style statements. 0330: vassign := "var" sname "=" sexpr ";" 0334: satom := sliteral scalar literals (numbers, strings). 0337: satom := _ Wildcard pattern. 0340: satom := "..." Ellipsis (for binding C varags functions). 0343: satom := "false" Boolean false. 0346: satom := "true" Boolean true. 0349: satom := "callback" "[" sexpr "]" Callback expression. 0352: satom := "[|" sexpr "|]" Array expression (deprecated). 0355: satom := "{" sexpr "}" Short form anonymous function closure. 0358: satom := scompound Short form anonymous procedure closure. 0362: satom := "(" stmt+ sexpr ")" Short form sequence operator. ( stmt; expr ) means the same as #{stmt; return expr; } 0378: satom := "(" "var" sexpr ")" special anonymous variable forces eager eval. 0391: satom := "(" sexpr ")" Grouping. 0394: satom := "(" ")" Empty tuple (unit tuple). 0397: satom := "extend" stypelist "with" sexpr "end" Object extension. 0400: satom := sconditional "endif" Conditional expression. 0403: sconditional := "if" sexpr "then" sexpr selse_part Conditional expression (prefix). 0406: selif := "elif" sexpr "then" sexpr 0408: selifs := selif 0409: selifs := selifs selif 0411: selse_part:= "else" sexpr 0412: selse_part:= selifs "else" sexpr felix.flxh 0001: syntax felix functions.flxh 0002: syntax functions General functional forms. 0006: satom := sadjectives "fun" stvarlist slambda_fun_args fun_return_type "=" scompound Anonymous function (lamda). 0012: x[slambda_pri] := sadjectives "fun" stvarlist slambda_fun_args fun_return_type "=>" sexpr Anonymous function (lamda). 0018: satom := sadjectives "gen" stvarlist slambda_fun_args fun_return_type "=" scompound Anonymous generator (lamda). 0024: x[slambda_pri] := sadjectives "gen" stvarlist slambda_fun_args fun_return_type "=>" sexpr Anonymous generator (lamda). 0031: satom := sadjectives "proc" stvarlist slambda_fun_args scompound Anonymous procedure (lamda). 0037: satom := sadjectives "proc" stvarlist scompound Anonymous procedure (lamda). 0044: satom := sadjectives "object" stvarlist slambda_fun_args fun_return_type "=" scompound Anonymous object constructor (lamda). UGLY. 0050: sadjective := "inline" Function adjective (prefix property) inline. 0053: sadjective := "noinline" Function adjective (prefix property) noinline. 0057: sadjective := "extern" Function adjective (prefix property) extern. 0061: sadjective := "virtual" Function adjective (prefix property) virtual. In classes only. Specifies an overrideable function. 0066: sadjective := "lvalue" Function adjective (prefix property) lvalue. C function bindings only. Allows result of function call to be addressed. 0070: sadjective := "pure" Function dependent on its arguments only, not dependent on any variables in its enclosing context. 0073: sadjective := "impure" Function may be dependent on variables in its enclosing context. 0076: sadjective := "total" Function returns a result for all argument values. 0080: sadjective := "partial" Function may fail for some argument values. Equivalent to a function with a non-tautologous but unknown pre-condition. 0083: sadjective := "method" Specifies a method, in an object definition only. 0089: sadjective := "export" Specifies function is to be exported under its Felix name. Function must be top level and non-polymorphic. Top level means the global space or a non-polymorphic class nested in a top level space (recursively). 0090: sadjective := "export" sstring 0092: sadjectives := sadjective* 0094: slambda_fun_arg := "(" sparameter_comma_list "when" sexpr ")" 0095: slambda_fun_arg := "(" sparameter_comma_list ")" 0096: slambda_fun_args := slambda_fun_arg+ 0099: fun_return_type := ":" stypeexpr "expect" sexpr Function return type specification with post-condition. 0102: fun_return_type := ":" stypeexpr Function return type specification without post-condition. 0105: fun_return_type := "expect" sexpr Function return postcondition without type. 0108: fun_return_type := sepsilon No return type. 0111: object_return_type := stypeexpr Object factory return type. 0114: sfunction := "invariant" sexpr ";" Object invariant 0117: sparameter := sparam_qual sname ":" x[sarrow_pri] "=" x[sor_condition_pri] Function parameter with type and default value. 0120: sparameter := sparam_qual sname ":" x[sarrow_pri] Function parameter with type. 0124: sparameter := sparam_qual sname Function parameter without type. Defaults to polymorphic in unnamed type variable. 0127: sparameter_comma_list := sepsilon Empty parameter tuple. 0130: sparameter_comma_list := sparameter ("," sparameter)* Populated parameter tuple. 0133: sparam_qual := "val" Parameter qualifier: val. 0136: sparam_qual := "var" Parameter qualifier: var. 0139: sparam_qual := "ref" Parameter qualifier: ref. 0142: sparam_qual := "fun" Parameter qualifier: fun. 0145: sparam_qual := sepsilon Default parameter qualifier is val. 0148: sfun_arg := "(" sparameter_comma_list "when" sexpr ")" Function tuple parameter with pre-condition. 0151: sfun_arg := "(" sparameter_comma_list ")" Function tuple parameter without pre-condition. 0154: sfun_arg := sname Short form function parameter single polymorphic variable. 0158: sfun_kind := "cfun" Function binder: C function. A function with C function type. 0162: sfun_kind := "gen" Function binder: Generator. A function with side effects. 0166: sfun_kind := "fun" Function binder: Function. A function without side-effects. 0168: stmt := sfunction 0174: sfunction := sadjectives sfun_kind sdeclname sfun_arg* fun_return_type "=>" sexpr ";" General function definition. Multiple tuple arguments, body is expression. Example: inline fun f (x:int when x>0) (y:long when y>0l) : long expect result > 0l => x.long + y; 0183: sfunction := sadjectives sfun_kind sdeclname sfun_arg* fun_return_type "=" scompound General function definition. Multiple tuple arguments, body of statements. inline fun f (x:int when x>0) (y:long when y>0l) : long expect result > 0l { return x.long + y; } 0189: sfunction := "object" sdeclname sfun_arg* "implements" object_return_type "=" scompound Object factory definition with interface type. 0195: sfunction := "object" sdeclname sfun_arg* "=" scompound Object factory definition without interface type. 0221: sfunction := "object" sdeclname sfun_arg* "extends" stypeexpr_comma_list "=" scompound Object factory definition with inherited methods and interface type. Object factory definition with inherited methods. 0236: stypeexpr_comma_list := stypeexpr ("," stypeexpr)* 0239: sopt_cstring := "=" scode_spec 0240: sopt_cstring := sepsilon 0245: sfunction := sadjectives sfun_kind sdeclname fun_return_type "=" smatching+ ";" Short form function definition. Example: fun f : int -> int = | 0 => 0 | _ => 1; 0274: sproc_kind := "proc" Procedure binder. 0278: sproc_kind := "cproc" C procedure binder. Procedure has C function type (with void result type). 0280: sopt_traint_eq:= "expect" sexpr "=" 0281: sopt_traint_eq:= "=" 0282: sopt_traint_eq:= sepsilon 0284: sopt_traint:= "expect" sexpr 0285: sopt_traint:= sepsilon 0287: sctor_init := sname "(" sexpr ")" 0288: sctor_inits := ":" sctor_init ("," sctor_init)* 0289: sctor_inits := sepsilon 0294: sfunction := "ctor" stvarlist squalified_name sfun_arg+ sopt_traint_eq scompound Short form constructor function. The name of the function must be a type name. The return type is taken as the type with the name of the function. 0311: sfunction := "ctor" stvarlist squalified_name sfun_arg+ sopt_traint "=>" sexpr ";" Short form constructor function. The name of the function must be a type name. The return type is taken as the type with the name of the function. 0326: sfunction := sadjectives sproc_kind sdeclname sfun_arg* sopt_traint_eq scompound Procedure definition, general form. 0332: sfunction := sadjectives sproc_kind sdeclname sfun_arg* "=>" stmt Procedure definition, short form (one statement). grammar_float_lexer.flxh 0007: syntax felix_float_lexer Floating point literals. Follows ISO C89, except that we allow underscores; AND we require both leading and trailing digits so that x.0 works for tuple projections and 0.f is a function application 0050: strfloat := sfloat 0053: sliteral := sfloat grammar_ident_lexer.flxh 0001: syntax felix_ident_lexer 0028: sname := flx_ident =># "_1" | tex_ident =># "_1" | sym_ident grammar_int_lexer.flxh 0175: syntax felix_int_lexer Integer literals. Felix integer literals consist of an optional radix specifer, a sequence of digits of the radix type, possibly separated by an underscore (_) character, and a trailing type specifier. The radix can be: 0b, 0B - binary 0o, 0O - octal 0d, 0D - decimal 0x, 0X - hex The default is decimal. NOTE: unlike C a leading 0 in does NOT denote octal. Underscores are allowed between digits or the radix and the first digit, or between the digits and type specifier. The adaptable signed type specifiers are: t -- tiny (char as int) s -- short i -- int l -- long v,ll -- vlong (long long in C) z -- ssize (ssize_t in C, a signed variant of size_t) j -- intmax p -- intptr d -- ptrdiff These may be upper of lower case. A "u" or "U" before or after such specifier indicates the correspondin unsigned type. The follingw exact type specifiers can be given: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "I8" | "I16" | "I32" | "I64" | "U8" | "U16" | "U32" | "U64"; The default type is "int". 0213: sinteger := int_prefix 0229: sliteral := int_lit 0232: sintegral := int_lit 0233: sintegral := "-" int_lit 0244: strint := sintegral grammar_lexer.flxh 0036: syntax lexer grammar_regdefs.flxh 0001: syntax global_regdefs grammar_string_lexer.flxh 0181: syntax felix_string_lexer String literals. Generaly we follow Python here. Felix allows strings to be delimited by; single quotes ' double quotes " triped single quotes ''' tripled double quotes """ The single quote forms must be on a single line. The triple quoted forms may span lines, and include embedded newline characters. These forms all allows embedded escape codes. These are: \a - 7 : bell \b - 8 : backspace \t - 9 : horizontal tab \n - 10 : linefeed, newline \r - 13 : carriage return \v - 11 : vertical tab \f - 12 :form feed \e - 27 : escape \\ - \ : slosh \" - " : double quote \' - ' : single quote \ - 32 : space \xFF - hexadecimal character code \o7 \o77 \o777 -- octal character code (stops on count of 3 or non-octal character) \d9 \d99 \d999 -- decimal character code (stops on count of 3 or non-decimal character) \uFFFF - utf8 encoding of specified hex value \UFFFFFFFF - utf8 encoding of specified hex value A prefix "r" or "R" on a double quoted string or triple double quoted string suppresses escape processing, this is called a raw string literal. NOTE: single quoted string cannot be used! A prefix "w" or "W" specifies a wide character string, of character type wchar. DEPRECATED. A prefix of "u" or "U" specifes a string of uint32. This is a full Unicode string. THIS FEATURE WILL BE DEPRECATED. IT WILL BE REPLACED BY C++11 Unicode compliant strings. A prefix of "c" or "C" specifies a C NTBS (Nul terminated byte string) be generated instead of a C++ string. Such a string has type +char rather than string. A literal prefixed by "q" or "Q" is a Perl interpolation string. Such strings are actually functions. Each occurrence of$(varname) in the string is replaced
at run time by the value "str varname". The type of the
variable must provide an overload of "str" which returns
a C++ string for this to work.
A literal prefixed by a "f" or "F" is a C format string.
Such strings are actually functions.
The string contains code such as "%d" or other supported
C format string. Variable field width specifiers "*" are
not permitted. The additional format specification %S
is supported and requires a C++ string argument.
Such functions accept a tuple of values like this:
f"%d-$S" (42, "Hello") If vsnprintf is available on the local platform it is used to provide an implementation which cannot overrun. If it is not, vsprintf is used instead with a 1000 character buffer. The argument types and code types are fully checked for type safety. The special literal with a "n" or "N" prefix is a way to encode an arbitrary sequence of characters as an identifer in a context where the parser might interpret it otherwise. It can be used, for example, to define special characters as functions. For example: typedef fun n"@" (T:TYPE) : TYPE => cptr[T]; 0235: sname := nstring_literal 0262: sliteral := String 0276: sliteral := Wstring 0290: sliteral := Ustring 0304: sliteral := Cstring 0308: sliteral := Qstring 0312: sliteral := Fstring json.flxh 0015: syntax json String grammar for JSON. This DSSL just allows one to construct syntactically valid JSON strings. That is, an expression like: json ( { a:1 ,b:"hello", [1,2,null] } ) is equivalent to '{ a:1 ,b:"hello", [1,2,null] }' however, it is validated by the parser. 0017: x[sapplication_pri] := "json" "(" json_value ")" loops.flxh 0030: syntax loops Primary looping contructs. 0034: stmt := "break" sname Labelled break. Use to exit from the loop with the specified label. 0036: stmt_group := "do" sstatements "done" 0037: stmt_group := "begin" sstatements "end" 0038: stmt_group := "perform" stmt 0042: stmt := "continue" sname Labelled continue. Use to continue with the next iteration of the loop with the specified label. 0046: stmt := "redo" sname Labelled redo. Use to restart this iteration of the loop with the specified label. 0050: optlabel := sname ":" Syntax for a loop label. Use just before the loop. 0053: optlabel := sepsilon Loop labels aren't required. 0056: stmt := optlabel "while" sexpr stmt_group Standard while loop. 0069: stmt := optlabel "until" sexpr stmt_group Negated while loop. 0081: stmt := optlabel "for" "(" stmt sexpr ";" stmt ")" stmt 0099: stmt := optlabel "for" stmt "while" sexpr ";" "next" stmt stmt_group 0118: stmt := optlabel "for" stmt "until" sexpr ";" "next" stmt stmt_group 0146: stmt := optlabel "for" sname "in" sexpr "upto" sexpr stmt_group Numeric upwards for loop, existing control variable. Ranges are inclusive. This is essential in case the loops if over the complete domain of the control variable type. The start and end argument types and the declared control variable type must be the same. 0174: stmt := optlabel "for" "var" sname ":" sexpr "in" sexpr "upto" sexpr stmt_group Numeric upwards for loop, also declares the control variable with type. The control variable is local to the enclosing context, NOT the loop, so it can be inspected in code following the loop. Ranges are inclusive. This is essential in case the loops if over the complete domain of the control variable type. The start and end argument types and the declared control variable type must be the same. 0202: stmt := optlabel "for" "var" sname "in" sexpr "upto" sexpr stmt_group Numeric upwards for loop, also declares the control variable. The control variable is local to the enclosing context, NOT the loop, so it can be inspected in code following the loop. Ranges are inclusive. This is essential in case the loops if over the complete domain of the control variable type. The start and end argument types must be the same. 0229: stmt := optlabel "for" sname "in" sexpr "downto" sexpr stmt_group Numeric downwards for loop, existing control variable. Ranges are inclusive. This is essential in case the loops if over the complete domain of the control variable type. The start and end argument types and the declared control variable type must be the same. 0257: stmt := optlabel "for" "var" sname ":" sexpr "in" sexpr "downto" sexpr stmt_group Numeric downwards for loop, also declares the control variable with type. The control variable is local to the enclosing context, NOT the loop, so it can be inspected in code following the loop. Ranges are inclusive. This is essential in case the loops if over the complete domain of the control variable type. The start and end argument types and the declared control variable type must be the same. 0285: stmt := optlabel "for" "var" sname "in" sexpr "downto" sexpr stmt_group Numeric downwards for loop, also declares the control variable. The control variable is local to the enclosing context, NOT the loop, so it can be inspected in code following the loop. Ranges are inclusive. This is essential in case the loops if over the complete domain of the control variable type. The start and end argument types and the declared control variable type must be the same. 0322: stmt := optlabel "for" sname "in" sexpr stmt_group Basic stream consumer. The second argument must be a value for which there is a generator: iterator : D -> unit -> opt[T] Due to a hack in std/datatype/slice.flx: gen iterator[t] (f:1->opt[t]) => f; you can also use an actual iterator. 1. The iterator function is called. 2. If the result is None, the loop exits. 3. If the result is Some ?t, then t is assigned to the control variable, 4. the loop body is executed, and 6. we go back to step 1. 0365: stmt := optlabel "match" spattern "in" sexpr stmt_group Upmarket stream consumer. The second argument must be a value for which there is a generator: iterator : D -> unit -> opt[T] Due to a hack in std/datatype/slice.flx: gen iterator[t] (f:1->opt[t]) => f; you can also use an actual iterator. 1. The iterator function is called. 2. If the result is None, the loop exits. 3. If the result is Some ?t, then t is matched against the pattern. 4. If the pattern matches, loop body is executed, and 5. we go back to step 1. 6. If the pattern does not match, 7. we go back to step 1 without executing the loop body. macros.flxh 0001: syntax macros 0003: stmt := "macro" "val" sbasic_name_comma_list "=" sexpr ";" 0006: stmt := "forall" sname "in" sexpr "do" sstatements "done" namespaces.flxh 0002: syntax namespaces Felix namespace control. 0009: stmt := "rename" sdeclname "=" squalified_name ";" Create a new solo name and bind it to an existing name. NOTE: it doesn't rename anything! Used to inject solo names into a namespace. 0017: stmt := "rename" "fun" sdeclname "=" squalified_name ";" Create a new name for an existing set of function names. NOTE: it doesn't rename anything! Used to inject an overload set into a namespace. 0024: stmt := "inherit" stvarlist squalified_name ";" Inject all the public members of a class or module into a namespace. 0037: stmt := "open" stvarlist squalified_name ";" Inject all the public members of a class or module "just underneath" a namespace. Such names will be hidden by any names actually defined or injected into the actual namespace scope. NOTE: The names are not public members of the namespace. But they're not private members either, they're not members at all. Open makes names available for use in a namespace without making them members for export. 0041: stmt := "use" sname "=" squalified_name ";" Open a single name to a namespace bound to the given qualified name. 0045: stmt := "use" squalified_name ";" A short form for opening a single name as the base part of a qualified name. 0056: stmt := "module" sdeclname "=" ? scompound Define a module. DEPRECATED. Use classes instead. 0063: stmt := "open" "module" sdeclname "=" ? scompound Define a module and open in it in the current scope. DEPRECATED: Use classes instead. 0080: stmt := "class" sdeclname "=" ? scompound Define a class. A class is a collection of constants, variables, types, functions, and other entities. A polymorphic class may contain virtual functions, which are functions which can be defined later for particular types. This is equivalent to a specialisation of a template in C++. NOTE: polymorphic classes may not contain variables. Only variables of non-polymorphic classes can be instantiated. 0086: stmt := "open" "class" sdeclname "=" ? scompound Define a class and open it. 0103: stmt := "instance" stvarlist squalified_name "=" ? scompound Define an instance of a class. This is a specialisation of the class which may contain overrides of virtual functions for a subset of the possible types. Instances can be defined in any class scope (including and usually at the top level of the program). Members of instances which are not overrides are private to the instance. 0121: stmt := "with" sstatements "do" sstatements "done" Provide a set of definitions in the with block which are available in the do block but are lost thereafter. Effectively these definitions are private to the do block. The with block is basically an anonymous class which is opened in the do block. Example: var x = 42; with var x = 1 do var y = x; done println$ x; // prints 42 not 1
patterns.flxh

0008:  syntax patterns
Pattern matching.
Pattern matching is a way to "take apart" a value according
to its structure.
Matches operate "inside out".
0012:    stmt:= "match" sexpr "with" stmt_matching+ "endmatch" ";"
Pattern match statement.
At least one branch must match or the program aborts with a match failure.
0018:    stmt:= "match" sexpr "with" stmt_matching+ "otherwise" stmt+
Short form pattern match statement with
implicit handling of trailing wildcard
by following statements.
0035:    stmt_matching := "|" spattern "=>" stmt+
A single branch of a pattern match statement.
The match argument expression is compared to the pattern.
If it matches any contained pattern variables are assigned
the values in the corresponding possition of the expression,
and the statements are executed.
0038:    satom := pattern_match "endmatch"
Pattern match expression with terminator.
0043:    pattern_match := "match" sexpr "with" smatching+
Pattern match expression without terminator.
Match the expression against each of the branches in the matchings.
At least one branch must match or the program aborts with a match failure.
0051:    smatching := "|" spattern "=>" x[let_pri]
The match argument expression is compared to the pattern.
If it matches any contained pattern variables are assigned
the values in the corresponding possition of the expression,
and expression is evaluated and becomes the return value
of the whole match.
0054:    smatching := "|" "=>" sexpr
Match nothing.
0062:    spattern := sas_pattern "when" sexpr
Match with guard.
The LHS pattern is match first.
Then the RHS guard expression is evaluated,
in a context which includes any extracted match variables.
If the guard is true, the whole pattern matches,
otherwise the matching fails.
0063:    spattern := sas_pattern
0068:    sas_pattern := scons_pattern "as" sname
Match with naming of subexpression.
Matches the pattern against the corresponding subexpression,
and gives it a name.
0069:    sas_pattern := scons_pattern
0074:    scons_pattern := stuple_cons_pattern "!" scons_pattern
Match a non-empty list.
The LHS is the head of the list and the RHS is the tail.
Does not match the empty list.
0076:    scons_pattern := stuple_cons_pattern
0081:    stuple_cons_pattern := stuple_pattern ",," stuple_cons_pattern
Match a tuple of at least 3 elements.
The LHS is the first element of the tuple.
The RHS is the rest of the tuple.
0083:    stuple_cons_pattern := stuple_pattern
0086:    stuple_pattern := scoercive_pattern ("," scoercive_pattern )*
Match a tuple with 2 or more components.
0092:    scoercive_pattern := sapplicative_pattern "|>" x[sarrow_pri]
Match a value with a coercion.
The subexpression corresponding to the LHS is compared.
If it matches the result is coerced to the RHS type expression.
0094:    scoercive_pattern := sapplicative_pattern
0100:    sapplicative_pattern := sctor_name sargument_pattern
Match a non-constant sum type constructor
that is, one with an argument.
The LHS name must match the constructor used to make the value.
The RHS pattern is matched against the argument it was constructed with.
0103:    sargument_pattern := satomic_pattern
0104:    sargument_pattern := "?" sname
0105:    sargument_pattern := "#" sctor_name
0106:    sargument_pattern := "case" sinteger
0108:    sargument_pattern := sname
0111:    sapplicative_pattern := satomic_pattern
0112:    sapplicative_pattern := "?" sname
0113:    sapplicative_pattern := "#" sctor_name
0114:    sapplicative_pattern := "case" sinteger
0116:    sapplicative_pattern := sctor_name
0119:    sctor_name := sname
The sum type constructor can either be a qualified name...
0122:    sctor_name := "case" sinteger
or it can be a case literal.
0128:    satomic_pattern := "true"
Match the value true = case 1 of 2.
0131:    satomic_pattern := "false"
Match the value false = case 0 of 2.
0134:    satomic_pattern := "_"
Match anything without naming the subexpression.
0137:    satomic_pattern := "(" spattern ")"
Precedence control.
0140:    satomic_pattern := "(" ")"
Match the unit tuple.
0145:    satomic_pattern :=  "(" spat_assign ("," spat_assign )* ")"
Match a record.
The record must have fields with the given names.
It may have more fields though, these are ignored.
0148:    spat_assign := sname "=" spattern
0155:    satomic_pattern := "$" "(" sexpr ")" Match an arbitrary expression. Equivalent to ?name when name == expr. 0161: satomic_pattern := sliteral Match against any literal value. This includes integers, strings, whatever. The underlying type must support equality operator (==). Usually it would be instance of class Eq. 0167: satomic_pattern := sliteral ".." sliteral Match against a range specified by two literals. The range is inclusive. The underlying type must support less than operator (<). Usually it would be an instance of class Tord. plugins.flxh 0041: syntax plugins 0043: stmt := "static-link-symbol" sname "in" "plugin" sname ";" 0045: stmt := "static-link-plugin" sname ("," sname)* ";" python_grammar.flxh 0001: syntax python_grammar 0002: stmt := "export" "python" "fun" ssuffixed_name "as" sstring ";" regexps.flxh 0006: syntax regexps Syntax for regular definitions. Binds to library class Regdef, which in turn binds to the binding of Google RE2. 0019: stmt := "regdef" sdeclname "=" sregexp[ralt_pri] ";" Regular definition binder. Statement to name a regular expression. The expression may contain names of previously named regular expressions. Defines the LHS symbol as a value of type Regdef::regex. 0027: x[sapplication_pri] := "regexp" "(" sregexp[ralt_pri] ")" Inline regular expression. Can be used anywhere in Felix code. Returns a a value of type Regdef::regex. 0030: sregexp[ralt_pri] := sregexp[>ralt_pri] ("|" sregexp[>ralt_pri])+ Alternatives. 0037: sregexp[rseq_pri] := sregexp[>rseq_pri] (sregexp[>rseq_pri])+ Sequential concatenation. 0046: sregexp[rpostfix_pri] := sregexp[rpostfix_pri] "*" Postfix star (*). Kleene closure: zero or more repetitions. 0052: sregexp[rpostfix_pri] := sregexp[rpostfix_pri] "+" Postfix plus (+). One or more repetitions. 0058: sregexp[rpostfix_pri] := sregexp[rpostfix_pri] "?" Postfix question mark (?). Optional. Zero or one repetitions. 0063: sregexp[ratom_pri] := "(" sregexp[ralt_pri] ")" Parenthesis. Non-capturing group. 0067: sregexp[ratom_pri] := "group" "(" sregexp[ralt_pri] ")" Group psuedo function. Capturing group. 0074: sregexp[ratom_pri] := "charset" String The charset prefix operator. Treat the string as a set of characters, that is, one of the contained characters. 0081: sregexp[ratom_pri] := String The string literal. The given sequence of characters. Any valid Felix string can be used here. 0089: sregexp[ratom_pri] := "perl" "(" sexpr ")" The Perl psuedo function. Treat the argument string expression as a Perl regular expression, with constraints as specified for Google RE2. 0096: sregexp[ratom_pri] := "regex" "(" sexpr ")" The regex psuedo function. Treat the argument Felix expression of type Regdef::regex as a regular expression. 0101: sregexp[ratom_pri] := sname Identifier. Must name a previously defined variable of type Regdef:;regex. For example, the LHS of a regdef binder. requirements.flxh 0042: syntax requirements Syntax to express and provide dependencies. Requirements operate as extensions to the usual usage dependencies, to provide the compiler additional information regarding C/C++ contructions used in bindings. A requirement of a C type is activated if, and only if, that type is used in a program (or plugin). Similarly, a requirement of a function is activated if, and only if, the function is used. An unnamed requirement in a class is activated if any C binding in the class is used. Such bindings also propagate to descendent (contained) classes. A named requirement is activated only if an active requirement requires it. Requirements may have "tag names". When a requirement is required by name, all requirements with that name are activated. Circularities in named requirements are permitted and harmless. Floating insertions (header, body) are emitted in order of writting at fixed places in the generated C++ header and implementation files. Floating insertions can themselves have requirements. WARNING: there are two gotchas! Gotcha 1: requirements on names cannot fail, even if no resource is tagged wih that name. This is because requirements activate the set of resources with the given name, and as usual, a set may be empty. Gotcha 2; Just because you put a requires statement in a class doesn't mean it will be activated. requirements are only triggered by the use of C bindings! Using a Felix entity will not trigger the requirement! 0044: srequires_clause := "requires" srequirements General form of required clause. 0047: srequires_clause := sepsilon An empty requirement is deemed satisfied. 0050: srequirement:= squalified_name A requirement on a requirement defined by name elsewhere. 0054: srequirement := "property" sstring A generic "catch all" requirement or specification of some property named by a string. 0086: srequirement := "package" scode_spec A dependency on an external package with a given name. Also known as a resource abstraction. The package name refers to an entry in an external database usually represented by directory of text files (usually called "config"), each of which usually has extension "fpc". Each file contains a number of fields, which may specify a platform dependent filename for a shared/dynamic link library, static link library, header file, compiler option switch, or other information. The package construction abstracts the platform dependent data required to locate and use a resource. The Felix compiler "flxg" generates a list of required abstract resources. The Felix command line harness "flx" queries the database of resources using the "flx_pkgconfig" tool, and applies the relevant arguments to the relevant steps of the compilation process. This allows fully automatic compilation and execution of Felix programs without the programmer needing to continually worry about build scripts. Instead the system installer is required, once, to provide the resource database. 0094: srequirement := "scanner" scode_spec The scanner requirement applies only to a C type binding. It specifies the name of a C function which the garbage collector can called to search a data structure for pointers. By default, if no scanner is specified for a C type, the type is assumed not to contain any Felix pointers. 0102: srequirement := "finaliser" scode_spec The finaliser requirement applies only to a C type binding. It specifies the name of a C function which the garbage collector can call to finalise an object prior to freeing up the underlying memory. By default, if no finaliser is specifed, the C++ destructor is called. 0109: srequirement := "encoder" scode_spec The encoder requirement applies only to a C type binding. It specifies the name of a C function which can be called to serialise one element of the object. By default, if no encoder is specifed, memcpy is used. 0116: srequirement := "decoder" scode_spec The decoder requirement applies only to a C type binding. It specifies the name of a C function which can be called to deserialise one element of the object. By default, if no decoder is specifed, memcpy is used. 0120: srequirement_atom:= srequirement Requirement expressions. Deprecated. 0123: srequirement_atom:= "(" srequirements ")" Requirement expressions. Deprecated. 0126: srequirement_and:= srequirement_and "and" srequirement_atom Requirement expressions. Deprecated. 0128: srequirement_and:= srequirement_atom 0131: srequirement_or:= srequirement_or "or" srequirement_and Requirement expressions. Deprecated. 0133: srequirement_or:= srequirement_and 0138: srequirements:= srequirements "," srequirement_or Requirement expressions: a comma separated list of requirements specified each one of the requirements applies independently. 0140: srequirements:= srequirement_or 0149: srequirement := "body" scode_spec The body requirement is a floating requirement that specifies that the given code string be inserted into the output "near the top" of the generated C++ body (cpp) file. It can be used to emit utiliy functions written in C. 0159: srequirement := "header" scode_spec The header requirement is a floating requirement that specifies that the given code string be inserted into the output "near the top" of the generated C++ header (hpp) file. It is typically used to emit a "#include" directive so that the requiring binding has relevant types and functions available. 0167: scode_spec := sstring A Felix string used as a code specification is treated as a template with special coding internally which can be replaced. This feature supports the fact that Felix code insertions can be polymorphic. 0171: scode_spec := scstring A c-string like c"xxxx" is emitted literally without any substitutions. 0176: scode_spec := "ident" This is a special code to make specific that a binding is an identity which can be optimised away. 0181: stmt := "requires" srequirements ";" The anonymous requires statement specifies requirements which propagates to all C bindings in the same class, or any descendant (enclosed) class. 0185: stmt := sname "requires" srequirements ";" The named requires statement simply names a requirement. 0191: stmt := "header" scode_spec srequires_clause ";" The header statement specifies a header requirement which propagates to all C bindings in the same class, or any descendant (enclosed) class. 0197: stmt := "body" scode_spec srequires_clause ";" The body statement specifies a header requirement which propagates to all C bindings in the same class, or any descendant (enclosed) class. 0201: stmt := "header" sdeclname "=" scode_spec srequires_clause ";" Named header requirement. 0207: stmt := "body" sdeclname "=" scode_spec srequires_clause ";" Named body requirement. save.flxh statements.flxh 0003: syntax statements A grab bag of miscellaneous statements and nonterminals used to construct other statements. 0007: stmt := "comment" sstring ";" A comment statement based on a string argument. 0011: stmt := "private" stmt Statement qualifier which makes a definition private to the containing module or class. 0014: stmt := "publish" sstring stmt Deprecated method of documenting a definition. 0017: stmt := ";" An empty statement. 0027: stmt := "include" sstring ";" Include file directive. This is similar to C's pre-processor include except that the file is parsed and macro processed first, entirely independently of the including file, and then the resulting AST is inserted into the current AST. Thus the included file also has no influence on the including file either: the two files are parsed entirely independently. 0032: sdeclname := sname stvarlist A declarative name consists of an identifier and an (optional) type variable specification. 0045: stmt := stype_qual* "type" sdeclname "=" "new" sexpr ";" A way to contruct a new abstract type out of an existing type. Only two operations are available on this new type: _repr_ t: exposes the underlying type make_t : constructs the type from the underlying type. These operations are only available in the class or module containing the new type definition. This allows the private details of the type to be accessed so as to define operations on it, inside the same space as the definition, but leaves the type abstract externally. 0053: stypeclass_constraint_list := stypeclass_constraint ("," stypeclass_constraint )* Type constraint syntax. Type constraints are ways to constrain possible types which type variables may take on. 0056: stypeclass_constraint := squalified_name 0060: stypeclass_constraint := stypeexpr "is" sname Allow T is Real to mean Real[T]. 0064: stype_constraint := "with" stypeclass_constraint_list A constraint specifying types require an instance of a particular type class. 0067: stype_constraint := "where" sexpr A predicative or equational constraint. 0070: stype_constraint := "with" stypeclass_constraint_list "where" sexpr Both types of constraint together. 0074: stype_constraint := "where" sexpr "with" stypeclass_constraint_list Both types of constraint together. 0078: stype_constraint := sepsilon The constraint is empty if the polymorphism is parametric. 0081: seqorin:= "=" stypeexpr Individual type variable equational constraint. 0084: seqorin:= "in" stypeexpr Individual type variable membership constraint. 0087: seqorin:= sepsilon No constraint! 0090: stvar := sname seqorin A type variable, possibly with an individual constraint. 0094: stvar := sname ":" stypeexpr seqorin A type variable with an individual constraint. This is usually the same as a predicate. 0097: stvar_comma_list := stvar ("," stvar)* A list of type variables with optional individual constraints. 0098: stvar_comma_list := sepsilon 0104: stvarlist:= sepsilon A type variable specification consists of a possibly empty list of type variables with individual constraints, plus an optional type constraint relating the specified variables. 0105: stvarlist:= "[" stvar_comma_list stype_constraint "]" 0108: stypeparameter:= sname ":" x[sarrow_pri] 0109: stypeparameter:= sname 0110: stypeparameter_comma_list := sepsilon 0111: stypeparameter_comma_list := stypeparameter ("," stypeparameter)* 0113: stypefun_arg := sname 0114: stypefun_arg := "(" stypeparameter_comma_list ")" 0115: stypefun_args := stypefun_arg+ 0121: stodo := "todo" sstring ";" The todo no-op is primarily a way to document unfinished code. Currently no action is taken. Felix reserves the right to throw an exception, or emit some diagnostics in future versions. 0122: stodo := "todo" ";" 0128: scompound := "{" sstatements "}" Compound construction. Note his is NOT a statement. A compound followed by a semi-colon ";" is, however. 0132: sname_suffix:= "," sname sname_suffix A suffixed name. Used to name an overloaded function. 0133: sname_suffix:= "," sname texsyms.flxh 0010: syntax texsyms This file contains a huge set of operators from TeX, AMSTeX and LaTeX. The precedence classification is currently very crude. Some operators are duplicate semantics with different names. Some are negations, and should be handled properly. Nouns such as Greek letters are not included because they're atoms and don't need any parsing. 0014: bin := "\amalg" 0015: cmp := "\approx" 0016: cmp := "\approxeq" 0017: cmp := "\Arrowvert" 0018: cmp := "\arrowvert" 0019: cmp := "\asymp" 0023: cmp := "\backsim" 0024: cmp := "\backsimeq" 0025: cmp := "\bar" 0026: cmp := "\barwedge" 0027: cmp := "\between" 0028: bin := "\bigcap" 0029: bin := "\bigcirc" 0030: bin := "\bigcup" 0031: bin := "\bigodot" 0032: bin := "\bigoplus" 0033: bin := "\bigotimes" 0034: bin := "\bigsqcup" 0035: bin := "\bigtriangledown" 0036: bin := "\bigtriangleup" 0037: bin := "\biguplus" 0038: bin := "\bigvee" 0039: bin := "\bigwedge" 0040: bin := "\bowtie" 0041: bin := "\Box" 0042: bin := "\boxdot" 0043: bin := "\boxminus" 0044: bin := "\boxplus" 0045: bin := "\boxtimes" 0046: cmp := "\Bumpeq" 0047: cmp := "\bumpeq" 0051: bin := "\cap" 0052: bin := "\Cap" 0053: bin := "\cdot" 0054: bin := "\cdotp" 0055: cmp := "\circeq" 0056: bin := "\circledast" 0057: bin := "\circledcirc" 0058: bin := "\circleddash" 0059: cmp := "\cong" 0060: bin := "\coprod" 0062: bin := "\Cup" 0063: cmp := "\curlyeqprec" 0064: cmp := "\curlyeqsucc" 0065: bin := "\curlyvee" 0066: bin := "\curlywedge" 0070: arr := "\dashleftarrow" 0071: arr := "\dashrightarrow" 0072: bin := "\divideontimes" 0073: cmp := "\doteq" 0074: cmp := "\Doteq" 0075: cmp := "\doteqdot" 0076: bin := "\dotplus" 0077: bin := "\doublebarwedge" 0078: bin := "\doublecap" 0079: bin := "\doublecup" 0080: bin := "\Downarrow" 0081: bin := "\downarrow" 0082: bin := "\downdownarrows" 0083: bin := "\downharpoonleft" 0084: bin := "\downharpoonright" 0088: cmp := "\eqcirc" 0089: cmp := "\eqsim" 0090: cmp := "\eqslantgtr" 0091: cmp := "\eqslantless" 0092: cmp := "\equiv" 0096: bin := "\fallingdotseq" 0100: cmp := "\ge" 0101: cmp := "\geq" 0102: cmp := "\geqq" 0103: cmp := "\geqslant" 0104: arr := "\gets" 0105: cmp := "\gg" 0106: cmp := "\ggg" 0107: cmp := "\gggtr" 0108: cmp := "\gnapprox" 0109: cmp := "\gneq" 0110: cmp := "\gneqq" 0111: cmp := "\gnsim" 0112: cmp := "\gt" 0113: cmp := "\gtrapprox" 0114: cmp := "\gtrdot" 0115: cmp := "\gtreqless" 0116: cmp := "\gtreqqless" 0117: cmp := "\gtrless" 0118: cmp := "\gtrsim" 0119: cmp := "\gvertneqq" 0123: arr := "\hookleftarrow" 0124: arr := "\hookrightarrow" 0128: bin := "\iff" 0129: bin := "\impliedby" 0135: bin := "\Join" 0141: cmp := "\le" 0142: arr := "\leadsto" 0143: arr := "\Leftarrow" 0144: arr := "\leftarrow" 0145: arr := "\leftarrowtail" 0146: arr := "\leftharpoondown" 0147: arr := "\leftharpoonup" 0148: arr := "\leftleftarrows" 0149: arr := "\Leftrightarrow" 0150: arr := "\leftrightarrow" 0151: cmp := "\leftrightarrows" 0152: cmp := "\leftrightharpoons" 0153: arr := "\leftrightsquigarrow" 0154: cmp := "\leq" 0155: cmp := "\leqq" 0156: cmp := "\leqslant" 0157: cmp := "\lessapprox" 0158: cmp := "\lessdot" 0159: cmp := "\lesseqgtr" 0160: cmp := "\lesseqqgtr" 0161: cmp := "\lessgtr" 0162: cmp := "\lesssim" 0163: arr := "\Lleftarrow" 0164: cmp := "\lll" 0165: cmp := "\llless" 0166: cmp := "\lnapprox" 0167: cmp := "\lneq" 0168: cmp := "\lneqq" 0169: cmp := "\lnot" 0170: cmp := "\lnsim" 0171: arr := "\Longleftarrow" 0172: arr := "\longleftarrow" 0173: arr := "\Longleftrightarrow" 0174: arr := "\longleftrightarrow" 0175: arr := "\longmapsto" 0176: arr := "\Longrightarrow" 0177: arr := "\longrightarrow" 0178: cmp := "\lt" 0179: cmp := "\ltimes" 0180: cmp := "\lvertneqq" 0184: arr := "\mapsto" 0188: cmp := "\ncong" 0189: cmp := "\ne" 0190: cmp := "\neq" 0191: cmp := "\ngeq" 0192: cmp := "\ngeqq" 0193: cmp := "\ngeqslant" 0194: cmp := "\ngtr" 0195: cmp := "\ni" 0196: cmp := "\nleq" 0197: cmp := "\nleqq" 0198: cmp := "\nleqslant" 0199: cmp := "\nless" 0200: cmp := "\notin" 0201: cmp := "\nparallel" 0202: cmp := "\nprec" 0203: cmp := "\npreceq" 0204: cmp := "\nsim" 0205: cmp := "\nsubseteq" 0206: cmp := "\nsubseteqq" 0207: cmp := "\nsucc" 0208: cmp := "\nsucceq" 0209: cmp := "\nsupseteq" 0210: cmp := "\nsupseteqq" 0211: cmp := "\ntriangleleft" 0212: cmp := "\ntrianglelefteq" 0213: cmp := "\ntriangleright" 0214: cmp := "\ntrianglerighteq" 0218: bin := "\odot" 0219: bin := "\ominus" 0220: bin := "\oplus" 0221: bin := "\oslash" 0222: bin := "\otimes" 0223: cmp := "\owns" 0227: cmp := "\perp" 0228: bin := "\pm" 0229: cmp := "\prec" 0230: cmp := "\precapprox" 0231: cmp := "\preccurlyeq" 0232: cmp := "\preceq" 0233: cmp := "\precnapprox" 0234: cmp := "\precneqq" 0235: cmp := "\precnsim" 0236: cmp := "\precsim" 0237: bin := "\prod" 0238: cmp := "\propto" 0244: cmp := "\rhd" 0245: arr := "\Rightarrow" 0246: arr := "\rightarrow" 0247: arr := "\rightarrowtail" 0248: arr := "\rightharpoondown" 0249: arr := "\rightharpoonup" 0250: arr := "\rightleftarrows" 0251: arr := "\rightleftharpoons" 0252: arr := "\rightleftharpoons" 0253: arr := "\rightrightarrows" 0254: arr := "\rightsquigarrow" 0255: arr := "\Rrightarrow" 0256: cmp := "\rtimes" 0260: bin := "\setminus" 0261: cmp := "\sim" 0262: cmp := "\simeq" 0263: cmp := "\smallsetminus" 0264: bin := "\sqcap" 0265: bin := "\sqcup" 0266: cmp := "\sqsubset" 0267: cmp := "\sqsubseteq" 0268: cmp := "\sqsupset" 0269: cmp := "\sqsupseteq" 0270: bin := "\square" 0271: cmp := "\subset" 0272: cmp := "\Subset" 0273: cmp := "\subseteq" 0274: cmp := "\subseteqq" 0275: cmp := "\subsetneq" 0276: cmp := "\subsetneqq" 0277: cmp := "\succ" 0278: cmp := "\succapprox" 0279: cmp := "\succcurlyeq" 0280: cmp := "\succeq" 0281: cmp := "\succnapprox" 0282: cmp := "\succneqq" 0283: cmp := "\succnsim" 0284: cmp := "\succsim" 0285: cmp := "\supset" 0286: cmp := "\Supset" 0287: cmp := "\supseteq" 0288: cmp := "\supseteqq" 0289: cmp := "\supsetneq" 0290: cmp := "\supsetneqq" 0294: cmp := "\thickapprox" 0295: cmp := "\thicksim" 0296: cmp := "\times" 0297: arr := "\to" 0298: bin := "\triangle" 0299: bin := "\triangledown" 0300: cmp := "\triangleleft" 0301: cmp := "\trianglelefteq" 0302: cmp := "\triangleq" 0303: cmp := "\triangleright" 0304: cmp := "\trianglerighteq" 0305: arr := "\twoheadleftarrow" 0306: arr := "\twoheadrightarrow" 0310: cmp := "\unlhd" 0311: cmp := "\unrhd" 0312: bin := "\Uparrow" 0313: bin := "\uparrow" 0314: bin := "\Updownarrow" 0315: bin := "\updownarrow" 0316: bin := "\upharpoonleft" 0317: bin := "\upharpoonright" 0318: bin := "\uplus" 0319: bin := "\upuparrows" 0323: cmp := "\varsubsetneq" 0324: cmp := "\varsubsetneqq" 0325: cmp := "\varsupsetneq" 0326: cmp := "\varsupsetneqq" 0327: bin := "\vee" 0328: cmp := "\veebar" 0332: bin := "\wedge" 0336: arr := "\xleftarrow" 0337: arr := "\xrightarrow" 0356: x[scomparison_pri]:= x[>scomparison_pri] bin x[>scomparison_pri] 0357: x[scomparison_pri]:= x[>scomparison_pri] cmp x[>scomparison_pri] 0360: x[stex_implies_condition_pri] := x[>stex_implies_condition_pri] "\implies" x[>stex_implies_condition_pri] 0361: x[stex_or_condition_pri] := x[>stex_or_condition_pri] ( "\lor" x[>stex_or_condition_pri])+ 0362: x[stex_and_condition_pri] := x[>stex_and_condition_pri] ( "\land" x[>stex_and_condition_pri])+ 0363: x[stex_not_condition_pri] := "\lnot" x[stex_not_condition_pri] 0368: x[ssetunion_pri] := x[ssetunion_pri] "\cup" x[>ssetunion_pri] 0369: x[ssetintersection_pri] := x[ssetintersection_pri] "\cap" x[>ssetintersection_pri] 0372: x[sarrow_pri] := x[scase_literal_pri] arr x[sarrow_pri] 0375: satom := "\lceil" sexpr "\rceil" 0376: satom := "\lfloor" sexpr "\rfloor" type_decls.flxh 0065: syntax type_decls Stuff for defining types. Felix type expressions use the same syntax as value expressions. 0068: satom := stypematch 0071: stmt := "typedef" sdeclname "=" sexpr ";" Typedef creates an alias for a type. 0079: stmt := "typedef" "fun" sdeclname stypefun_args ":" stypeexpr "=>" sexpr ";" Typedef fun create a type function or functor. It maps some types to another type. This is the simple expression form. 0087: stmt := "typedef" "fun" sdeclname ":" stypeexpr "=" stype_matching+ ";" Typedef fun create a type function or functor. It maps some types to another type. This is the simple matching form. 0101: stype_matching := "|" sexpr "=>" sexpr 0108: stypematch := "typematch" sexpr "with" stype_matching+ "endmatch" A typematch expression computes a type based on a pattern match. The matching process never rejects a type variable which mighht later match after substitution. It also never accepts a match which might later fail to match after substitution. 0132: sexport := "export" A struct is a nominally type product type similar to a C struct. A struct may be polymorphic. Felix generates a constructor for the struct from a tuple of the types of the fields of te struct, in the order they're written. The syntax allows functions and procedures to be included in a struct, however these are not non-static members. Rather they global functions with an additional argument prefixed of the struct type (for a fun) or pointer to the struct type (for a proc). In such functinos the special identifier "self" must be used to refer to the struct. For example: struct X { a : int; fun f(b: int) => self.a + b; } println$ X 1 . f 2;
// f is equivalent to
fun f (self:X) (b:int) => self.a + b;
0133:    sexport := sepsilon
0134:    stmt := sexport "struct" sdeclname "=" ? "{" sstruct_mem_decl * "}"
0189:    sstruct_mem_decl := stypeexpr sname ";"
0190:    sstruct_mem_decl := sname ":" stypeexpr ";"
0191:    sstruct_mem_decl := sfunction
0200:    stmt := "cstruct" sdeclname "=" ? "{" sstruct_mem_decl * "}" srequires_clause ";"
A ctruct provides a model of a C structure.
This is the same as a struct except the structure is not emitted.
CAVEAT: A C struct constructor should not be used
unless the cstruct definition is a complete model of the C struct.
0205:    stmt := "typedef" "struct" "{" sstruct_mem_decl * "}" sdeclname srequires_clause ";"
A hack to help with cut and paste from C headers into Felix
0210:    stmt := "typedef" "struct" sdeclname "{" sstruct_mem_decl * "}" sdeclname srequires_clause ";"
A hack to help with cut and paste from C headers into Felix
0214:    sopt_name := sname
0215:    sopt_name := sepsilon
0231:    stmt := "union" sdeclname "=" stype_sum_items2 ";"
A union is a model of a discriminated union or variant.
Such unions have a discriminant tag that determines
at run time which component is populated.
The only way to access the union field is by using a
match which automatically enforces proper access.
The fields of a union are called type constructors.
A constant type constructor has no arguments.
A non-constant type constructor has an argument
which can be extracted in a match.

Unions provide a safe way to "unify" heterogenous data
into a single data type.
0237:    stmt := "union" sdeclname "{" stype_sum_item1* "}"
Deprecated C like syntax for unionx.
0242:    stmt := senum_decl
0247:    stmt := "enum" sdeclname "{" senum_items "}"
Short for for declaring an enumeration,
which is a union all of whose fields are constant constructors.
Deprecated syntax.
0254:    stmt := "enum" sdeclname "=" senum_items ";"
Short for for declaring an enumeration,
which is a union all of whose fields are constant constructors.
0259:    sopt_value := "=" sinteger
0260:    sopt_value := sepsilon
0261:    senum_item := sname sopt_value
0262:    senum_items := senum_item "," senum_items
0263:    senum_items := senum_item
0264:    senum_items := sepsilon
0268:    stmt := "interface" sdeclname stype_extension "{" srecord_type "}"
Java like interface of an object type.
Equivalent to a record type.
0272:    srecord_type := srecord_mem_decl (";" srecord_mem_decl)* ";"
0274:    stypelist := stypeexpr ("," stypeexpr)*
0275:    stype_extension := "extends" stypelist
0276:    stype_extension := sepsilon
variables.flxh

0002:  syntax variables
General variable binders.
0009:    stmt := "val" sname sname_suffix "=" sexpr ";"
Value binder: multi declaration. Like:

val x,y,z = 1,2,3;
0038:    stmt := "val" sdeclname "=" sexpr ";"
Value binder, single.
0044:    stmt := "val" sdeclname ":" stypeexpr "=" sexpr ";"
Value binder, single, with type.
0050:    stmt := "ref" sdeclname "<-" sexpr ";"
Reference binder.
0056:    stmt := "ref" sdeclname ":" stypeexpr "<-" sexpr ";"
Reference binder with type.
0064:    stmt := "fun" sdeclname "<-" sexpr ";"
Fun binder, for lazy evaluation.
A function with no arguments.
Uttering the name of the function calls it.
0070:    stmt := "fun" sdeclname ":" stypeexpr "<-" sexpr ";"
Fun binder with type.
0076:    stmt := "var" sname sname_suffix "=" sexpr ";"
Variable binder, multiple.
0105:    stmt := "var" sdeclname "=" sexpr ";"
Variable binder, single.
0111:    stmt := "var" sdeclname ":" stypeexpr "=" sexpr ";"
Variable binder, single, with type.
0117:    stmt := "var" sdeclname ":" stypeexpr ";"
Variable binder, single, with type, no explicit initialiser.