Overview

The language has no type declarations or type annotations; all types are inferred by a Hindley-Milner-style type inference engine that is part of the type checker. Unlike Standard ML, the language incorporates Ohori-style record polymorphism. This means that, for example, the following function addab can subsequently be applied to any record argument as long as it has immutable integer fields a and b:

fun addab r = r.a + r.b
in
  addab { a = 5, b = 7, c = "hello" } -
  addab { b = 23, a = 0 } *
  addab { z = 1, a = 22, y = 15, b = -1, x = 4 }

Syntax

Notice that this grammar, as written, is highly ambiguous.

WARNING This syntax is out-of-date.

 program   -> functions * mainfun
 functions -> fun fundecl (and fundecl)*
 fundecl   -> name formals = exp
 formals   -> varpat | ( [varpat (, varpat)*] )
 varpat    -> _ | name
 exp       -> let varpat = exp in exp
            | functions in exp
            | if exp then exp else exp
            | case exp of match
            | exp with recordexp
            | exp where recordexp
            | exp binconn exp
            | exp exp
            | unaryop exp
            | exp . label
            | exp ! label
            | exp ! label := exp
            | name
            | true 
            | false 
            | integer 
            | string
            | ( )
            | ( exp )
            | ( exp , exp (, exp)* )
            | ( exp ; exp (; exp)* )
            | [ (exp [, exp]*) ]
            | recordexp
 match     -> nilcase | conscase
            | conscase | nilcase
 nilcase   -> [ ] => exp
 conscase  -> varpat :: varpat => exp
 binconn   -> boolconn | cmpop | arithop | ::
 boolconn  -> andalso | orelse
 cmpop     -> == | > | >= | <> | < | <=
 arithop   -> + | - | * | / | %
 unaryop   -> - | isnull | hd | tl | not
 label     -> name | integer
 recordexp -> { [fieldexp (, fieldexp)*] }
 fieldexp  -> name = exp | name := exp
 mainfun   -> fun main ( varpat , varpat ) = exp
 name      -> . . .
 integer   -> . . .
 string    -> ". . . ”

Expressions

literal data

MLPolyR programs can use the following constants:

  • boolean - true, false
  • numerical - integer
  • string
  • unit ( )— the record/tuple with no fields
  • lists [ . . . ]
  • records { . . . }
  • tuples ( . . . )

identifiers

Identifiers (name) in MLPolyR name values, not locations. They are not mutable. The only form of assignment is update of mutable record fields.

binary operations

In general, binary operations have the form e1 op e2 where op is one of:

  • short-circuiting logical or: orelse — boolean arguments and results
  • short-circuiting logical and: andalso — boolean arguments and results
  • comparisons: == <> < > <= >= — integer operands, boolean result
  • list cons: ::— element and list operands, list result
  • addition and subtraction: + - — integer operands and result
  • multiplication and division: * / % — integer operands and result

These operators are listed in order of increasing precedence.

unary operations

There are five unary operations:

  • boolean negation: not e— boolean argument, boolean result
  • arithmetic negation: - e— integer argument, integer result
  • empty list test: isnull e— list argument, boolean result
  • list head: hd e— list argument, element result
  • list tail: tl e— list argument, list result

conditional expression

An if expression evaluates its boolean condition and depending on the outcome proceeds to evaluate either the then branch or the else branch. The expression that is not needed does not get evaluated. Notice that e1 andalso e2 and e1 orelse e2 are equivalent to if e1 then e2 else false and if e1 then true else e2, respectively.

Built-in functions

MLPolyR programs are compiled in a global environment containing a binding for the following record value:

val String : { toInt     : string -> int,
               fromInt   : int -> string,
               inputLine : () -> string,
               size      : string -> int,
               output    : string -> (),
               sub       : string * int -> int,
               concat    : string list -> string,
               substring : string * int * int -> string,
               compare   : string * string -> int }

The elements of this record can be used to perform simple I/O tasks and string manipulation.