A MAL instruction has purposely a simple format. It is syntactically represented by an assignment, where an expression (function call) delivers results to multiple target variables. The assignment patterns recognized are illustrated below.
(t1,..,t32) := module.fcn(a1,..,a32); t1 := module.fcn(a1,..,a32); t1 := v1 operator v2; t1 := literal; (t1,..,tn) := (a1,..,an);
Operators are grouped into user defined modules. Omission of the module name is interpreted as the user module.
Simple binary arithmetic operations are merely provided as a short-hand, e.g. the expression t:=2+2 is converted directly into t:= calc.+(2,2).
Target variables are optional. The compiler introduces internal variables to hold the result of the expression upon need. They won't show up when you list the MAL program unless they are being used elsewhere.
Each instruction should fit on a single line, which makes it easy for the parser to recover upon encountering a syntax error. Comments start with a sharp '#' and continues to the end of the line. They are retained in the internal code representation to ease debugging of compiler generated MAL programs.
The data structure to represent a MAL block is kept simple. It contains a sequence of MAL statements and a symbol table. The MAL instruction record is a code byte string overlaid with the instruction pattern, which contains references into the symbol tables and administrative data for the interpreter. This method leads to a large allocated block, which can be easily freed. Variable- and statement- block together describe the static part of a MAL procedure. It carries enough information to produce a listing and to aid symbolic debugging.
The complete MAL syntax can be found here.