.sh 1 "Expressions and Type Checking"
.sh 2 "Expressions"
.(b
expression  ::=  operand  binary_operator{{+}}   #   (  expression  )
.)b
.(b
operand  ::=  |1literal   #   denotation   #   unary_operator  expression   #
              /1array_constructor   #   record_constructor
.)b
.(b
array_constructor  ::=  (  vector_element  @,@  vector_element  @,@{{+}}  )
.)b
.(b
vector_element  ::=  expression   #   @[@  integer_expression  @]@  expression
.)b
.(b
record_constructor  ::=  import_source{{o}}  record_identifier  (  expression  @,@{{+}}  )
.)b
.(b
import_source  ::=  component_identifier  .
.)b
.pp
Expressions compute values.
They are evaluated in a way that
is consistent with operator precedence and parenthesized
expressions.
Evaluation of boolean expressions is ``short-circuit:''
evaluation stops as soon as the final value of the expression
can be determined.
.pp
Most expressions compute a single value.
Constructors compute lists of values.
An array constructor computes two or more values of the
same type.
A record constructor computes one or more values
of possibly different types.
Expressions in constructors must be values
of the basic types and constructors may not be nested.
Constructors are used in assignments to array or record variables
or to formal parameters.
Elements in an array constructor are assigned to two-dimensional
arrays in row-major order.
.pp
Within array constructors, an integer expression in brackets
may be used to indicate repetition of the following expression;
e.g., @([5] 0)@ is an array of five zeroes.
The repetition expression is evaluated once.
If the count is positive, the following expression is evaluated
and its value is replicated count times.
If the repetition count is zero or negative, no replication occurs
and the following expression is not evaluated.
.pp
Operands within expressions may invoke pre-defined
or user-defined functions (operations that have a @returns@ clause).
The value returned by the invoked operation is
used in the expression as the value of the operand.
.PS L
%Examples:
.sp .5
	me.name
	me.age-10
	"hi" | | " there"
	word & 0FFFF0000X
	(x+y)*z
	(1, 2, [3] 0, 6, 7)
	([N] 0)
	person("olsson", 33)
.PE
.sh 2 "Literals"
.(b
literal  ::=  |1number   #   character   #   string   #   enumeration_literal   #
              /1@true@   #   @false@   #   @null@   #   @noop@
.)b
.lp
Literals directly specify values.
Numbers are unsigned sequences of digits.
Decimal numbers are sequences of 0-9.
Octal numbers are sequences of 0-7 followed by `q' or `Q'.
Hexadecimal numbers are sequences of 0-9, `a'-`f',
or `A'-`F' followed by `x' or `X';
hexadecimal numbers must begin with a digit.
All numbers specify the least-significant
bits of the number; unspecified bits are set to 0.
.pp
Character literals are single ASCII characters
enclosed in single quotes (apostrophes).
Strings are sequences of ASCII characters
enclosed in double quotes.
In addition, character literals and strings
can contain the following special characters:
.(b
.ta .5i,3i,3.5i
\e\|n	newline (NL)      	\e\|a	alert (BEL)
\e\|t	tab (HT)           	\e\|e	escape (ESC)
\e\|b	backspace (BS)     	\e\|v	vertical tab (VT)
\e\|r	return (CR)        	\e\|f	form feed (FF)
\e\|'	single quote       	\e\|"	double quote
\e\|\e\|	backslash
\e\|\fIooo\fP	bit pattern where \fIooo\fP is 1-3 octal digits
\e\|x\fIhh\fP	bit pattern where \fIhh\fP is 1 or 2 hexadecimal digits
\e\|c	character c where c is any other character
.)b
For example, the double quote character can be included
in a string by preceding it by a backslash.
.pp
Enumeration literals are the identifiers introduced
in enumeration definitions.
As noted in Sec. 3.1, these must be unique in any
scope and hence the type of an enumeration literal
is unique.
.pp
The boolean literals are @true@ and @false@.
The capability and file literals are @null@ and @noop@.
The pointer literal is also @null@.
.PS L
%Examples:
.sp .5
	4096
	1333Q
	0abcdefX
	'a'
	'\e'\&'   # single quote character literal
	"i'm getting tired"
	"write two\enlines"
	red    # enum literal
.PE
.sh 2 "Denotations"
.(b
denotation  ::=  object_name  .{{+}}  arguments{{o}}   #   object_name .{{+}}  substring
.)b
.(b
object_name  ::=  identifier  indices{{o}}  @^@{{*}}
.)b
.(b
indices  ::=  |1@[@  expression  @]@   #   @[@  expression  @,@  expression  @]@   #
              /1@[@  expression  @,@  slice  @]@   #   @[@  slice  @,@  expression  @]@
.)b
.(b
slice  ::=  expression  @:@  expression   #   expression  @:@  @*@   #   @*@  @:@  expression
.)b
.(b
arguments  ::=  (  expression  @,@{{*}}  )
.)b
.(b
substring  ::=  @[@  integer_expression  @]@   #   @[@  integer_expression  @:@  integer_expression  @]@
.)b
.lp
Whereas a literal is a value, a denotation names
one or more values or invokes a function that returns
one or more values.
Denotations encompass references to variables and
record fields, and invocation of operations and
pre-defined functions.
As indicated, names can be subscripted to denote
individual elements or slices of subscripted variables,
or elements of arrays of operations.
Names are followed by hats (`@^@') for pointer dereferencing,
and separated by dots (`@.@') for record fields.
.pp
A slice is a vector that is a subset of
another vector, or a subset of either a row or
a column of a matrix.
The elements and size of the slice are determined by the
values of the expressions that delimit the slice.
For example, the elements in @v[i:j]@ are
.PS
v[i], v[i+1], ..., v[j]
.PE
A slice may have zero elements, but not a negative number of elements.
Thus, @j-i+1@ must be at least zero in the above example.
.pp
One of the expressions bounding a slice can be
the special value `@*@'.
In this case, `@*@' is taken to be either the lower or
upper bound of the range from which the slice is taken.
For example, given @a[1:N]@, the slice @a[*:j]@ is
the same as @a[1:j]@.
For vector or matrix formal parameters that have a
declared lower or upper bound of `@*@', the value of
`@*@' in a slice becomes the appropriate value calculated
from the actual parameter.
.pp
Array indices must have the same type as that of the corresponding
range in the declaration of the denoted variable.
They must also have values within the declared range of values.
.pp
A substring is zero or more characters within a string variable.
The index of the lower end of a substring must be at least 1;
the index of the upper end must be no more than the
current length of the string.
A substring is treated as an array of characters,
not a string.
.PS L
%Examples:
.sp .5
	sc.push(15)
	me.name
	list_head^.value
	vector
	vector[1:*]
	vector[5:10]
	boolean_matrix[i,j-1:j+1]
.PE
.sh 2 "Operators"
.lp
SR provides a variety of operators for use in expressions.
The unary operators have the highest precedence.
The other operators are all binary operators, listed below
in \fIdecreasing\fR order of preference.
Note that there are multiple representations for some operators.
.(b
.ta .5i,1i
unary operators
	@-@	integer negation
	@~@	boolean or bit-wise complement (tilde character)
	@not@	boolean or bit-wise complement
	\*C\&@\fR	address of
	@?@	number of pending invocations of indicated operation
.)b
.(b
multiplying operators
	@*@	integer times
	@/@	quotient from integer division
	@%@	remainder from integer division\**
.)b
.(f
\**As long as @b@ is not 0, it is always true
that @(a/b)*b + a%\&b@ is equal to @a@.
Thus if both @a@ and @b@ are positive,
the remainder operator is equivalent to the mathematical modulus operator.
However, if either @a@ or @b@ is negative, the result of @a%\&b@
will be machine dependent since the result of integer division
is machine dependent is this case.
.)f
.(b
adding operators
	@+@	integer or pointer addition
	@-@	integer or pointer subtraction
	@| |@	string concatenation
.)b
.(b
shift operators
	@>>@	shift bits in left operand right by value of right operand
	@<<@	shift bits in left operand left by value of right operand
.)b
.(b
relational operators
	@=@	equal, for ordered types and pointers
	@!=@	not equal, for ordered types and pointers
	@~=@	not equal, for ordered types and pointers
	@>=@	greater than or equal, for ordered types
	@>@	greater than, for ordered types
	@<=@	less than or equal, for ordered types
	@<@	less than, for ordered types
.)b
.(b
AND operators
	@and@	boolean or bit-wise and
	@&@	boolean or bit-wise and
.)b
.(b
OR operators
	@or@	boolean or bit-wise inclusive or 	
	@|@	boolean or bit-wise inclusive or
	@xor@	boolean or bit-wise exclusive or
.)b
.sh 2 "Pre-Defined Functions"
.lp
The following functions are pre-defined.
With the exception of @bool@, @char@, @int@, and @new@, the names of
these functions are not reserved.
Thus, an SR program can declare an object having the same name;
however, this precludes using the pre-defined function
in the scope of the user-declared object.
.(b
.ta 1.5i
@abs(x)@	absolute value of integer x
.)b
.(b
@min(x, ...)@	minimum of arguments, which must be of same ordered type
@max(x, ...)@	maximum of arguments, which must be of same ordered type
.)b
.(b
@low(T)@	smallest value of the ordered type named @T@
@high(T)@	largest value of the ordered type named @T@
@pred(x)@  	predecessor of @x@; defined for ordered types
@succ(x)@  	successor of @x@; defined for ordered types
.)b
.(b
@ub(v)@   	upper bound of vector variable @v@
@ub1(m)@   	upper bound of range 1 of vector or matrix variable @m@
@ub2(m)@ 	upper bound of range 2 of matrix variable @m@
@lb(v)@    	lower bound of vector variable @v@
@lb1(m)@    	lower bound of range 1 of vector or matrix variable @m@
@lb2(m)@    	lower bound of range 2 of matrix variable @m@
@length(s)@	number of characters currently stored in string variable @s@
@maxlength(s)@	maximum number of characters that can be stored in string variable @s@
.)b
.(b
@int(x)@  	convert @x@ to integer; defined for ordered types
@char(x)@  	convert @x@ to character; defined for ordered types
@bool(x)@  	convert @x@ to boolean; defined for ordered types
.)b
.(b
@new(T)@	return pointer to new instance of type identifier or basic type @T@
@free(p)@ 	free object pointed to by pointer @p@
.)b
.(b
@myresource()@	capability for executing resource
@myvm()@    	capability for local virtual machine
@mymachine()@	machine on which currently executing
@locate(x,s,p)@	define machine number @x@ to be the machine named by string @s@;
        	the optional third argument is a pathname that will be used to load
         	the executable program on machine @x@
.)b
.(b
@nap(msec)@	block executing process for @msec@ milliseconds
@age()@  	elapsed time, in milliseconds, since local virtual machine created
.)b
The @locate@ function provides a convenient way to use symbolic names
to specify machine locations; see Appendix 3 for details on running SR programs.
The accuracy of @nap@ and @age@ is dependent upon the granularity
of the host system clock.
.pp
In addition to these pre-defined functions,
one conversion function is implicitly associated with each
user-defined enumeration type.
In particular,
.(b
@enum_identifier(x)@
.)b
converts @x@ to the named enumeration type, assuming @x@ is a value
of an ordered type and the result is within the range of values
of the enumeration type.
Recall that enumeration literals are implicitly numbered from 0 up to one
less than the number of literals of the type.
.sh 2 "Signatures and Type Checking"
.lp
Type checking in SR is based on \fIstructural equivalence\fR.
An object can be assigned to another object provided
they have the same structure.
Two objects have the same structure if they have the same
number of basic elements and corresponding pairs of basic elements
have the same type.
.pp
For example, two records have the same structure if they
have the same number of fields and each corresponding field has
the same structure, independent of field names.
Also, two resources have the same structure if they
export the same number of operations and each
corresponding operation has the same parameter structure
and the same type of return value (if any), independent of the names
of operations, parameters, and return values.
.pp
#Signatures provide the basis for checking whether
two objects have the same structure.
Every expression and variable (including formal parameters) has a signature.
The signature of a single-valued expression or variable
has the form
.(b
@type@
.)b
where @type@ encodes the type of the variable or expression.
The signature of an array or array slice is
.(b
@[size] type@
.)b
where the size field gives the total number of elements,
independent of the number of dimensions or the types of subscripts.
.pp
The signature of an expression is built from the
signatures of each operand according to the
effects of different operators.
For example, the signature of a vector constructor
will be `[size] type' where size is the number
of elements and type is the type of each element.
For a string expression, the signature is `@string(n)@'
where @n@ is the actual length of the string expression;
e.g., the current length of a string variable.
A substring is treated like a slice of a character array
and hence has a signature of the form `@[n] char@'
where @n@ is the number of characters in the substring.
Type conversion (cast) functions such as @int@ are
used to convert an expression with one signature into an expression
with another signature.
.pp
The signature of a composite object\(emsuch as a record,
operation, or resource\(emis a list of the signatures of its components.
In forming record and operation signatures, field and parameter
names are ignored;
only the type structure is encoded.
.pp
An expression can be assigned to a target variable or formal
parameter provided they have compatible signatures.
In constructing the signature of an expression or
target of an assignment, instances of `*' in array
slices are first replaced by the appropriate upper
or lower bound as discussed earlier in Sec. 7.3.;
then the total number of elements is calculated.
(Instances of `*' in formals are not replaced.)
Two signatures are #compatible if both the following requirements are met:
.np
(a) both the expression and target are scalars, or
.br
(b) both are arrays and either
the sizes are the same or the size of the array formal is `*'; and
.np
(a) the types are the same,
.br
(b) the types are @ptr any@ and another pointer type, or
.br
(c) the type of the expression is @string(n)@ and
the type of the target is either @string(*)@ or a string of maximum length @n@.
.lp
In the simplest cases, scalars can be assigned to scalars of
the same type and arrays can be assigned to arrays of
the same size and element type.
In addition, a string expression can be assigned
to a string variable or formal if the maximum length is sufficient, and
an array expression can be assigned to an array formal
if the formal will accept any number of elements.
Also, vectors can be assigned to matrices and vice-versa provided the
vector and matrix have the same size;
in this case the values are assigned in row-major order
(all of the first row, then all of the second, etc.).
.pp
As an example, given
.PS
op foo(f[1:*]: int; s : string(*))
.PE
the invocation
.PS
call foo(a,b)
.PE
is legal for any length integer array @a@ and
any length string @b@.
When the invocation is serviced, the inherited
upper-bound of @f@ can be determined by calling @ub(f)@,
and the inherited maximum length of @s@ can be
determined by calling @maxlength(s)@, which is also
the initial length of @s@.
.pp
Arrays of characters (including substrings) can be
assigned to strings and vice-versa provided
the sizes are compatible.
A string of length @n@ can be assigned
to an array of @n@ characters
and a character array of length @n@ can be assigned
to a string variable having maximum length of at least @n@.
However, arrays of strings are not compatible with arrays of characters.
For example, a vector constructor such as
.PS
([10] "a")
.PE
produces a vector of 10 strings on length one and cannot be assigned
to a 10 element character array.
However,
.PS
([10] 'a')
.PE
produces a vector of 10 characters.
