According to MOSTflexiPL's basic philosophy, the language does not provide any predefined syntax for comments, but rather allows the user to individually define his own preferred syntax(es), e. g.:
"/*" ... "*/"; /* Define C style block comments. */ "//" ...; // Define C++ and Java style line comments. print /* /* // comment */ 10 // comment // /*Generally speaking, the predefined infix operator
•...•
(the three dots have to be written literally)
defines comments
surrounded by the begin and end strings denoted by its operands.
In contrast,
the predefined postfix operator •...
defines comments starting with the begin string denoted by its operand
and ending before the next line break.
As the example illustrates,
a comment started by a specific begin string
ends at the first occurence of the corresponding end string
or the next line break, respectively,
which implies that comments of the same kind cannot be nested.
However,
by defining different kinds of comments,
arbitrary nesting is basically possible,
as the example also demonstrates.
Therefore,
the last line of the example without any comments
simply contains print 10
.
The predefined nullary operator read
reads a line from the standard input stream
and returns it (without the final line terminator) as a string
,
e. g.:
print "Please enter your name:"; "name" := read; print "Hello, " ++ name ++ "!"If EOF is reached before any character has been read,
read
returns nil.
To convert a string read that way to an int
or float
value,
one of the predefined conversion operators can be applied,
e. g.:
print "Please enter an integer:"; "s" := read; "n" := int s; print "The number is " ++ nGenerally speaking, an expression
T x
consisting of some type T
and some value x
of some other type S
yields x
converted to T
,
if a suitable conversion operator conv•
is available.
More specifically,
T x
is an application
of the following predefined generic “cast” operator:
[ "T" : type; "S" : type; "x" : S; ["x" : S] "conv" x : T {} ] T x : T { conv x }This operator is a bit unusual, because its signature does not contain any names, but only operands. (Therefore, the operator is called “anonymous.”) Furthermore, the operator has an implicit parameter
conv•
with a parameter of type S
and result type T
,
which is used to actually perform the type conversion from S
to T
.
According to the general rules for implicit parameters,
an application T x
of the cast operator is correct,
if and only if a matching conv•
operator
is visible at the point of application.
To support standard type conversions,
the following conv•
operators are predefined
with rather obvious meanings:
["x" : string] "conv" x : int { ...... }; ["x" : int] "conv" x : string { ...... }; ["x" : string] "conv" x : float { ...... }; ["x" : float] "conv" x : string { ...... }; ["x" : int] "conv" x : float { ...... }; ["x" : float] "conv" x : int { ...... }; ["x" : char] "conv" x : int { ...... }; ["x" : int] "conv" x : char { ...... }; ["T" : type; "x" : T] "conv" x : T { x }The conversion from
char
to int
and vice versa
allows to obtain a character's position in the Unicode character set
and vice versa.
The conversion in the last line
supports trivial conversions from any type T
to itself.
Because these operators conv•
are heavily overloaded,
with some variants differing only in their result types,
direct applications such as conv 10
would be ambiguous.
Applications of the cast operator, however,
automatically select the appropriate variant
according to the source and target type of the cast.
Of course,
a user is free to define additional conv•
operators,
e. g., to convert persons to strings:
["p" : Person] "conv" p : string { p.name }Afterwards, the expression
string p
would be correct
for every subexpression p
having type Person
.
These conversion operators are used in two different places as well,
quite similar to Java's toString
method:
First,
the predefined operator print•
accepts operands x
of any type T
,
if a conv•
operator with parameter type T
and result type string
is available,
and in fact prints x
converted to string
,
followed by a line terminator.
Thus,
print p
would also be correct for any person p
,
if the above conv•
operator is visible,
and would actually print the person's name.
Similarly,
the concatenation operator •++•
already mentioned in “Sequences”
also accepts operands of arbitray types S
and T
,
if conv•
operators with parameter types S
resp. T
and result type string
are available,
and in fact converts its operands to strings
before actually concatenating them.