Expressions

An expression is evaluated to produce a value. The expressions have the following forms.

x

An identifier is an expression, assuming it occurs in a context where that identifier is defined. It stands for the value that the identifier names. So x is the thing named by x.

true
false

These reserved words stand for boolean values.

1234

Integer constants are written in standard decimal notation. There is no sign. (You can get a negative result from an expression, just not from a constant.)

'a'
'\n'

These are character constants. The only special characters are '\n' (newline) and '\\' (backslash).

A == B

Expression A == B has value true if A and B have the same value, and false if A and B have different values.

A < B

Expression A < B has value true if the value of A is strictly less than the value of B, and false otherwise.

A > B

Expression A > B is equivalent to expression B < A. (Note that there are no <= or >= operators.)

A + B

A + B produces the sum of the values of A and B. It is required that expressions A and B produce integers.

AB

AB produces the difference of the values of A and B. It is required that expressions A and B produce integers.

A * B

A * B produces the product of the values of A and B. It is required that expressions A and B produce integers.

A / B

A / B produces the integer quotient of the values of A and B. For example, expresssion 5/3 has value 1. It is required that expressions A and B produce integers.

( A )

Expression (A) has the same meaning as expression A.

[A, B, C]

Any sequence of zero or more expressions separated by commas and surrounded by [...] is an expression whose value is a list of the values of the expressions listed.

There can be any number of expressions in the list, including none. For example, expression [2+3, 8+4] has value [5,12]. Expression

head A

Expression head A produces the head of list A. (The head is the first value in the list. Computing the head of anything that is not a nonempty list is an error.)

tail A

Expression tail A produces the tail of list A. (The tail is the result of removing the head. For example, the tail of [2,4,6] is [4,6], and the tail of [3] is [ ]. Computing the tail of anything that is not a nonempty list is an error.)

isNull A

Expression isNull A produces true if A is [ ], and false otherwise.

A : B

A : B produces a list L such that head(L) is the value of expression A, and tail(L) is the value of expression B. For example, expression 2:[4,6] has value [2,4,6].

[A,B,C] is has the same meaning as ((A):(B):(C):[ ]).

isList A

Expression isList A produces true if A is a list (either [ ] or something created using the : operator), and false otherwise.

isInt A

Expression isInt A produces true if A is an integer, and false otherwise.

isBool A

Expression isBool A produces true if A is a boolean value (true or false), and false otherwise.

isChar A

Expression isChar A produces true if A is a character value, and false otherwise.

isFunction A

Expression isFunction A produces true if A is a function, and false otherwise.

isAction A

Expression isAction A produces true if A is an action.

case C1 => E1 | C2 => E2 | ... | else => En+1 end

Expression

  case 
      C1 => E1
    | C2 => E2
    | … 
    | Cn => En
    | else => En+1
  end
is evaluated by testing conditions C1, ..., Cn in the order written.

The else phrase is required. There must be at least one condition, not counting the else phrase.

A or B

A or B is equivalent to case A => true | else => B end.

A and B

A and B is equivalent to case A => B | else => false end.

not A

not A is equivalent to case A => false | else => true end.

A B

If A and B are expressions, then A B is an expression. Since you just write two expressions next to one another, this is called juxtaposition.

The value of A must be a function. If the value of A is function f, and the value of B is value v, then evaluating A B produces the value f (v), the result of applying function f  to value v.

Notice that the function is not required to be an identifier. It can be any expression whose value is a function.

x -> A

The value of expression x -> A is a function f  defined by f (x) = A.

The left-hand side of -> is required to be an identifier, and that identifier can be used in expression A.

let x = A in B end

If x is an identifier and A and B are expressions then expression

  let x = A in 
    B 
  end
has the value of expression B, but while B is evaluated, identifier x names the value of expression A.

Expression let x = A in B end has the same value as expression

  ((x -> B) A)

readChar
readInt
produce A
print A
printList A

Each of these expressions produces an action. (A is another expression.)

Note that they do not perform an action. Rather, they have an action as their value. There is more detail about these later.

A ~> B

This is used with actions. Expression A should produce an action, and B should produce a function that produces an action as its result.

When performed (by the interpreter), an action can produce an answer (as do readChar and readInt). This expression builds a new action that:

  1. performs action A, getting result r;
  2. computes new action b = B(r);
  3. performs action b.

The result of action b is used as the result of expression A ~> B.

A ; B

This is equivalent to

  A ~> (x -> B)
where x is a new name, not used anywhere else. It just does action A then does action B, ignoring the result of A, and producing the same answer as B.


Precedence and associativity

Ambiguity is resolved by the following precedence and associativity rules. The table lists operators from high precedence to low precedence, with an associativity for each. Left associativity means that the operation is done from left to right. Right associativity means that the operation is done from right to left.

Operator Associativity
head, tail, isBool, isChar, isFunction, isAction, isInt, isList, isNull, print, printList, produce n/a
juxtaposition left
*, / left
+, − left
: right
==, <, > none (x == y == z is not allowed)
and left
or left
-> right
;, ~> left