@Chapter
    @Title { Expressions }
    @Tag { expressions }
@Begin
@BeginSections

@Section
    @Title { Overview }
    @Tag { expressions.overview }
@Begin
@LP
An @I expression is a sequence of @I { factors }, which can be
expression @Index { Expression }
factor @Index { Factor }
evaluated alone to produce a value, optionally decorated by
@I { factor prefixes } and @I { factor suffixes } which operate
on the value produced by their factor to produce a new value,
and joined to neighbouring factors by @I { infix operators }:
@ID @OneRow @SyntaxDiag title { expr } { @StartRight
    @Loop
	A { @Sequence
	      A { @Loop A { @Skip } B { @ACell factor_prefix } }
	      B { @ACell factor }
	      C { @Loop A { @Skip } B { @ACell factor_suffix } }
	  }
	B { @ACell infix_op }
}
Factor suffixes have the highest precedence, followed by factor
prefixes and then infix operators.  The grouping of infix operators
depends on associativity and precedence information given when the
operators are defined (Section {@NumberOf functions.operators}).  The
syntax of factors is
@ID @OneRow @SyntaxDiag title { factor } { @StartRight @Select
    A { @ACell literal }
    B { @BCell self }
    C { @ACell paren_expr }
    D { @ACell list_expr }
    E { @ACell array_expr }
    F { @ACell call_expr }
    G { @ACell builtin_expr }
    H { @ACell let_expr }
    I { @ACell if_expr }
    J { @ACell case_expr }
}
This chapter has one section for each of these alternative kinds of
factor, followed by sections on factor prefixes, factor suffixes,
and operators.
@End @Section

@Section
    @Title { Literals }
    @Tag { expressions.literals }
@Begin
@LP
The simplest factors are @I { literals } -- constant values of
literal @Index { Literal }
integral, @Nonpareil { bool }, @Nonpareil { real }, @Nonpareil { char },
or @Nonpareil { string } type:
@ID @Nonpareil { false   16   3.1416   'a'   "A string" }
Their syntax may be found in Section {@NumberOf lexical.literals}.
@PP
Number literals have no initial optional minus sign, but the unary minus
prefix operators from the @Nonpareil { real } and integral classes can be
applied to get a negative number which looks like a literal and can be
used wherever a literal can be.  This is how C handles this potentially
ambiguous situation.
@PP
The type of a number literal is taken to be @Nonpareil { real } if
number.literal @Index { Number literal }
@F { . }, @F { e }, or @F { E } is present.  Otherwise it has an
unsigned integral type (Appendix {@NumberOf standard.integral}):
@Nonpareil { ubyte } if its value is at most @Nonpareil { ubyte!max_ubyte },
@Nonpareil { ushort } if its value is at most
@Nonpareil { ushort!max_ushort }, and @Nonpareil { uint } otherwise.
Coercions map from these types to their signed and wider versions
(Appendix {@NumberOf standard.integral}), so an integral type error
should occur only if the value is too large for the intended type.
@End @Section

@Section
    @Title { Self }
    @Tag { expressions.self }
@Begin
@LP
The reserved word @Nonpareil { self } denotes the current object.  It may be
self @Index { @Nonpareil { self } reserved word }
used only within noncreation features (in their parameter default values
and preconditions as well as bodies) and invariants.
@End @Section

@Section
    @Title { Parenthesized expressions and manifest tuples }
    @Tag { expressions.paren }
@Begin
@LP
The @I { parenthesized expression } covers two cases:
parenthesized.expressions @Index { Parenthesized expression }
@ID @OneRow @SyntaxDiag title { paren_expr } { @StartRight @Sequence
    A { @CCell @Nonpareil { ( } }
    B { @Loop
	   A { @ACell expr }
	   B { @CCell @Nonpareil { , } }
      }
    C { @CCell @Nonpareil { ) } }
}
If there is just one expression between the parentheses, it denotes a
parenthesized expression.  If there are two or more, it denotes a tuple
tuple @Index { Tuple }
object creation call.  For example, the expression
@ID @Nonpareil { (x, y, sqrt(x*x + y*y)) }
means
@Nonpareil { triple(x, y, sqrt(x*x + y*y)) }.
Nonpareil does not have empty or one-element tuples.
@End @Section

@Section
    @Title { Manifest lists and arrays }
    @Tag { expressions.lists }
@Begin
@LP
@I { List expressions } and @I { array expressions } denote lists and
list.expression @Index { List expression }
"[" @Index @Nonpareil { [ }
"]" @Index @Nonpareil { ] }
array.expression @Index { Array expression }
"[|" @Index @Nonpareil { [| }
"|]" @Index @Nonpareil { |] }
arrays of zero or more elements:
@ID @Tbl
    mv { 0i }
    aformat { @Cell A | @Cell B }
{
@Rowa
    A { @SyntaxDiag title { list_expr } { @StartRight @Sequence
	A { @CCell @Nonpareil { [ } }
	B { @Optional @Loop
	       A { @ACell expr }
	       B { @CCell @Nonpareil { , } }
	  }
	C { @CCell @Nonpareil { ] } }
      } }
    B { @SyntaxDiag title { array_expr } { @StartRight @Sequence
	A { @CCell @Nonpareil { [| } }
	B { @Optional @Loop
	       A { @ACell expr }
	       B { @CCell @Nonpareil { , } }
	  }
	C { @CCell @Nonpareil { |] } }
      } }
}
A list expression is a shorthand for ordinary object creation.
For example,
@ID @Nonpareil { [x, y, sqrt(x*x + y*y)] }
is shorthand for
@Nonpareil { nlist(x, nlist(y, nlist(sqrt(x*x + y*y), elist))) }.
However, @OneCol @Nonpareil { [| ... |] } is the only way to
get a manifest array.  These delimiters have been adopted from
OCaml @Cite { $leroy2001 }.
ocaml @Index { OCaml language }
@End @Section

@Section
    @Title { Call expressions }
    @Tag { expressions.call }
@Begin
@LP
The @Nonpareil { call expression } has syntax
call.expression @Index { Call expression }
@CD @OneRow @SyntaxDiag title { call_expr } { @StartRight @OneOrBoth
    A { @Sequence
	  A { @ACell ordinary_name }
	  B { @Optional @ACell actual_generics }
      }
    B { @Sequence
	  A { @Select
	        A { @CCell @Nonpareil { ! } }
		B { @CCell @Nonpareil { !! } }
	    }
	  B { @ACell name }
	  C { @Optional @ACell actual_generics }
      }
}
It covers two cases.  When there is no @Nonpareil { ! } or
@Nonpareil { !! } symbol, it
denotes a function call with optional actual generic parameters but
no ordinary actual parameters (these appear as factor suffixes
in Section {@NumberOf expressions.suffixes }).  The call could be
an object creation call, for example:
@ID @Nonpareil { nlist{int}(5, elist) }
Some ordinary actual parameters have been added for the
sake of familiarity.  Without them, @Nonpareil { nlist{int} } is
a function which when given two parameters will return an
@Nonpareil { nlist{int} } object, and hence is perfectly able to
stand alone.  Alternatively, the call could be a call on a feature
of the current class, or a parameter or let variable.
@PP
When @Nonpareil { ! } (or its variant form @Nonpareil { !! }, for
"!" @Index @Nonpareil { ! }
"!!" @Index @Nonpareil { !! }
which see below) appears, the part before the @Nonpareil { ! } must
denote a class instantiation (if empty, the current class is assumed),
and the part after it must be a feature of that class.  No object is
created or referenced, however.  Instead, the result is the feature
with the usually implicit self parameter not curried and instead
explicit in the feature's type.  Alternatively, if the feature referred
to is a predefined object (Section {@NumberOf classes.predefined}) there
is no implicit self parameter either.  Either way, this is called an
an @I { unclassed function }.
unclassed.function @Index { Unclassed function }
@PP
A good way to think of @Nonpareil { ! } is as a variant of the
@Nonpareil { . } symbol that usually introduces feature calls.
For example, the conventional expression
@ID @Nonpareil { nlist{int}(5, elist).head }
has type @Nonpareil { int } and value 5.  Deleting the
actual parameters and replacing @Nonpareil { . } by @Nonpareil { ! }
produces this:
@ID @Nonpareil { nlist{int}!head }
This expression is an unclassed function of type
@Nonpareil { fun1{nlist{int}, int} }.  The function takes a non-empty
list of integers and returns the first element of that list.  A more
typical example is
@ID @Nonpareil { mylist.fold(int!+, 0) }
which passes the unclassed addition function from @Nonpareil { int },
of type @OneCol @Nonpareil { fun2{int, int, int} }, for use in
folding the elements of list @Nonpareil { mylist }.
@PP
Another application of unclassed functions is to call
features of parent classes that have been redefined so would
otherwise be inaccessible.  One simply names the parent class,
followed by @Nonpareil { ! }, the parent feature, and its parameters,
the first of which would in this application be @Nonpareil { self }.
@PP
The symbol @Nonpareil { ! } gives access to all features except
punctuation sequence prefix operators.  Its variant form,
@Nonpareil { !! }, gives access only to punctuation sequence prefix
operators.  For example, supposing the @Nonpareil { int } class to
contain both an infix operator @Nonpareil { - } and a prefix
operator @Nonpareil { - }, one would use @Nonpareil { int!- } to
gain access to the infix operator, and @Nonpareil { int!!- } to gain
access to the prefix operator.  These rules apply irrespective of
whether the operator name happens to occur in both forms or not.
@End @Section

@Section
    @Title { Builtin expressions }
    @Tag { expressions.builtin }
@Begin
@LP
The @I { builtin expression } has syntax
builtin.expression @Index { Builtin expression }
@ID @OneRow @SyntaxDiag title { builtin_expr } { @StartRight @Sequence
    A { @BCell @Nonpareil { builtin } }
    B { @ACell @Nonpareil { string_literal } }
    C { @Optional @ACell { actual_generics } }
    D { @Optional @Sequence
	  A { @CCell @Nonpareil { ( } }
	  B { @Loop
	         A { @ACell expr }
		 B { @CCell @Nonpareil { , } }
	    }
	  C { @CCell @Nonpareil { ) } }
      }
}
It denotes an expression which cannot be written in Nonpareil and instead
will be inserted by the compiler.  For example, the @Nonpareil { + }
operator in the @Nonpareil { int } class is defined like this:
@ID @Nonpareil { infix +(other: int): int := builtin "int_add"(self, other) }
The syntax is similar to a call expression, except that all the actual
parameters must be given and there are no named or optional parameters.
@PP
There is a fixed set of builtin expressions known to the compiler, each
with a particular number of parameters and a type, and identified by the
string following @Nonpareil { builtin }.  In principle these can be used
anywhere, but since they have all been packaged into the core libraries
in functions which are inlined for efficiency, end users have nothing
to gain by invoking builtin expressions directly.
@End @Section

@Section
    @Title { Let expressions }
    @Tag { expressions.let }
@Begin
@LP
The let expression allows temporary values to be given names, as an
let.expression @Index { Let expression }
aid to writing long expressions.  For example,
@ID @OneRow @Nonpareil {
let
  sqrt_disc := sqrt(b*b - 4*a*c)
  root1 := (-b + sqrt_disc)/(2*a)
  root2 := (-b - sqrt_disc)/(2*a)
in
  (root1, root2)
end
}
defines temporary values @Nonpareil { sqrt_disc }, @Nonpareil { root1 },
and @Nonpareil { root2 }.  This is both more efficient (since
@Nonpareil { sqrt_disc } is used twice) and easier to read than
the alternative.
@PP
The syntax of let expressions is
let @Index { @Nonpareil { let } reserved word }
in @Index { @Nonpareil { in } reserved word }
end @Index { @Nonpareil { end } reserved word }
@ID @OneRow @SyntaxDiag title { let_expr } { @StartRight
  @Sequence
    A { @BCell @Nonpareil { let } }
    B { @Optional @Repeat @ACell function }
    C { @BCell @Nonpareil { in } }
    D { @ACell expr }
    E { @BCell @Nonpareil { end } }
}
The value of the whole expression is the value of the expression
after @Nonpareil { in }, within which the functions (Chapter {@NumberOf
functions}) after @Nonpareil { let } may be used.  Each let function must
have a body.  The result type may be omitted, in which case it is taken
from the body, unless the function is recursive, in which case the result
type cannot be determined automatically and must be given explicitly.
@PP
The name of a function defined in a let expression is visible from
the point where it appears to the concluding @Nonpareil { end } of the
let expression.  It may thus be used by itself and by later functions
within the same let expression, but not by earlier ones.
@FootNote {
The compiler is currently unable to handle a let definition with
parameters that contains both a call to itself and a reference to a
local variable (parameter, downcast variable, or let definition without
parameters) defined outside the let definition, where the first recursive
call precedes the first reference to the variable.  The problem is that
the signature of the let definition has to be changed behind the
scenes to include a parameter representing the local variable, but
the change occurs too late for the recursive call.  In such cases the
compiler recognizes the problem and prints an error message suggesting
that the code be simplified.
}
@End @Section

@Section
    @Title { If expressions and downcasting }
    @Tag { expressions.if }
@Begin
@LP
@I If expressions are used to produce alternative values depending on
if.expression @Index { If expression }
conditions.  For example,
@ID @OneRow @Nonpareil {
if discriminant < 0 then
    no_roots
elsif discriminant = 0 then
    one_root(-b/(2*a))
else
    let
        sqrt_disc := sqrt(b*b - 4*a*c)
        root1 := (-b + sqrt_disc)/(2*a)
        root2 := (-b - sqrt_disc)/(2*a)
    in
        two_roots(root1, root2)
    end
end
}
returns @Nonpareil { no_roots } if @Nonpareil { discriminant < 0 }, or
else @Nonpareil { one_root(-b/(2*a)) } if
@OneCol @Nonpareil { discriminant = 0 }, or finally
@OneCol @Nonpareil { two_roots(root1, root2) } otherwise.  The
alternative results must all have the same type, or at least be subtypes
of some common type.  It is not obvious that this is the case in the
above example, but presumably the three classes @Nonpareil { no_roots },
@Nonpareil { one_root }, and @Nonpareil { two_roots } have a common ancestor.
@PP
The syntax of if expressions is
if @Index { @Nonpareil { if } reserved word }
then @Index { @Nonpareil { then } reserved word }
elsif @Index { @Nonpareil { elsif } reserved word }
else @Index { @Nonpareil { else } reserved word }
end @Index { @Nonpareil { end } reserved word }
@ID @OneRow @SyntaxDiag title { if_expr } { @StartRight
    @Sequence
	A { @BCell @Nonpareil { if } }
	B { @Loop
	      A { @Sequence
		   A { @ACell expr }
		   B { @Optional @ACell { downcast_clause } }
		   C { @BCell @Nonpareil { then } }
		   D { @ACell expr }
		}
	      B { @BCell @Nonpareil { elsif } }
	  }
	C { @BCell @Nonpareil { else } }
	D { @ACell expr }
	E { @BCell @Nonpareil { end } }
}
The expressions after @Nonpareil { if } and @Nonpareil { elsif }
are evaluated sequentially until one has result @Nonpareil { true }, at
which point the expression following the matching @Nonpareil { then } is
evaluated, and its value is the value of the whole expression.  If none
of the tested expressions produce @Nonpareil { true }, then the expression
after @Nonpareil { else } (which is compulsory) is evaluated and its value
is the value of the whole expression.
@PP
Although the syntax does not say so, the expression after
@Nonpareil { else } may not be an @Nonpareil { if } expression.  This
prohibition allows the Nonpareil compiler to spot the common error of
using @OneCol @Nonpareil { else if } where @Nonpareil { elsif } was
intended; without it, this error would have a very mystifying effect.
@PP
The if expression includes Nonpareil's downcasting syntax:
downcasting @Index { Downcasting }
@ID @OneRow @SyntaxDiag title { downcast_clause } { @StartRight
    @Sequence
	A { @BCell @Nonpareil { is } }
	B { @Optional @Sequence
	      A { @ACell name_def }
	      B { @CCell @Nonpareil { : } }
	  }
	C { @ACell type }
}
When @Nonpareil { is } appears, the value of the preceding test
is @Index { @Nonpareil { is } reserved word }
expression is checked to see whether its dynamic type is equal to
(not is a subtype of) the type following @Nonpareil { is }.  If it
is equal, then the expression after the following @Nonpareil { then }
is the result of the @Nonpareil { if }.  Within that expression, the
defined name, if given, is visible and has value equal to the value
of the test expression, but with type equal to the given type -- it
contains the downcast value.
@End @Section

@Section
    @Title { Case expressions }
    @Tag { expressions.case }
@Begin
@LP
The @I { case expression } is a relative of the if expression in which
case.expression @Index { Case expression }
there are typically many branches, each to be taken if the value
of a given expression has a particular value:
@ID @OneRow 0.8vx @Break @Nonpareil {
case month

    when september, april, june, november yield 30

    when february yield if leap_year then 29 else 28 end

    else 31

end
}
The syntax of the @Nonpareil { case } expression is
case @Index { @Nonpareil { case } reserved word }
when @Index { @Nonpareil { when } reserved word }
yield @Index { @Nonpareil { yield } reserved word }
else @Index { @Nonpareil { else } reserved word }
end @Index { @Nonpareil { end } reserved word }
".." @Index  @Nonpareil { .. }
@IndentedList

@LI @OneRow @SyntaxDiag title { case_expr } { @StartRight
	@Sequence
	      A { @BCell @Nonpareil { case } }
	      B { @ACell expr }
	      C { @Loop
		    A { @Skip }
                    B { @ACell case_item }
		}
	      D { @Optional @Sequence
		  A { @BCell @Nonpareil { else } }
		  B { @ACell expr }
	        }
	      E { @BCell @Nonpareil { end } }
}

@LI @OneRow @SyntaxDiag title { case_item } { @StartRight
   @Sequence
      A { @BCell @Nonpareil { when } }
      B { @Loop
	    A { @Sequence
		     A { @ACell expr }
		     B { @Optional @Sequence
			   A { @CCell @Nonpareil { .. } }
			   B { @ACell expr }
		       }
	      }
	    B { @CCell @Nonpareil { , } }
        }
      C { @BCell @Nonpareil { yield } }
      D { @ACell expr }
}

@EndList
The expression following @Nonpareil { case } is evaluated, and its
value compared with each of the values (or ranges of values) following
@Nonpareil { when }.  The type of the case labels must be equal to the
type of the test expression, which must itself be an enumerated type
(including @Nonpareil { bool } and @Nonpareil { char }), @Nonpareil { int },
or @Nonpareil { string }.  The case label expressions must be simple
enough for their values to be determined at compile time, and these
values must not overlap.
@PP
If the test expression is equal to any of these values, or lies in one
of the ranges of values, the expression after the corresponding
@Nonpareil { yield } is evaluated and its value is the result
of the whole expression.  Otherwise, the expression following
@Nonpareil { else } is used.  The @Nonpareil { else } clause may only be
omitted when the previous alternatives handle every possible value of
the type of the test expression.
@PP
Case expressions whose test expressions have type @Nonpareil { string }
are useful for defining constant symbol tables.  Although ranges of
@Nonpareil { string } values are allowed, there are reasons for not
using them:  they are interpreted according to lexicographical ordering,
which is not the same as culturally expected ordering; and their presence
prevents the implementation from using a hash table, which it prefers
unless there are only a few cases @Cite { $kingston2005np.implementation }.
@End @Section

@Section
    @Title { Factor prefixes:  prefix operators and anonymous functions }
    @Tag { expressions.prefixes }
@Begin
@LP
As previously defined in Section {@NumberOf expressions.overview}, an
expression is a sequence of factors, optionally decorated by factor
prefixes and factor suffixes, and joined to neighbouring factors by
infix operators:
@ID @OneRow @SyntaxDiag title { expr } { @StartRight
    @Loop
	A { @Sequence
	      A { @Loop A { @Skip } B { @ACell factor_prefix } }
	      B { @ACell factor }
	      C { @Loop A { @Skip } B { @ACell factor_suffix } }
	  }
	B { @ACell infix_op }
}
A @I { factor prefix } is a prefix operator call
factor.prefix @Index { Factor prefix }
prefix.operator.call @Index { Prefix operator call }
require @Index { @Nonpareil { require } reserved word }
fun @Index { @Nonpareil { fun } reserved word }
end @Index { @Nonpareil { end } reserved word }
(Section {@NumberOf expressions.operators}) or anonymous function:
@CD @OneRow @SyntaxDiag title { factor_prefix } { @StartRight @Select
    A { @ACell prefix_op }
    B { @Sequence
           A { @BCell fun }
	   C { @Optional @ACell parameters }
	   D { @Optional @Sequence
	          A { @CCell @Nonpareil { : } }
	          B { @ACell type }
	     }
	   E { @Optional @Sequence
	          A { @BCell @Nonpareil { require } }
	          B { @Loop A { @Skip } B { @ACell expr } }
	          C { @BCell @Nonpareil { end } }
	     }
           F { @CCell @Nonpareil { := } }
      }
}
All factor prefixes have lower precedence than all factor suffixes, but
higher precedence than all infix operators, so the influence of a factor
prefix extends over the following factor prefixes, the factor, and
its factor suffixes.
@PP
The anonymous function syntax is almost the same as for ordinary
anonymous.function @Index { Anonymous function }
functions (Chapter {@NumberOf functions}), and the meaning is the same
here as it is there.  There are three syntactic differences:  the function
name(s) are replaced by the @Nonpareil { fun } reserved word; there are no
generic parameters (because Nonpareil cannot pass a generic function
as a value); and the (compulsory) body is omitted from the syntax here,
since it is supplied by the expression under the influence of the function.
It is always safe to omit the result type; if this is done, the type of
the body of the function will be used as the result type.
@End @Section

@Section
    @Title { Factor suffixes:  postfix operators, feature calls, and
function applications }
    @Tag { expressions.suffixes }
@Begin
@LP
A @I { factor suffix } is a postfix operator call
factor.suffix @Index { Factor suffix }
postfix.operator.call @Index { Postfix operator call }
(Section {@NumberOf expressions.operators}), feature call with optional
actual generic parameters, or function application whose actual parameters
may optionally be named:
@IndentedList

@LI @OneRow @SyntaxDiag title { factor_suffix } { @StartRight
      @Select
            A { @ACell postfix_op }
	    B { @Sequence 
		  A { @CCell @Nonpareil { . } }
		  B { @Sequence
			 A { @ACell ordinary_name }
			 B { @Optional @ACell actual_generics }
		    }
	      }
	    C { @ACell parameters }
}

@LI @OneRow @SyntaxDiag title { parameters } { @StartRight
      @Sequence
	A { @CCell @Nonpareil { ( } }
	B { @Loop
	      A { @Sequence
		    A { @Optional @Sequence
			  A { @ACell name }
			  B { @CCell @Nonpareil { := } }
		      }
		    B { @ACell expr }
		}
	      B { @CCell @Nonpareil { , } }
	  }
	C { @CCell @Nonpareil { ) } }
}

@EndList
See Chapter {@NumberOf functions} for further information
about function calls and named actual parameters.
@End @Section

@Section
    @Title { Operator calls }
    @Tag { expressions.operators }
@Begin
@LP
Prefix, postfix, and infix operator calls all have the
operator.calls @Index { Operator call }
same syntax, one which allows operators to have actual generic
parameters and actual optional parameters, like other functions:
@ID @OneRow @SyntaxDiag title { prefix_op, postfix_op, infix_op }
{ @StartRight
    @Sequence
        A { @ACell operator_name }
        B { @Optional @ACell actual_generics }
        C { @Optional @Sequence
	        A { @CCell @Nonpareil { ( } }
		B { @Loop
			A { @Sequence
			      A { @ACell name }
			      B { @CCell @Nonpareil { := } }
			      C { @ACell expr }
			  }
			B { @CCell @Nonpareil { , } }
		  }
	        C { @CCell @Nonpareil { ) } }
          }
}
Of course, they differ in the presence of positional actual parameters
to the left and right of this syntax.  These parts of the operator calls
were shown in earlier syntax diagrams.
@PP
If the parser finds a parenthesis after an operator and any actual
generic parameters, it cannot tell immediately whether it is the
beginning of the following factor or function application, or the
beginning of a list of assignments to the optional parameters of
the operator.  It chooses the latter interpretation if the left
parenthesis is followed by a name and then a @Nonpareil { := } token.
@End @Section

@EndSections
@End @Chapter
