Block | |||
::= | { (Statement ;)* Expression } | ||
| | { } | ||
Statement | |||
::= | Expression | ||
| | Binding | ||
Binding | |||
::= | let Patterns = Expression | ||
| | fun ValueId FunDef (and ValueId FunDef)* |
Expression | |||
::= | if Expression then Expression else Expression |
TryExpression | |||
::= | try Expression except MatchCase | ||
| | try Expression finally Expression |
|
{ val s = TextIO.openIn "somefile"; try someFunction (s) finally TextIO.closeIn s }To illustract how try-finally and try-except expressions are unwound, consider the following example:
try { try { try { try { try raise BAR finally ConsoleIO.print "1"; ConsoleIO.print "a" } finally ConsoleIO.print "2"; ConsoleIO.print "b" } except { BAR => ConsoleIO.print "3" }; ConsoleIO.print "c" } finally ConsoleIO.print "4"; ConsoleIO.print "d" } except { _ => ConsoleIO.print "5" }This will print ``123c4d.'' But if we change the second finally clause to raise the exception BAZ as follows:
try { try { try { try { try raise BAR finally ConsoleIO.print "1"; ConsoleIO.print "a" } finally {ConsoleIO.print "2"; raise BAZ}; ConsoleIO.print "b" } except { BAR => ConsoleIO.print "3" }; ConsoleIO.print "c" } finally ConsoleIO.print "4"; ConsoleIO.print "d" } except { _ => ConsoleIO.print "5" }then the expression will print ``1245.'' Note that in both examples, the finally clauses always execute.
If we have some form of thread finalization, then the finally clauses should be executed when a thread is finalized. Also when a thread is alerted.
Expression | |||
::= | raise Expression |
|
Expression | |||
::= | spawn Expression |
Expression | |||
::= | sync Expression |
Table 11.1: Moby infix and prefix operators
Infix operators
:= assignment operator (lowest precedence) || conditional or operator && conditional and operator == != equality operators <= < >= > relational operators @ : list operators (right associativity) << >> >>> bitwise shift operators | bitwise or operator & bitwise and operator + - additive operators * / % multiplicative operators ** exponentiation ^ function composition (highest precedence)
AssignmentExpr | |||
::= | ConditionalOrExpr := ConditionalOrExpr | ||
| | ConditionalOrExpr |
ConditionalOrExpr | |||
::= | ConditionalOrExpr || ConditionalAndExpr | ||
| | ConditionalAndExpr | ||
ConditionalAndExpr | |||
::= | ConditionalAndExpr && EqualityExpr | ||
| | EqualityExpr |
e1 || e2 | º | if e1 then True else e2 |
e1 && e2 | º | if e1 then e2 else False |
EqualityExpr | |||
::= | EqualityExpr EqualityOp RelationalExpr | ||
| | RelationalExpr | ||
EqualityOp | |||
::= | == | != |
Bool | Char | String | Int |
Long | Integer | Float | Double |
Extended |
We probably should allow equality of tuples of equality types.
We may want to support equality on monomorphic structured values in the future.
RelationalExpr | |||
::= | RelationalExpr RelationalOp ListExpr | ||
| | ListExpr | ||
RelationalOp | |||
::= | < | <= | >= | > |
ListExpr | |||
::= | ShiftExpr ListOp ListExpr | ||
| | ShiftExpr | ||
ListOp | |||
::= | @ | :: |
ShiftExpr | |||
::= | ShiftExpr ShiftOp BitwiseOrExpr | ||
| | BitwiseOrExpr | ||
ShiftOp | |||
::= | << | >> | >>> | ||
BitwiseOrExpr | |||
::= | BitwiseOrExpr | BitwiseAndExpr | ||
| | BitwiseOrExpr \/ BitwiseAndExpr | ||
| | BitwiseAndExpr | ||
BitwiseAndExpr | |||
::= | BitwiseAndExpr & AdditiveExpr | ||
| | BitwiseAndExpr /\ AdditiveExpr | ||
| | AdditiveExpr |
AdditiveExpr | |||
::= | AdditiveExpr AdditiveOp MultiplicativeExpr | ||
| | MultiplicativeExpr | ||
AdditiveOp | |||
::= | + | - | ||
MultiplicativeExpr | |||
::= | MultiplicativeExpr MultiplicativeOp Expr | ||
| | ExponentialExpr | ||
MultiplicativeOp | |||
::= | * | / | % | ||
ExponentialExpr | |||
::= | ExponentialExpr ** CompositionExpr | ||
| | CompositionExpr |
CompositionExpr | |||
::= | PrefixExpr ^ CompositionExpr | ||
| | PrefixExpr |
|
Another way to think about this is that ^ is overloaded on all combinations of polymorphic functions, where the arities match up correctly.
PrefixExpr | |||
::= | PrefixOp PrefixExpr | ||
| | ApplicationExpr | ||
PrefixOp | |||
::= | * | & | ! | ~ | - |
ApplicationExpr | |||
::= | ApplicationExpr PostfixExpr | ||
| | PostfixExpr |
PostfixExpr | |||
::= | PostfixExpr . Label | ||
| | PostfixExpr [ Expression ] | ||
| | AtomicExpr |
AtomicExpr | |||
::= | fn FunDef | ||
| | case Expression of MatchCase | ||
| | ( (Expression (, Expression)*)opt ) | ||
| | ( Expression : Type ) | ||
| | ( Expression is Pattern ) | ||
| | ( Expression isnot Pattern ) | ||
| | ChoiceEvent | ||
| | Block | ||
| | new Pathopt MakerId | ||
| | self | ||
| | super . Label | ||
| | nack_event | ||
| | rdy_event | ||
| | ( Operator ) | ||
| | Pathopt ValueId | ||
| | DataConstructor | ||
| | # DataConstructor | ||
| | ? DataConstructor | ||
| | Literal |
(e is p) | º | case e of { p => True, _ => False } |
(e isnot p) | º | case e of { p => False, _ => True } |
ChoiceEvent | |||
::= | {| WrappedEvent (, WrappedEvent)* |} | ||
WrappedEvent | |||
::= | Expression | ||
| | Expression \ Pattern => Expression | ||
| | Expression \ MatchCase |