Felix Syntax
assertions.flxh
0003: syntax assertions
Assertion statements.
See also functions to find pre- and post-conditions.
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
binary read-modify-write operators.
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
Prefix read/modify/write.
0054: spreincrop:= "++"
Pre-increment.
0056: spreincrop:= "--"
Pre-decrement.
0059: sassignexpr := sexpr spostincrop
Postfix read/modify/write.
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
which has external linkage and the link name
given in the "as" phrase.
The function must be identified by a suffixed name
to choose between overloads. Example:
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.
Instead, it is assumed to be already defined in C.
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.