The approach to achieve complete syntactic extensibility in MOSTflexiPL can be summarized by the formula: Everything is an expression, i. e., the application of an operator to subexpressions. However, the notion of operators used here is much more general than usual: Operators can have any number of names (or operator symbols), and they can be applied to any number of operands. This apparently rather small generalization of operators allows to subsume all relevant programming language constructs under this general notion. In fact, constants, variables, functions, control structures, type constructors, and even declaration forms simply become different kinds of operators. If it is now possible to freely define new operators, all aspects of the language become in fact extensible. This shall be illustrated with a number of examples.
MOSTflexiPL provides predefined operators for basic arithmetic,
e. g., −2 * 3 + 4
,
but it is quite easy to define new prefix, infix, and postfix operators
such as ^
and !
to denote, for example,
exponentiation and factorial.
Furthermore,
it is possible to define their associativity
and precedence with respect to other operators
and then use them in expressions such as −2 ^ 3 ^ 4!
just like predefined ones.
Because operators might have any number of names and operands,
the substring syntax s[3..7]
mentioned in “Background and Motivation”
can also be defined as an operator with three names
(bracket, dot-dot, and closing bracket)
that is applied to a string and two integer operands.
Its definition in MOSTflexiPL
is just as easy as the definition of a function in other languages.
Even the parentheses (•)
,
which are almost always a very special, predefined language construct,
are a simple (generic) operator with two names
(opening and closing parenthesis) and an operand in between
(indicated by the bullet sign).
Its definition in MOSTflexiPL is a simple one-liner.
Control structures such as if • then • else • end
also become operators,
whose names correspond to keywords in other languages.
Again,
a few basic control structures are predefined in MOSTflexiPL,
but the user can freely define new ones,
for example the remove statement
also mentioned in “Background and Motivation”.
What about the syntax of types?
If operators are allowed to operate on types
and in particular to return types,
then type constructors can also be defined as operators.
For example,
the array type int [10]
results from applying the operator •[•]
to the type int
and the integer value 10
.
Because a user can freely define new operators,
he could define an operator •{•x•}
that is applied to a type and two integer values
and returns a corresponding matrix type,
e. g., float{3x4}
.
So,
even the syntax of types can be extended and customized in an arbitrary way.
Finally,
even declaration forms turn out to be operators.
For example,
a Pascal-style variable declaration such as "x" : int
is the application of an infix colon operator to a name and a type.
Generally speaking,
even the syntax that is used to define new operators
is provided by means of operators.
For example,
the predefined operator [•]•:•{•}
defines new operators when being applied to appropriate operands,
e. g.,
["n" : int] n "!" : int { if n <= 1 then 1 else (n-1)! * n end }
to define a postfix factorial operator.
If the syntax of the predefined declaration operators is undesired,
one can basically define new operators that map to the predefined ones,
e. g., with • define • : • begin • end
.
By that means,
it is even possible to extend or change the syntax
that is used to define new syntax.