nonterminal ::= alternative ∣ alternative ∣ ... ∣ alternativeThe following extensions are used:
a , ... | a list of one or more as separated by commas: "" or "a" or "a, a" or "a, a, a", etc. |
{ a } | a sequence of zero or more as: "" or "a" or "a a" or "a a a", etc. |
[ a ] | an optional a: "" or "a". |
Nonterminal symbols appear in lightface. Reserved words appear in boldface.
All other terminal symbols are nonalphabetic and appear in lightface:
module | ::= | { equate } procedure |
∣ | { equate } iterator | |
∣ | { equate } cluster | |
procedure | ::= | idn ＝ proc [ parms ] args [ returns ] [ signals ] [ where ] |
routine_body | ||
end idn | ||
iterator | ::= | idn ＝ iter [ parms ] args [ yields ] [ signals ] [ where ] |
routine_body | ||
end idn | ||
cluster | ::= | idn ＝ cluster [ parms ] is idn , ... [ where ] |
cluster_body | ||
end idn | ||
parms | ::= | [ parm , ... ] |
parm | ::= | idn , ... : type ∣ idn , ... : type_spec |
args | ::= | ( [ decl , ... ] ) |
decl | ::= | idn , ... : type_spec |
returns | ::= | returns ( type_spec , ... ) |
yields | ::= | yields ( type_spec , ... ) |
signals | ::= | signals ( exception , ... ) |
exception | ::= | name [ ( type_spec , ... ) ] |
where | ::= | where restriction , ... |
restriction | ::= | idn has oper decl , ... |
∣ | idn in type_set | |
type_set | ::= | { idn ∣ idn has oper decl , ... { equate } } ∣ idn |
oper_decl | ::= | op name , ... : type_spec |
op_name | ::= | name [ [ constant , ... ] ] |
constant | ::= | expression ∣ type_spec |
routine_body | ::= | { equate } |
{ own_var } | ||
{ statement } | ||
cluster_body | ::= | { equate } rep ＝ type_spec { equate } |
{ own_var } | ||
routine { routine } | ||
routine | ::= | procedure ∣ iterator |
equate | ::= | idn ＝ constant ∣ idn ＝ type_set |
own_var | ::= | own decl |
∣ | own idn : type_spec := expression | |
∣ | own decl , ... := invocation | |
type_spec | ::= | null ∣ bool ∣ int ∣ real ∣ char ∣ string ∣ any ∣ rep ∣ cvt |
∣ | array [ type_spec ] ∣ sequence [ type_spec ] | |
∣ | record [ field_spec , ... ] ∣ struct [ field_spec , ... ] | |
∣ | oneof [ field_spec , ... ] ∣ variant [ field_spec , ... ] | |
∣ | proctype ( [ type_spec , ... ] ) [ returns ] [ signals ] | |
∣ | itertype ( [ type_spec , ... ] ) [ yields ] [ signals ] | |
∣ | idn [ constant , ... ] ∣ idn | |
field_spec | ::= | name , ... : type_spec |
statement | ::= | decl |
∣ | idn : type_spec := expression | |
∣ | decl , ... := invocation | |
∣ | idn , ... := invocation | |
∣ | idn , ... := expression , ... | |
∣ | primary . name := expression | |
∣ | primary [ expression ] := expression | |
∣ | invocation | |
∣ | while expression do body end | |
∣ | for [ decl , ... ] in invocation do body end | |
∣ | for [ idn , ... ] in invocation do body end | |
∣ | if expression then body | |
{ elseif expression then body } | ||
[ else body ] | ||
end | ||
∣ | tagcase expression | |
tag_arm { tag_arm } | ||
[ others : body ] | ||
end | ||
∣ | return [ ( expression , ... ) ] | |
∣ | yield [ ( expression , ... ) ] | |
∣ | signal name [ ( expression , ... ) ] | |
∣ | exit name [ ( expression , ... ) ] | |
∣ | break | |
∣ | continue | |
∣ | begin body end | |
∣ | statement resignal name , ... | |
∣ | statement except { when_handler } | |
[ others_handler ] | ||
end | ||
tag_arm | ::= | tag name , ... [ ( idn : type_spec ) ] : body |
when_handler | ::= | when name , ... [ ( decl , ... ) ] : body |
∣ | when name , ... ( * ) : body | |
others_handler | ::= | others [ ( idn : type_spec ) ] : body |
body | ::= | { equate } |
{ statement } | ||
expression | ::= | primary | |
∣ | ( expression ) | ||
∣ | ~ expression | % 6 (precedence) | |
∣ | expression | % 6 | |
∣ | expression ** expression | % 5 | |
∣ | expression // expression | % 4 | |
∣ | expression / expression | % 4 | |
∣ | expression * expression | % 4 | |
∣ | expression || expression | % 3 | |
∣ | expression + expression | % 3 | |
∣ | expression - expression | % 3 | |
∣ | expression < expression | % 2 | |
∣ | expression <= expression | % 2 | |
∣ | expression = expression | % 2 | |
∣ | expression >= expression | % 2 | |
∣ | expression > expression | % 2 | |
∣ | expression ~< expression | % 2 | |
∣ | expression ~<= expression | % 2 | |
∣ | expression ~= expression | % 2 | |
∣ | expression ~>= expression | % 2 | |
∣ | expression ~> expression | % 2 | |
∣ | expression & expression | % 1 | |
∣ | expression cand expression | % 1 | |
∣ | expression | expression | % 0 | |
∣ | expression cor expression | % 0 |
primary | ::= | nil ∣ true ∣ false |
∣ | int_literal ∣ real_literal ∣ char_literal ∣ string_literal | |
∣ | idn | |
∣ | idn [ constant , ... ] | |
∣ | primary . name | |
∣ | primary [ expression ] | |
∣ | invocation | |
∣ | type_spec${ field , ... } | |
∣ | type_spec$[ [ expression : ] [ expression , ... ] ] | |
∣ | type_spec$name [ [ constant , ... ] ] | |
∣ | force [ type_spec ] | |
∣ | up ( expression ) | |
∣ | down ( expression ) | |
invocation | ::= | primary ( [ expression , ... ] ) |
field | ::= | name , ... : expression |
any | down | int | record | tagcase |
array | else | is | rep | then |
begin | elseif | iter | resignal | true |
bool | end | itertype | return | type |
break | except | nil | returns | up |
cand | exit | null | sequence | variant |
char | false | oneof | signal | when |
cluster | for | others | signals | where |
continue | force | own | string | while |
cor | has | proc | struct | yield |
cvt | if | proctype | tag | yields |
do | in | real |
Upper- and lowercase letters are not distinguished in reserved words.
For example, “end,” “END,” and “eNd” are all the same reserved word.
Reserved words appear in boldface in this document, except for names of
types.
( | : | " | < | ~< | + | || |
) | := | ' | <= | ~<= | - | ** |
{ | , | \ | = | ~= | * | // |
} | . | >= | ~>= | / | & | |
[ | $ | > | ~> | ∣ | ||
] | ~ |
idn [ [ constant , ... ] ]
where idn names the user defined type, each constant must be computableShorthand Form | Expansion |
expr1 ** expr2 | T $power(expr1 ; expr2 ) |
expr1 // expr2 | T $mod(expr1 ; expr2 ) |
expr1 / expr2 | T $div(expr1 ; expr2 ) |
expr1 * expr2 | T $mul(expr1 ; expr2 ) |
expr1 || expr2 | T $concat(expr1 ; expr2 ) |
expr1 + expr2 | T $add(expr1 ; expr2 ) |
expr1 - expr2 | T $sub(expr1 ; expr2 |
expr1 < expr2 | T $lt(expr1 ; expr2 ) |
expr1 <= expr2 | T $le(expr1 ; expr2 ) |
expr1 = expr2 | T $equal(expr1 ; expr2 ) |
expr1 >= expr2 | T $ge(expr1 ; expr2 ) |
expr1 > expr2 | T $gt(expr1 ; expr2 ) |
expr1 ~< expr2 | ~ (expr1 < expr2 ) |
expr1 ~<= expr2 | ~ (expr1 <= expr2 ) |
expr1 ~= expr2 | ~ (expr1 = expr2 ) |
expr1 ~>= expr2 | ~ (expr1 >= expr2 ) |
expr1 ~> expr2 | ~ (expr1 > expr2 ) |
expr1 &expr2 | T $and(expr1 ; expr2 ) |
expr1 s∣ jexpr2 | T $or(expr1 ; expr2 ) |
-expr | T $minus(expr) |
~expr | T $not(expr) |
expression1 cand expression2
is the boolean and of expression1 and expression2. However, if expression1expression1 cor expression2
is the boolean or of expression1 and expression2, but expression2 is notPrecedence | Operators |
5 | ** |
4 | * / // |
3 | + - || |
2 | < <= = >= > ~< ~<= ~= ~>= ~> |
1 | & cand |
0 | ∣ cor |
The order of evaluation for operators of the same precedence is from left
to right, except for **, which is from right to left. The following examples
illustrate the precedence rules:
Expression | Equivalent Form |
a + b // c | a + (b // c) |
a + b - c | (a + b) - c |
a + b ** c ** d | a + (b ** (c ** d)) |
a = b | c = d | (a = b) | (c = d) |
-a * b | (-a) * b |
x: any := 3
y: int := force[int](x)
x: any := 3
y: int := x
body ::= { equate }
{ statement } % statements include declarations
The component update statement is not restricted to records. The
statement is legal if the corresponding invocation statement is legal. In
other words, T (the type of primary) must provide a procedure operation
called set_name, which takes two arguments whose types include the types
of primary and expression, respectively.
We recommend that set operations be provided for user-defined types
only if recordlike behavior is desired, that is, only if it is meaningful to
permit selected parts of the abstract object to be modified. In general,
set operations should not perform any substantial computation, except
possibly checking that the arguments satisfy certain constraints.
tagcase expression
tag_arm { tag_arm }
[ others : body ]
end
tag_arm ::= tag name , ... [ ( idn: type_spec ) ] : body
The expression must evaluate to a oneof or variant object. The tag of this
statement except { when_handler }
[ others_handler ]
end
when_handler ::= when name , ... [ ( decl , ... ) ] : body
∣ when name , ... ( * ) : body
others_handler ::= others [ ( idn : type_spec ) ] : body
idn ＝ | proc [ parms ] args [ returns ] [ signals ] [ where ] |
routine_body | |
end idn |
args | ::= ( [ decl , ... ] ) |
returns | ::= returns ( type_spec , ... ) |
signals | ::= signals ( exception , ... ) |
exception | ::= name [ ( type_spec , ... ) ] |
routine_body | ::= { equate } { own var } { statement } |
idn ＝ | iter [ parms ] args [ yields ] [ signals ] [ where ] |
routine_body | |
end idn |
yields ::= yields ( type_spec , ... )
idn ＝ | cluster [ parms ] is idn , ... [ where ] |
cluster_body | |
end idn |
cluster_body ::= | { equate } rep ＝ type_spec { equate } |
{ own var } | |
routine { routine } | |
routine ::= | procedure ∣ iterator |
where ::= where restriction , ...
where
restriction | ::= | idn has oper_decl , ... |
∣ | idn in type set | |
oper_decl | ::= | op_name , ... : type_spec |
op_name | ::= | name [ [ constant , ... ] ] |
type_set | ::= | { idn | idn has oper_decl , ... { equate } } |
∣ | idn |
The type null has exactly one, immutable object, represented
by the literal nil. Nil is generally used as a place holder in type
definitions using oneofs or variants.
Operations
copy =＝proc (n: null) returns (null)
effects Returns nil.
equal ＝ proc (n1, n2: null) returns (bool)
effects Returns true.
similar ＝ proc (n1, n2: null) returns (bool)
effects Returns true.
end null
The two immutable objects of type bool, with literals true and
false, represent logical truth values.
Operations
and ＝ proc (b1, b2: bool) returns (bool)
effects Returns the logical and of b1 and b2.
or ＝ proc (b1, b2: bool) returns (bool)
effects Returns the logical or of b1 and b2.
not ＝ proc (b: bool) returns (bool)
effects Returns the logical negation of b.
equal ＝ proc (b1, b2: bool) returns (bool)
similar ＝ proc (b1, b2: bool) returns (bool)
effects Returns true if b1 and b2 are both true or both false;
otherwise returns false.
copy ＝ proc (b: bool) returns (bool)
effects If b is true returns true; otherwise returns false.
end bool
Objects of type int are immutable and are intended to model
a subrange of the mathematical integers. The exact range is
not part of the language definition and can vary somewhat
from implementation to implementation. Each implementation
is constrained to provide a closed interval [int min, int max],
with int min < 0 and int max ≥ char top (the number of
characters|see section A.9.5). An overflow exception is sig-
naled by an operation if the result would lie outside this inter-
val.
Integer literals are written as a sequence of one or more decimal
digits.
Operations
add ＝ proc (x, y: int) returns (int) signals (overflow)
sub ＝ proc (x, y: int) returns (int) signals (overflow)
mul ＝ proc (x, y: int) returns (int) signals (overflow)
effects These are the standard integer addition, subtraction, and
multiplication operations. They signal overflow if the result
would lie outside the represented interval.
minus ＝ proc (x: int) returns (int) signals (overflow)
effects Returns the negative of x; signals overflow if the result
would lie outside the represented interval.
div ＝ proc (x, y: int) returns (int) signals (zero divide, overflow)
effects Signals zero divide if y = 0. Otherwise returns the integer
quotient of dividing x by y; signals overflow if the result would
lie outside the represented interval.
mod ＝ proc (x, y: int) returns (int) signals (zero divide, overflow)
effects Signals zero divide if y = 0. Otherwise returns the integer
remainder of dividing x by y; signals overflow if the result would
lie outside the represented interval.
power ＝ proc (x, y: int) returns (int) signals (negative exponent, overflow)
effects Signals negative exponent if y < 0. Otherwise returns x y ;
signals overflow if the result would lie outside the represented
interval.
abs ＝ proc (x: int) returns (int) signals (overflow)
effects Returns the absolute value of x; signals overflow if the
result would lie outside the represented interval.
max ＝ proc (x, y: int) returns (int)
effects Returns the larger of x and y.
min ＝ proc (x, y: int) returns (int)
effects Returns the smaller of x and y.
lt ＝ proc (x, y: int) returns (bool)
gt ＝ proc (x, y: int) returns (bool)
le ＝ proc (x, y: int) returns (bool)
ge ＝ proc (x, y: int) returns (bool)
equal ＝ proc (x, y: int) returns (bool)
effects These are the standard ordering relations.
similar ＝ proc (x, y: int) returns (bool)
effects Returns (x ＝ y).
copy ＝ proc (x: int) returns (y: int)
effects Returns y such that x = y.
from_to_by = iter (from, to, by: int) yields (int)
effects Yields the integers from from to to, incrementing by by
each time, that is, yields from, from+by, . . . , from + n * by ,
where n is the largest positive integer such that from + n * by ≤
to. If by = 0, then yields from indefinitely. Yields nothing if
from > to and by > 0, or if from < to and by < 0.
from to ＝ iter (from, to: int) yields (int)
effects Identical to from to by(from, to, 1).
parse ＝ proc (s: string) returns (int) signals (bad format, overflow)
effects s must be an integer literal, with an optional leading plus
or minus sign; if s is not of this form, signals bad format. Oth-
erwise returns the integer corresponding to s; signals overflow
if the result would be outside of the represented interval.
unparse ＝ proc (x: int) returns (string)
effects Produces the string corresponding to the integer value of
x, preceded by a minus sign if x < 0. Leading zeros are sup-
pressed, and there is no leading plus sign for positive integers.
end int
The type real models a subset of the mathematical real num-
bers. Reals are immutable and are written as a mantissa with
an optional exponent. A mantissa is either a sequence of one
or more decimal digits or two sequences (one of which may be
empty) joined by a period. The mantissa must contain at least
one digit. An exponent is E or e, optionally followed by +
or –, followed by one or more decimal digits. An exponent is
required if the mantissa does not contain a period. As is usual,
mEx ＝ m * 10^{x}. Examples of real literals are:
3.14 3.14E0 314e-2 .0314E+2 3. .14Each implementation represents numbers in
∀r ∈ D | Approx(r) ∈ Real |
∀r ∈ Real | Approx(r) = r |
∀r ∈ D {0} | ∣(Approx(r) - r)/r∣ < 10^{1-p} |
∀r,s ∈ D | r ≤ s ⇒ Approx(r) ≤ Approx(s) |
∀r ∈ D | Approx(–r) = –Approx(r) |
add ＝ proc (x, y: real) returns (real) signals (overflow, underflow)
effects Computes the sum z of x and y; signals overflow or under-
flow if z is outside of D, as explained earlier. Otherwise returns
approx(z) such that
(x, y ≥ 0 ∨ x, y ≤ 0) ⇒ add(x, y) = Approx(x + y)
add(x, y) = (1 + ε)(x + y) ∣ε∣ < 10^{1 - p}
add(x, 0) = x
add(x, y) = add(y, x)
x ≤ x' ⇒ add(x, y) ≤ add(x', y)
sub ＝ proc (x, y: real) returns (real) signals (overflow, underflow)
effects Computes x y ; the result is identical to add(x, y).
minus ＝ proc (x: real) returns (real)
effects Returns x .
mul ＝ proc (x, y: real) returns (real) signals (overflow, underflow)
effects Returns approx (x * y ); signals overflow or underflow if x * y
is outside of D.
div ＝ proc (x, y: real) returns (real)
signals (zero divide, overflow, underflow)
effects If y = 0, signals zero divide. Otherwise returns
approx (x =y ); signals overflow or underflow if x =y is outside
of D.
power ＝ proc (x, y: real) returns (real)
signals (zero divide, complex result, overflow, underflow)
effects If x = 0 and y < 0, signals zero divide. If x < 0 and
y is nonintegral, signals complex result. Otherwise returns an
approximation to x y ; signals overflow or underflow if x y is
outside of D.
abs ＝ proc (x: real) returns (real)
effects Returns the absolute value of x.
max ＝ proc (x, y: real) returns (real)
effects Returns the larger of x and y.
min ＝ proc (x, y: real) returns (real)
effects Returns the smaller of x and y.
exponent ＝ proc (x: real) returns (int) signals (undefined)
effects If x = 0, signals undefined. Otherwise returns the exponent
that would be used in representing x as a literal in standard
form, that is, returns
chmax({i∣abs(x) ≥ 10i })
mantissa ＝ proc (x: real) returns (real)
effects Returns the mantissa of x when represented in standard
form, that is, returns approx (x =10e ), where e = exponent (x ).
If x = 0.0, returns 0.0.
i2r ＝ proc (i: int) returns (real) signals (overflow)
effects Returns approx(i); signals overflow if i is not in D.
r2i ＝ proc (x: real) returns (int) signals (overflow)
effects Rounds x to the nearest integer and toward zero in case of
a tie. Signals overflow if the result lies outside the represented
range of integers.
trunc ＝ proc (x: real) returns (int) signals (overflow)
effects Truncates x toward zero; signals overflow if the result
would be outside the represented range of integers.
parse ＝ proc (s: string) returns (real) signals (bad format, overflow, underflow)
effects Computes the exact value z corresponding to a real or
integer literal and returns approx(z). s must be a real or integer
literal with an optional leading plus or minus sign; otherwise
signals bad format. Signals underflow or overflow if z is not in
D.
unparse ＝ proc (x: real) returns (string)
effects Returns a real literal such that parse(unparse(x)) = x. The
general form of the literal is
[-] i_field.f_field [ e ± x field ]
Leading zeros in i field and trailing zeros in { field are sup-
pressed. If x is integral and within the range of CLU integers,
then { field and the exponent are not present. If x can be rep-
resented by a mantissa of no more than Max_width digits and
no exponent (that is, if 1 ≤ exponent (arg 1) < Max_width ),
then the exponent is not present. Otherwise the literal is in
standard form, with Exp_width digits of exponent.
lt ＝ proc (x, y: real) returns (bool)
le ＝ proc (x, y: real) returns (bool)
ge ＝ proc (x, y: real) returns (bool)
gt ＝ proc (x, y: real) returns (bool)
equal ＝ proc (x, y: real) returns (bool)
effects The standard ordering relations.
similar ＝ proc (x, y: real) returns (bool)
effects Returns (x = y).
copy ＝ proc (x: real) returns (real)
effects Returns y such that x = y.
end real
Type char provides the alphabet for text manipulation. Char-
acters are immutable and form an ordered set. Every imple-
mentation must provide at least 128, but no more than 512,
characters; the first 128 characters are the ASCII characters in
their standard order.
Operations i2c and c2i convert between ints and chars. The
smallest character corresponds to zero, and characters are num-
bered sequentially up to char top, the integer corresponding to
the largest character. This numbering determines the ordering
of the characters.
Printing ASCII characters (octal 40 through octal 176), other
than single quote or backslash, can be written as that character
enclosed in single quotes. Any character can be written by
enclosing one of the following escape sequences in single quotes:
escape sequence | character |
\' | ' (single quote) |
\" | " (double quote) |
\\ | \ (backslash) |
\n | NL (newline) |
\t | HT (horizontal tab) |
\p | FF (form feed, newpage) |
\b | BS (backspace) |
\r | CR (carriage return) |
\v | VT (vertical tab) |
\*** | specified by octal value (exactly three octal digits) |
The escape sequences may also be written using upper case
letters. Examples of character literals are
`7'
`a'
\
"
`\"'
`\''
`\B'
`\177'
Operations
i2c ＝ proc (x: int) returns (char) signals (illegal char)
effects Returns the character corresponding the x; signals ille-
gal argument if x is not in the range [0, char top].
c2i ＝ proc (c: char) returns (int)
effects Returns the integer corresponding to c.
lt ＝ proc (c1, c2: char) returns (bool)
le ＝ proc (c1, c2: char) returns (bool)
ge ＝ proc (c1, c2: char) returns (bool)
gt ＝ proc (c1, c2: char) returns (bool)
equal ＝ proc (c1, c2: char) returns (bool)
effects These are the standard ordering relations, where the order
is consistent with the numbering of characters.
similar ＝ proc (c1, c2: char) returns (bool)
effects Returns (c1 = c2).
copy ＝ proc (c1: char) returns (c2: char)
effects Returns c2 such that c1 = c2.
end char
string ＝ data type is size, empty, concat, append, fetch, rest, indexs,
indexc, substr, lt, file, ge, gt, equal, similar, copy, c2s, s2ac,
ac2s, s2sc, sc2s, chars
Overview
Type string is used for representing text. A string is an im-
mutable sequence of zero or more characters. The characters of
a string are indexed sequentially starting from one. Strings are
lexicographically ordered based on the ordering for characters.
A string is written as a sequence of zero or more character rep-
resentations enclosed in double quotes. Within a string literal,
a printing ASCII character other than double quote or back-
slash is represented by itself. Any character can be represented
by using the escape sequences listed for characters. Examples
of string literals are
“Item\tCost” \altmode (\033) = \\033" \ " \ "
If the result of a string operation would be a string containing
more than int max characters, the operation signals failure.
Operations
size ＝ proc (s: string) returns (int)
effects Returns the number of characters in s.
empty ＝ proc (s: string) returns (bool)
effects Returns true if s is empty (contains no characters);
otherwise returns false.
concat ＝ proc (s1, s2: string) returns (string)
effects Returns a new string containing the characters of s1 fol-
lowed by the characters of s2. Signals failure if the new string
would contain more than int max characters.
append ＝ proc (s: string, c: char) returns (string)
effects Returns a new string containing the characters of s fol-
lowed by c. Signals failure if the new string would contain
more than int max characters.
fetch ＝ proc (s: string, i: int) returns (char) signals (bounds)
effects Signals bounds if i < 0 or i > size (s ); otherwise returns
the ith character of s.
rest ＝ proc (s: string, i: int) returns (string) signals (bounds)
effects Signals bounds if i < 0 or i > size (s ) + 1 ;
otherwise returns a new string containing the characters
s [i ]; s [i + 1 ]; . . . ; s [size (s )]. Note that if i = size(s)+1, rest
returns the empty string.
indexs ＝ proc (s1, s2: string) returns (int)
effects If s1 occurs as a substring in s2, returns the least index at
which s1 occurs. Returns 0 if s1 does not occur in s2, and 1 if
s1 is the empty string. For example,
chindexs("bc", "abcbc") = 2
chindexs("", "abcde") = 1
indexc ＝ proc (c: char, s: string) returns (int)
effects If c occurs in s, returns the least index at which c occurs;
returns 0 if c does not occur in s.
substr ＝ proc (s: string, at, cnt: int) returns (string)
signals (bounds, negative size)
effects If cnt < 0, signals negative size. If at < 1 or at >
size (s ) + 1, signals bounds. Otherwise returns a new string
containing the characters s [at ]; s [at + 1]; . . .; the new string
contains min (cnt ; size at + 1) characters. For example,
chsubstr ("abcdef", 2, 3) = "bcd"
chsubstr ("abcdef", 2, 7) = "bcdef"
chsubstr ("abcdef", 7, 1) = ""
Note that if min (cnt ; size at + 1) = 0, substr returns the
empty string.
lt ＝ proc (s1, s2: string) returns (bool)
le ＝ proc (s1, s2: string) returns (bool)
ge ＝ proc (s1, s2: string) returns (bool)
gt ＝ proc (s1, s2: string) returns (bool)
equal ＝ proc (s1, s2: string) returns (bool)
effects These are the usual lexicographic ordering relations on
strings, based on the ordering of characters. For example,
"abc" < "aca"
"abc" < "abca"
similar ＝ proc (s1, s2: string) returns (bool)
effects Returns true if s1 = s2; otherwise returns false.
copy ＝ proc (s1: string) returns (s2: string)
effects Returns s2 such that s1 = s2.
c2s ＝ proc (c: char) returns (string)
effects Returns a string containing c as its only character.
s2ac ＝ proc (s: string) returns (array[char])
effects Stores the characters of s as elements of a new array of
characters, a. The low bound of the array is 1, the size is
size(s), and the ith element of the array is the ith character of
s, for 1 ≤ i ≤ size (s ).
ac2s ＝ proc (a: array[char]) returns (string)
effects Does the inverse of s2ac. The result is a string with char-
acters in the same order as in a. That is, the ith character of
the string is the (i + low (a ) 1)th element of a.
s2sc ＝ proc (s: string) returns (sequence[char])
effects Transforms a string into a sequence of characters. The
size of the sequence is size(s). The ith element of the sequence
is the ith character of s.
sc2s ＝ proc (s: sequence[char]) returns (string)
effects Does the inverse of s2sc. The result is a string with char-
acters in the same order as in s. That is, the ith character of
the string is the ith element of s.
chars ＝ iter (s: string) yields (char)
effects Yields, in order, each character of s.
end string
create ＝ proc (lb: int) returns (array[t])
effects Returns a new, empty array with low bound lb.
new ＝ proc ( ) returns (array[t])
effects Returns a new, empty array with low bound 1.
predict ＝ proc (lb, cnt: int) returns (array[t])
effects Returns a new, empty array with low bound lb. Argument
cnt is a prediction of how many addhs or addls are likely to be
performed on this new array. If cnt > 0, addhs are expected;
otherwise addls are expected. These operations may execute
faster than if the array had been produced by calling create.
ll ＝ proc (lb, cnt: int, elem: t) returns (array[t]) signals (negative size)
effects If cnt < 0, signals negative size. Returns a new array with
low bound lb and size cnt, and with elem as each element; if this
new array would have high bound < int min or > int max ,
signals failure.
low ＝ proc (a: array[t]) returns (int)
effects Returns the low bound of a.
high ＝ proc (a: array[t]) returns (int)
effects Returns the high bound of a.
size ＝ proc (a: array[t]) returns (int)
effects Returns a count of the number of elements of a.
empty ＝ proc (a: array[t]) returns (bool)
effects Returns true if a contains no elements; otherwise returns false.
set_low ＝ proc (a: array[t], lb: int)
modifies a
effects Modifies the low and high bounds of a; the new low bound
of a is lb and the new high bound is high(apre lb +low (apre )). If
the new high bound is outside the represented range of integers,
signals failure and does not modify a.
trim ＝ proc (a: array[t], lb, cnt: int) signals (bounds, negative size)
modifies a
effects If lb < low (a ) or lb > high (a ) + 1, signals bounds. If
cnt < 0, signals negative size. Otherwise modifies a by remov-
ing all elements with index < lb or greater than or equal to
lb + cnt ; the new low bound is lb. For example, if a = ar-
ray[int]$[1,2,3,4,5], then
trim(a, 2, 2) results in a having value [2: 2, 3]
trim(a, 4, 3) results in a having value [4: 4, 5]
fetch ＝ proc (a: array[t], i: int) returns (t) signals (bounds)
effects If i < low (a ) or i > high (a ), signals bounds; otherwise
returns the element of a with index i.
store ＝ proc (a: array[t], i: int, elem: t) signals (bounds)
modifies a.
effects If i < low (a ) or i > high (a ), signals bounds; otherwise
makes elem the element of a with index i.
bottom ＝ proc (a: array[t]) returns (t) signals (bounds)
effects If a is empty, signals bounds; otherwise returns a[low(a)].
top ＝ proc (a: array[t]) returns (t) signals (bounds)
effects If a is empty, signals bounds; otherwise returns a[high(a)].
addh ＝ proc (a: array[t], elem: t)
modifies a.
effects If extending a on the high end causes the high bound or
size of a to be outside the defined range of integers, signals
failure. Otherwise extends a by 1 in the high direction and
stores elem as the new element.
addl ＝ proc (a: array[t], elem: t) signals (overflow)
modifies a.
effects If extending a on the low end causes the low bound or size
of a to be outside the defined range of integers, signals failure.
Otherwise extends a by 1 in the low direction and stores elem
as the new element.
remh ＝ proc (a: array[t]) returns (t) signals (bounds)
modifies a.
effects If a is empty, signals bounds. Otherwise shrinks a by re-
moving its high element and returning the removed element.
reml ＝ proc (a: array[t]) returns (t) signals (bounds)
modifies a.
effects If a is empty, signals bounds. Otherwise shrinks a by re-
moving its low element and returning the removed element.
elements ＝ iter (a: array[t]) yields (t)
effects The effect is equivalent to the following body:
for i: int in int$from to(array[t]$low(a), array[t]$high(a))
do
yield (a[i])
end
Note that if a is not modified by the loop body, the effect is to
yield the elements of a, each exactly once, from the low bound
to the high bound.
indexes ＝ iter (a: array[t]) yields (int)
effects Yields the indexes of a from the low bound of apre to the
high bound of apre . Note that indexes is unaffected by any
modifications done by the loop body.
equal ＝ proc (a1, a2: array[t]) returns (bool)
effects Returns true if a1 and a2 refer to the same array object;
otherwise returns false.
similar ＝ proc (a1, a2: array[t]) returns (bool)
requires t has operation
similar: proctype (t, t) returns (bool)
effects Returns true if a1 and a2 have the same low and high
bounds and if their elements are pairwise similar as deter-
mined by t$similar. This operation is equivalent to the following body:
at ＝ array[t]
if at$low(a) ~= at$low(a2) cor at$size(a1) ~= at$size(a2)
then return (false)
end
for i: int in at$indexes(a1) do
if ~t$similar(a1[i], a2[i]) then return (false) end
end
return (true)
similar1 ＝ proc (a1, a2: array[t]) returns (bool)
requires t has operation
equal: proctype (t, t) returns (bool)
effects Returns true if a1 and a2 have the same low and high
bounds and if their elements are pairwise equal as determined
by t$equal. This operation works the same way as similar,
except that t$equal is used instead of t$similar.
copy ＝ proc (a: array[t]) returns (b: array[t])
requires t has operation
copy: proctype (t) returns (t)
effects Returns a new array b with the same low and high bounds
as a and such that each element b[i] contains t$copy(a[i]). This
operation is equivalent to the following body:
b := array[t]$copy1(a)
for i: int in array[t]$indexes(a) do
b[i] := t$copy(a[i])
end
return (b)
copy1 ＝ proc (a: array[t]) returns (b: array[t])
effects Returns a new array b with the same low and high bounds
as a and such that each element b[i] contains the same element
as a[i].
ll copy ＝ proc (lb, cnt: int, elem: t) returns (array[t])
signals (negative size)
requires t has operation
copy: proctype (t) returns (t)
effects The effect is like ll except that elem is copied. If cnt < 0,
signals negative size. Otherwise returns a new array with low
bound lb and size cnt and with each element a distinct copy of
elem, as produced by t$copy; if the new array has high bound
< int min or > int max , signals failure. This operation is
equivalent to the following body:
if cnt < 0 then signal negative size end
x: array[t] := array[t]$predict(lb, cnt)
for j: int in int$from to(1, cnt) do
at$addh(x, t$copy(elem))
end array
end
return (x)
Sequences are immutable sequences of elements; they always
have low bound 1. The elements of the sequence can be indexed
sequentially from 1 up to the size of the sequence.
Sequences can be created by calling sequence operations and
by means of a special constructor; arguments of the constructor
are simply the elements of the new sequence; for example,
sequence[int]$[3, 7]
creates a two-element sequence containing 3 at index 1 and 7 at
index 2. The special constructor is discussed further in section
A.6.8.
Any operation call that attempts to access a sequence with an
index that is not within the defined range terminates with the
bounds exception. Any operation call that would give rise to
a sequence whose size is greater than int max terminates with
the failure exception.
Operations
new ＝ proc ( ) returns (sequence[t])
effects Returns the empty sequence.
ll ＝ proc (cnt: int, elem: t) returns (sequence[t]) signals (negative size)
effects If cnt < 0, signals negative size. Otherwise returns a se-
quence containing cnt elements each of which is elem.
size ＝ proc (s: sequence[t]) returns (int)
effects Returns a count of the number of elements in s.
empty ＝ proc (s: sequence[t]) returns (bool)
effects Returns true if s contains no elements; otherwise returns false.
fetch ＝ proc (s: sequence[t], i: int) returns (t) signals (bounds)
effects If i < 1 or i > size(s ), signals bounds. Otherwise returns
the ith element of s.
bottom ＝ proc (s: sequence[t]) returns (t) signals (bounds)
effects If s is empty, signals bounds. Otherwise returns s[1].
top ＝ proc (s: sequence[t]) returns (t) signals (bounds)
effects If s is empty, signals bounds. Otherwise returns s[size(s)].
replace ＝ proc (s: sequence[t], i: int, elem: t) returns (sequence[t]) signals (bounds)
effects If i < 1 or i > high (s ), signals bounds. Otherwise returns
a new sequence containing the same elements as s, except that
elem is in the ith position. For example,
replace(sequence[int]$[2,5], 1, 6]) = [6, 5]
addh ＝ proc (s: sequence[t], elem: t) returns (sequence[t])
effects Returns a new sequence containing the same elements as
s followed by one additional element, elem. If the resulting
sequence has size > int max , signals failure.
addl ＝ proc (s: sequence[t], elem: t) returns (sequence[t])
effects Returns a new sequence containing elem as the first ele-
ment followed by the elements of s. If the resulting sequence
has size >int max , signals failure.
remh ＝ proc (s: sequence[t]) returns (sequence[t]) signals (bounds)
effects If s is empty, signals bounds. Otherwise returns a new
sequence containing all elements of s except the last one.
reml ＝ proc (s: sequence[t]) returns (sequence[t]) signals (bounds)
effects If s is empty, signals bounds. Otherwise returns a new
sequence containing all elements of s except the first one.
concat ＝ proc (s1, s2: sequence[t]) returns (sequence[t])
effects Returns a new sequence containing the elements of s1 fol-
lowed by the elements of s2. Signals failure if the size of the
new sequence is > int max .
e2s ＝ proc (elem: t) returns (sequence[t])
effects Returns a one-element sequence containing elem as its only element.
a2s ＝ proc (a: array[t]) returns (sequence[t])
effects Returns a sequence containing the elements of a in the same order as in a.
s2a ＝ proc (s: sequence[t]) returns (array[t])
effects Returns a new array with low bound 1 and containing the
elements of s in the same order as in s.
elements ＝ iter (s: sequence[t]) yields (t)
effects Yields the elements of s in order.
indexes ＝ iter (s: sequence[t]) yields (int)
effects Yields the indexes of s from 1 to size(s).
equal ＝ proc (s1, s2: sequence[t]) returns (bool)
requires t has operation
equal: proctype (t, t) returns (bool)
effects Returns true if s1 and s2 have equal values as determined
by t$equal. This operation is equivalent to the following body:
qt ＝ sequence [t]
if qt$size(s1) ~= qt$size(s2) then return (false) end
for i: int in qt$indexes(s1) do
if s1[i] ~= s2[i] then return(false) end
end
return (true)
similar ＝ proc (s1, s2: sequence[t]) returns (bool)
requires t has operation
similar: proctype (t, t) returns (bool)
effects Returns true if s1 and s2 have similar values as determined
by t$similar. Similar works in the same way as equal, except
that t$similar is used instead of t$equal.
copy ＝ proc (s: sequence[t]) returns (sequence[t])
requires t has operation
copy: proctype (t) returns (t)
effects Returns a new sequence containing as elements copies of
the elements of s. This operation is equivalent to the following
body:
qt ＝ sequence[t]
y: qt := qt$new()
for e: t in qt$elements(s) do
y := qt$addh(y, t$copy(e))
end
return (y)
ll copy ＝ proc (cnt: int, elem: t) returns (sequence[t])
signals (negative size)
requires t has operation
copy: proctype (t) returns (t)
effects If cnt < 0, signals negative size.
Otherwise returns a new sequence containing cnt elements each
of which is a copy of elem. This operation is equivalent to the
following body:
qt = sequence[t]
if cnt < 0 then signal negative size end
x: qt := qt$new()
for i: int in int$from to(1, cnt) do
x := qt$addh(x, T$copy(elem))
end sequence
end
return (x)
A record is a mutable collection of one or more named objects.
The names are called selectors, and the objects are called com-
ponents. Different components may have different types. A
record type specification has the form
record [ field_spec , . . .]
where
field_spec ::= name, . . .: type_spec
Selectors must be unique within a specification, but the order-
ing and grouping of selectors is unimportant. For example, the
following name the same type:
record[last, first, middle: string, age: int]
record[last: string, age: int, first, middle: string]
A record is created using a record constructor, such as
info $ flast: "Jones", first: "John", age: 32, middle: "J."}
(assuming that "info" has been equated to one of the above
type specifications; see section A.4.3). An expression must be
given for each selector, but the order and grouping of selec-
tors need not resemble the corresponding type specification.
Record constructors are discussed in section A.6.8.
In the following definitions of record operations, let
rt = record[n1 : t1 ; . . . ; nk : tk ]
Operations
get_n_{i} ＝ proc (r: rt) returns (ti )
effects Returns the component of r whose selector is n_{i} . There is
a get operation for each selector.
set_n ＝ proc (r: rt, e: ti )
modifies r.
effects Modifies r by making the component whose selector is n_{i}
be e. There is a set operation for each selector.
r gets r ＝ proc (r1, r2: rt)
modifies r1.
effects Sets each component of r1 to be the corresponding
component of r2.
r gets s ＝ proc (r: rt, s: st)
modifies r.
effects Here st is a struct type whose components have the same
selectors and types as rt. Sets each component of r to be the
corresponding component of s.
equal ＝ proc (r1, r2: rt) returns (bool)
effects Returns true if r1 and r2 are the very same record object;
otherwise returns false.
similar ＝ proc (r1, r2: rt) returns (bool)
requires Each ti has operation
similar: proctype (ti ; ti ) returns (bool)
effects Returns true if r1 and r2 contain similar objects for each
component as determined by the ti $similar operations. The
comparison is done in lexicographic order; if any comparison
returns false, false is returned immediately.
similar1 ＝ proc (r1, r2: rt) returns (bool)
requires Each ti has operation
equal: proctype (ti ; ti ) returns (bool)
effects Returns true if r1 and r2 contain equal objects for each
component as determined by the ti $equal operations. The com-
parison is done in lexicographic order; if any comparison re-
turns false, false is returned immediately.
copy1 ＝ proc (r: rt) returns (rt)
effects Returns a new record containing the components of r as
its components.
copy ＝ proc (r: rt) returns (rt)
requires Each ti has operation
copy: proctype (ti ) returns (ti )
effects Returns a new record obtained by performing copy1(r) and
end record
then replacing each component with a copy of the correspond-
ing component of r. Copies are obtained by calling the ti $copy
operations. Copying is done in lexicographic order.
A struct is an immutable record. A struct type specification
has the form
struct [ field_spec, ... ]
where (as for records)
field_spec ::= name, . . .: type_spec
A struct is created using a struct constructor, which syntacti-
cally is identical to a record constructor. Struct constructors
are discussed in section A.6.8.
In the following operation descriptions,
st ＝ struct[n1 : t1 ; . . . ; nk : tk ]
Operations
get_n_{i} ＝ proc (s: st) returns (ti )
effects Returns the component of s whose selector is n_{i} . There is
a get operation for each selector.
replace_n_{i} ＝ proc (s: st, e: ti ) returns (st)
effects Returns a new struct object whose components are those of
s except that component n_{i} is e. There is a replace operation
for each selector.
s2r ＝ proc (s: st) returns (rt)
effects Here rt is a record type whose components have the same
selectors and types as st. Returns a new record object whose
components are those of s.
r2s ＝ proc (r: rt) returns (st)
effects Here rt is a record type whose components have the same
selectors and types as st. Returns a struct object whose components are those of r.
equal ＝ proc (s1, s2: st) returns (bool)
requires Each ti has operation
equal: proctype (ti ; ti ) returns (bool)
effects Returns true if s1 and s2 contain equal objects for each
component as determined by the ti $equal operations. The com-
parison is done in lexicographic order; if any comparison re-
turns false, false is returned immediately.
similar ＝ proc (s1, s2: st) returns (bool)
requires Each ti has operation
similar: proctype (ti ; ti ) returns (bool)
effects Returns true if s1 and s2 contain similar objects for each
component as determined by the ti $similar operations. The
comparison is done in lexicographic order; if any comparison
returns false, false is returned immediately.
copy ＝ proc (s: st) returns (st)
requires Each ti has operation
copy: proctype (ti ) returns (ti )
effects Returns a struct containing a copy of each component of s;
copies are obtained by calling the ti $copy operations. Copying
is done in lexicographic order.
end struct
A oneof type is a tagged, discriminated union. A oneof is a
labeled object, to be thought of as “one of” a set of alternatives.
The label is called the tag, and the object is called the value.
A oneof type specification has the form
oneof [ field_spec , . . .]
where (as for records
field_spec ::= name, ... : type_spec
Tags must be unique within a specification, but the ordering
and grouping of tags is unimportant.
Although there are oneof operations for decomposing oneof ob-
jects, they are usually decomposed via the tagcase statement,
which is discussed in section A.7.9.
In the following descriptions of oneof operations,
ot ＝ oneof[n1 : t1 ; . . . ; nk : tk ]
Operations
make_n_{i} ＝ proc (e: ti ) returns (ot)
effects Returns a oneof object with tag n_{i} and value e. There is
a make operation for each selector.
is_n_{i} ＝ proc (o: ot) returns (bool)
effects Returns true if the tag of o is n_{i} , else returns false. There
is an is operation for each selector.
value_n_{i} ＝ proc (o: ot) returns (ti ) signals (wrong tag)
effects If the tag of o is n_{i} , returns the value of o; otherwise signals
wrong tag. There is a value operation for each selector.
o2v ＝ proc (o: ot) returns (vt)
effects Here vt is a variant type with the same selectors and types
as ot. Returns a new variant object with the same tag and
value as o.
v2o ＝ proc (v: vt) returns (ot)
effects Here vt is a variant type with the same selectors and types
as ot. Returns a oneof object with the same tag and value as
v.
equal ＝ proc (o1, o2: ot) returns (bool)
requires Each ti has operation
equal: proctype (ti ; ti ) returns (bool)
effects Returns true if o1 and o2 have the same tag and equal
values as determined by the equal operation of their type.
similar ＝ proc (o1, o2: ot) returns (bool)
requires Each ti has operation
similar: proctype (ti ; ti ) returns (bool)
effects Returns true if o1 and o2 have the same tag and similar
values as determined by the similar operation of their type.
copy ＝ proc (o: ot) returns (ot)
requires Each ti must have operation
copy: proctype (ti ) returns (ti )
effects Returns a oneof object with the same tag as o and con-
taining as a value a copy of o's value; the copy is made using
the copy operation of the value's type.
end oneof
A variant is a mutable oneof. A variant type specification has
the form
variant [ field_spec , . . . ]
where (as for records)
field_spec ::= name, . . . : type_spec
Although there are variant operations for decomposing variant
objects, they are usually decomposed via the tagcase state-
ment, which is discussed in section A.7.9.
In the following descriptions of variant operations,
vt ＝ variant[n1 : t1; . . . ; nk : tk ]
Operations
make_n_{i} ＝ proc (e: ti ) returns (vt)
effects Returns a new variant object with tag n_{i} and value e.
There is a make operation for each selector.
change_n_{i} ＝ proc (v: vt, e: ti )
modifies v.
effects Modifies v to have tag n_{i} and value e.
There is a change operation for each selector.
is n_{i} ＝ proc (v: vt) returns (bool)
effects Returns true if the tag of v is n_{i} ; otherwise returns false.
There is an is operation for each selector.
value_n_{i} ＝ proc (v: vt) returns (ti ) signals (wrong tag)
effects If the tag of v is n_{i} , returns the value of v; otherwise
signals wrong tag. There is a value operation for each selector.
v gets v ＝ proc (v1, v2: vt)
modifies v1.
effects Modifies v1 to contain the same tag and value as v2.
v gets o ＝ proc (v: vt, o: ot)
modifies v.
effects Here ot is the oneof type with the same selectors and types
as vt. Modifies v to contain the same tag and value as o.
equal ＝ proc (v1, v2: vt) returns (bool)
effects Returns true if v1 and v2 are the same variant object.
similar ＝ proc (v1, v2: vt) returns (bool)
requires Each ti must have operation
similar: proctype (ti , ti ) returns (bool)
effects Returns true if v1 and v2 have the same tag and similar
values as determined by the similar operation of their type.
similar1 ＝ proc (v1, v2: vt) returns (bool)
requires Each ti must have operation
equal: proctype (ti , ti ) returns (bool)
effects Returns true if v1 and v2 have the same tag and equal
values as determined by the equal operation of their type.
copy ＝ proc (v: vt) returns (vt)
requires Each ti must have operation
copy: proctype (ti ) returns (ti )
effects Returns a variant object with the same tag as v and con-
taining as a value a copy of v's value; the copy is made using
the copy operation of the value's type.
copy1 ＝ proc (v: vt) returns (vt)
effects Returns a new variant object with the same tag as v and
containing v's value as its value.
end variant
proctype ( [ type_spec , . . . ] ) [ returns ] [ signals ]
and an iterator type specification has the formitertype ( [ type_spec , . . . ] ) [ yields ] bn brack signals ]
where
returns | ::= | returns (type_spec , . . .) |
yields | ::= | yields (type_spec , . . .) |
signals | ::= | signals (exception , . . .) |
exception | ::= | name [ (type_spec , . . .) ] |
equal ＝ proc (x, y: t) returns (bool)
similar ＝ proc (x, y: t) returns (bool)
effects These operations return true if and only if x and y are the
same module with the same parameters.
copy ＝ proc (x: t) returns (y: t)
effects Returns y such that x = y.
File names are immutable objects used to name files. The
system file name format is viewed as consisting of four string
components:
1. directory|specifies a file directory or device;
2. name|the primary name of the file (for example, “thesis”);
3. suffix|a name normally indicating the type of file (for
example, "clu" for a CLU source file);
4. other|all other components of the system file name
form.
The directory and other components may have internal syn-
tax. The name and suffix should be short identifiers. (For
example, in the TOPS-20 file name "ps:hcluseriref.lpt.3";,
the directory is "ps:hcluseri", the name is \ref;', the
suffix is "lpt", and the other is "3". In the UNIX
path name "/usr/snyder/doc/refman.r", the directory is
"/usr/snyder/doc", the name is `refman', the suffix is "r", and
there is no other.)
A null component has the following interpretation:
1. directory|denotes the current “working” directory (for
example, the “connected directory” under TOPS-20 and
the “current directory” under UNIX|see also section
A.10.6);
2. name|may be illegal, have a unique interpretation, or
be ignored (for example, under TOPS-20, a null name
is illegal for most directories, but for some devices the
name is ignored);
3. suffix|may be illegal, have a unique interpretation, or
be ignored (for example, under TOPS-20, a null suffix is
legal, as in "hrwsifoo");
4. other|should imply a reasonable default.
Operations
create ＝ proc (dir, name, suffix, other: string) returns ( file name)
signals (bad format)
effects Creates a new file name from its components; if any com-
ponent is not in the form required by the underlying system,
signals bad format. In the process of creating a file name, the
string arguments may be transformed|for example, by truncation or case-conversion.
get_dir ＝ proc (fn: file name) returns (string)
get_name ＝ proc (fn: file name) returns (string)
get_suffix ＝ proc (fn: file name) returns (string)
get_other ＝ proc (fn: file name) returns (string)
effects These operations return string forms of the components of
a file name. If the file name was created using the create op-
eration, the strings returned may be different than those given
as arguments to create|for example, they may be truncated
or case-converted.
parse ＝ proc (s: string) returns ( file name) signals (bad format)
effects This operation creates a file name given a string in the
system standard file name syntax.
unparse ＝ proc (fn: file name) returns (string)
effects This operation transforms a file name into the system stan-
dard file name syntax. We require that
parse(unparse(fn)) = fn
create(fn.dir, fn.name, fn.suffix, fn.other) = fn
for all file names fn. One implication of this rule is that there
can be no file name that can be created by create but not by
parse; if a system does have file names that have no string
representation in the system standard file name syntax, create
must reject those file names as having a bad format. Alter-
natively, the file name syntax can be extended so that it can
express all possible file names.
make output ＝ proc (fn: file name, suffix: string)
returns ( file name) signals (bad format)
effects This operation is used by programs that take input from a
file and write new files whose names are based on the input file
name. The operation transforms the file name into one that
is suitable for an output file. The transformation is done as
follows: (1) the suffix is set to suffix; (2) if the old directory is
not suitable for writing, it is set to null; (3) the name, if null
and meaningless, is set to “output”. (Examples of directories
that may not be suitable for writing are directories that involve
transferring files over a slow network.)
make temp ＝ proc (dir, prog, file id: string) returns ( file name)
signals (bad format)
effects This operation creates a file name appropriate for a tempo-
rary file, using the given preferred directory name (dir), pro-
gram name (prog), and file identifier ( file id). To be useful,
both prog and file id should be short and alphabetic. The re-
turned file name, when used as an argument to stream$open or
istream$open to open a new file for writing, is guaranteed to
create a new file and will not overwrite an existing file. Fur-
ther file name references to the created file should be made
using the name returned by the stream or istream get_name
operation.
equal ＝ proc (fn1, fn2: file name) returns (bool)
effects Returns true if and only if the two file names will unparse
to equal strings.
similar ＝ proc (fn1, fn2: file name) returns (bool)
effects The same as the equal operation.
copy ＝ proc (fn: file name) returns ( file name)
effects Returns a file name that is equal to fn.
end file name
Streams provide the means to read and write text files and
to perform some other operations on file objects. The opera-
tions allowed on any particular stream depend upon the access
mode. In addition, certain operations may have no effect in
some implementations.
When an operation cannot be performed because of an in-
correct access mode, implementation limitations, or proper-
ties of an individual file or device, the operation will signal
not possible (unless the description of the operation explicitly
says that the invocation will be ignored). End of file is sig-
naled by reading operations when there are no more characters
to read.
Streams provide operations to connect streams to strings, to
interact with a user at a terminal, and to record input/output
in one stream on another. These operations are described in
subsequent sections.
Operations
open ＝ proc (fn: file name, mode: string) returns (stream)
signals (not possible(string))
effects Opens a stream to fn in the given mode. The possible
access modes are "read", "write", and "append". If mode is
not one of these strings, not possible("bad access mode") is sig-
naled. In those cases where the system is able to detect that the
specified preexisting file is not a text file, not possible(\wrong
file type") is signaled. If mode is "read", the named file must
exist and a stream is returned upon which input operations
can be performed. If mode is "write", a new file is created
or an old file is rewritten. A stream is returned upon which
output operations can be performed. Write mode to storage
les should guarantee exclusive access to the file, if possible.
If mode is "append" and if the named file does not exist, one
is created. A stream is returned, positioned at the end of the
file, upon which output operations can be performed. Append
mode to storage files should guarantee exclusive access to the
file, if possible.
primary input ＝ proc( ) returns (stream)
effects Returns the “primary” input stream, suitable for reading.
This is usually a stream to the user's terminal, but may be set
by the operating system.
primary output ＝ proc( ) returns (stream)
effects Returns the “primary” output stream, suitable for writing.
This is usually a stream to the user's terminal, but may be set
by the operating system.
error output ＝ proc( ) returns (stream)
effects Returns the “primary” output stream for error messages,
suitable for writing. This is usually a stream to the user's
terminal, but may be set by the operating system.
can read ＝ proc (s: stream) returns (bool)
effects Returns true if input operations appear possible on s.
can write ＝ proc (s: stream) returns (bool)
effects Returns true if output operations appear possible on s.
getc ＝ proc (s: stream) returns (char)
signals (end of file, not possible(string))
modifies s.
effects Removes the next character from s and returns it. Signals
end of file if there are no more characters.
peekc ＝ proc (s: stream) returns (char)
signals (end of file, not possible(string))
effects This input operation is like getc, except that the character
is not removed from s.
empty ＝ proc (s: stream) returns (bool)
signals (not possible(string))
effects Returns true if and only if there are no more characters
in the stream. It is equivalent to an invocation of peekc, where
true is returned if peekc returns a character and false is returned
if peekc signals end of file. Thus in the case of terminals, for
example, this operation may wait until additional characters
have been typed by the user.
getl ＝ proc (s: stream) returns (string)
signals (end of file, not possible(string))
modifies s.
effects Reads and returns (the remainder of) the current input
line and reads but does not return the terminating newline (if
any). This operation signals end of file only if there are no
characters and end-of- file is detected.
gets ＝ proc (s: stream, term: string) returns (string)
signals (end of file, not possible(string))
modifies s.
effects Reads characters until a terminating character (one in
term) or end-of- file is seen. The characters up to the termina-
tor are returned; the terminator (if any) is left in the stream.
Signals end of file only if there are no characters and end-of- file
is detected.
putc ＝ proc (s: stream, c: (char) signals (not possible(string))
modifies s.
effects Appends c to s. Writing a newline indicates the end of the
current line.
putl ＝ proc (s: stream, str: string) signals (not possible(string))
modifies s.
effects Writes the characters of str onto s, followed by a newline.
puts ＝ proc (s: stream, str: string) signals (not possible(string))
modifies s.
effects Writes the characters in str using putc. Naturally it may
be somewhat more efficient than doing a series of individual
putcs.
putzero ＝ proc (s: stream, str: string, cnt: int)
signals (negative field width, not possible(string))
modifies s.
effects Outputs str. However, if the length of str is less than cnt,
outputs cnt length (str ) zeros before the first digit or period
in the string (or at the end, if no such characters).
putleft ＝ proc (s: stream, str: string, cnt: int)
signals (negative field width, not possible(string))
modifies s.
effects Outputs str. However, if the length of str is less than cnt,
outputs cnt length (str ) spaces after the string.
putright ＝ proc (s: stream, str: string, cnt: int)
signals (negative field width, not possible(string))
modifies s.
effects Outputs str. However, if the length of str is less than cnt,
outputs cnt length (str ) spaces before the string.
putspace ＝ proc (s: stream, cnt: int)
signals (negative field width, not possible(string))
modifies s.
effects Outputs cnt spaces on s.
putc image ＝ proc (s: stream, c: char) signals (not possible(string))
modifies s.
effects Like putc, except that an arbitrary character may be writ-
ten and the character is not interpreted by the CLU I/O sys-
tem. (For example, the ITS XGP program expects a text file
containing certain escape sequences. An escape sequence con-
sists of a special character followed by a xed number of ar-
bitrary characters. These characters could be the same as an
end-of-line mark, but they are recognized as data by their con-
text. On a record-oriented system, such characters would be
part of the data. In either case, writing a newline in image
mode would not be interpreted by the CLU system as indicat-
ing an end-of-line.) Characters written to a terminal stream
with this operation can be used to cause terminal-dependent
control functions.
getc image ＝ proc (s: stream) returns (char)
signals (end of file, not possible(string))
modifies s.
effects Provided to read escape sequences in text files, as might
be written using putc image. Using this operation inhibits the
recognition of end-of-line marks, where used. When reading
from a terminal stream, the character is not echoed and is not
subject to interpretation as an editing command.
puts image ＝ proc (s: stream, str: string) signals (not possible(string))
modifies s.
effects Writes the characters in str using putc image. Naturally
it may be somewhat more efficient than doing a series of individual putc images.
gets image ＝ proc (s: stream, str: string) returns (string)
signals (end of file, not possible(string))
modifies s.
effects Reads characters until a terminating character (one in str)
or end-of- file is seen. Using this operation inhibits the recog-
nition of end-of-line marks, where used. When reading from
a terminal stream, the characters read are not echoed and are
not subject to interpretation as editing commands. The char-
acters up to the terminator are returned; the terminator (if
any) is left in the stream. This operation signals end of file
only if there are no characters and end-of- file is detected.
close ＝ proc (s: stream) signals (not possible(string))
modifies s.
effects Attempts to terminate I/O and remove the association
between the stream and the file. If successful, further use of
operations that signal not possible will signal not possible. This
operation will fail if buffered output cannot be written.
abort ＝ proc (s: stream)
modifies s.
effects Terminates I/O and removes the association between the
stream and the file. If buffered output cannot be written, it
will be lost, and if a new file is being written, it may or may
not exist.
is closed ＝ proc (s: stream) returns (bool)
effects Returns true if and only if the stream is closed.
is terminal ＝ proc (s: stream) returns (bool)
effects Returns true if and only if the stream is attached to an
interactive terminal (see below).
get_lineno ＝ proc (s: stream) returns (int)
signals (end of file, not possible(string))
effects Returns the line number of the current (being or about
to be read) line. If the system maintains explicit line numbers
in the file, said line numbers are returned. Otherwise lines are
implicitly numbered, starting with 1.
set_lineno ＝ proc (s: stream, num: int)
signals (not possible(string))
modifies s.
effects If the system maintains explicit line numbers in the file,
sets the line number of the next (not yet started) line to num.
Otherwise it is ignored.
get_line_length ＝ proc (s: stream) returns (int)
signals (no limit)
effects If the file or device to which the stream is attached has
a natural maximum line length, that length is returned. Oth-
erwise no limit is signaled. The line length does not include
newline characters.
get_page_length ＝ proc (s: stream) returns (int)
signals (no limit)
effects If the device to which the stream is attached has a natu-
ral maximum page length, that length is returned. Otherwise
no limit is signaled. Storage files will generally not have page
lengths.
get_date ＝ proc (s: stream) returns (date)
signals (not possible(string))
effects Returns the date of the last modification of the
corresponding storage file.
set_date ＝ proc (s: stream, d: date) signals (not possible(string))
modifies s.
effects Sets the modification date of the corresponding storage
file. The modification date is set automatically when a file is
opened in "write" or "append" mode.
get_name ＝ proc (s: stream) returns ( file name)
signals (not possible(string))
effects Returns the name of the corresponding file. It may be
different than the name used to open the file, in that defaults
have been resolved and link indirections have been followed.
set_output_buffered ＝ proc (s: stream, b: bool)
signals (not possible(string))
modifies s.
effects Sets the output buffering mode. Normally output may
be arbitrarily buffered before it is actually written out. Un-
buffered output can be used on some systems to decrease the
amount of information lost if the program terminates prema-
turely. For terminal streams, unbuffered output is useful in
programs that output incomplete lines as they are working to
allow the user to watch the progress of the program.
get_output_buffered ＝ proc (s: stream) returns (bool)
effects Returns true if and only if output to the stream is
being buffered.
equal ＝ proc (s1, s2: stream) returns (bool)
similar ＝ proc (s1, s2: stream) returns (bool)
effects Returns true if and only both arguments are the same stream.
copy ＝ proc (s: stream) returns (stream)
effects Returns a stream equal to s.
String Input/Output
It is occasionally useful to be able to construct a stream that is not con-
nected to a file, but instead simply collects the output text into a string.
Conversely, it is occasionally useful to be able to take a string and convert
it into an input stream so that it can be given to a procedure that expects
a stream. String streams allow these functions to be performed. A string
stream does not have a file name, a creation date, a maximum line or page
length, or explicit line numbers. The following stream operations deal with
string streams:
create input ＝ proc (s: string) returns (stream)
effects An input stream is created that will return the characters
in the given string. If the string is nonempty and does not end
with a newline, an extra terminating newline will be appended
to the string.
create output ＝ proc( ) returns (stream)
effects An output stream is created that will collect output text
in an internal buffer. The text may be extracted using the
get_contents operation.
get_contents ＝ proc (s: stream) returns (string) signals (not possible(string))
effects Returns the text that has so far been output to s. Signals
not possible if the stream was not created by create output.
Terminal I/O
Terminal I/O is performed via streams attached to interactive terminals.
Such a stream is normally obtained via the primary input and primary output
operations. A terminal stream is capable of performing both input and out-
put operations. A number of additional operations are possible on terminal
streams, and a number of standard operations have special interpretations.
Terminal input will normally be buffered so that the user can perform
editing functions, such as deleting the last character on the current line,
deleting the current line, redisplaying the current line, and redisplaying the
current line after clearing the screen. Specific characters for causing these
functions are not suggested. In addition, some means must be provided for
the user to indicate end-of- file, so that a terminal stream can be given to
a program that expects an arbitrary stream and reads it until end-of- file.
The end-of- file status of a stream is cleared by the reset operation.
Input buffering is normally provided on a line basis. When a program
rst asks for input (using getc, for example), an entire line of input is read
from the terminal and stored in an internal buffer. Further input is not
taken from the terminal until the existing buffered input is read.
New input caused to be read by the getbuf operation will be buffered
as a unit. Thus one can read in a large amount of text and allow edit-
ing of that entire text. In addition, when the internal buffer is empty,
the getc image operation will read a character directly from the terminal,
without interpreting it or echoing it.
The user may specify a prompt string to be printed whenever a new
buffer of input is requested from the terminal; the prompt string will be
reprinted when redisplay of the current line is requested by the user. How-
ever, if new input is requested just when an un nished line has been output
to the terminal, that un nished line is used instead as a prompt.
The routine putc image can be used to cause control functions, such as
"\007" (bell) and \np" (new-page or clear-screen). We cannot guarantee
the effect caused by any particular control character, but we recommend
that the standard ASCII interpretation of control characters be supported
wherever possible.
Terminal output may be buffered by the system up to one line at a time.
However, the buffer must be ushed when new input is requested from
the terminal. Terminal streams do not have modification dates, but they
should have file names and implicit line numbers. The following additional
operations are provided:
getbuf ＝ proc (s: stream, str: string) returns (string)
signals (end of file, not possible(string))
modifies s.
effects This operation is the same as gets, but for terminals with
input buffering, the new input read by getbuf is buffered as a
unit, rather than a line at a time, allowing input editing of the
entire text.
get_prompt ＝ proc (s: stream) returns (string)
effects Returns the current prompt string. The prompt string is
initially empty (""). The empty string is returned for nonterminal streams.
set_prompt ＝ proc (s: stream. str: string)
modifies s.
effects Sets the string to be used for prompting to str. For non-
terminal streams there is no effect.
get_input_buffered ＝ proc (s: stream) returns (bool)
effects Returns true if and only if s is attached to a terminal and
input is being buffered.
set_input_buffered ＝ proc (s: stream, b: bool) signals (not possible(string))
modifies s.
effects Sets the input buffering mode. Only buffered terminal
input is subject to editing.
Scripting
Streams provide a mechanism for recording the input and/or output from
one stream onto any number of other streams. This can be particularly
useful in recording terminal sessions. The following additional operations
are provided:
add script ＝ proc (s1, s2: stream) signals (script failed)
modifies s1.
effects Adds s2 as a script stream of s1. All subsequent input
from and output to s1 will also be output to s2. Not possible
exceptions that arise in actually outputting to s2 will be ig-
nored. This operation will fail if s2 cannot be written to or if
either stream is a direct or indirect script stream of the other.
rem script ＝ proc (s1, s2: stream)
modifies s2.
effects Removes, but does not close, s2 as a direct script
stream of s1.
unscript ＝ proc (s: stream)
effects Removes, but does not close, all direct script streams
of s.
end stream
Istreams provide the means to read and write image files and
to perform some other operations on file objects. The opera-
tions allowed on any particular istream depend upon the access
mode. In addition, certain operations may be null in some im-
plementations.
When an operation cannot be performed, because of an in-
correct access mode, implementation limitations, or proper-
ties of an individual file or device, the operation will signal
not possible (unless the description of the operation explicitly
says that the invocation will be ignored).
Actual reading and writing of objects is performed by encode
and decode operations of the types involved. All of the built-in
CLU types and type generators (except the routine type gen-
erators), and the file name and date types, provide these oper-
ations. Designers of abstract types are encouraged to provide
them also. The type specifications of the encode and decode
operations for a type T are
encode ＝ proc (c: T, s: istream)
signals (not possible(string))
decode ＝ proc (s: istream) returns (T)
signals (end of file not possible(string))
For parameterized types, encode will have a where clause re-
quiring encode operations for all components, and decode will
have a where clause requiring decode operations for all com-
ponents.
The encode operations are output operations. They write an
encoding of the given object onto the istream. The decode
operations are input operations. They decode the information
written by encode operations and return an object “similar” to
the one encoded. If the sequence of decode operations used to
read a file does not match the sequence of encode operations
used to write it, meaningless objects may be returned. The
system may in some cases be able to detect this condition, in
which case the decode operation will signal not possible(\bad
format"). The system is not guaranteed to detect all such
errors.
Operations
open ＝ proc (fn: file name, mode: string)
signals (not possible(string))
effects The possible access modes are "read", "write", and "append".
If mode is not one of these strings, not possible(\bad
access mode") is signaled. In those cases where the system
is able to detect that the specified preexisting file is not an
image file, not possible("wrong file type") is signaled. If mode
is "read", the named file must exist. If the file exists, an image
stream is returned upon which decode operations can be
performed. If mode is "write", a new file is created or an old
file is rewritten. An image stream is returned upon which encode
operations can be performed. Write mode to storage files
should guarantee exclusive access to the file, if possible. If
mode is "append" and if the named file does not exist, one is
created. An image stream is returned, positioned at the end of
the file, upon which encode operations can be performed. Append
mode to storage files should guarantee exclusive access
to the file, if possible.
can read ＝ proc (s: istream) returns (bool)
effects Returns true if decode operations appear possible on s.
can write ＝ proc (s: istream) returns (bool)
effects Returns true if encode operations appear possible on s.
empty ＝ proc (istream) returns (bool)
effects Returns true if and only if there are no more objects in
the associated file.
reset ＝ proc (s: istream) signals (not possible(string))
effects Resets s so that the next input or output operation will
read or write the first item in the file.
ush ＝ proc (s: istream) signals (not possible(string))
effects Writes any buffered output to the associated file, if possible.
get_date ＝ proc (s: istream) returns (date) signals (not possible(string))
effects Returns the date of the last modification of the corresponding storage file.
set_date ＝ proc (s: istream, d: date) signals (not possible(string))
modifies s.
effects Sets the modification date of the corresponding storage
file. The modification date is set automatically when a file is
opened in "write" or "append" mode.
get_name ＝ proc (s: istream) returns ( file name)
effects Returns the name of the corresponding file. It may be
different than the name used to open the file, in that defaults
have been resolved and link indirections have been followed.
close ＝ proc (s: istream) signals (not possible(string))
modifies s.
effects Attempts to terminate I/O and remove the association
between s and the file. If successful, further use of operations
that signal not possible will signal not possible. This operation
will fail if buffered output cannot be written.
abort ＝ proc (s: istream)
modifies s.
effects Terminates I/O and removes the association between the
istream and the file. If buffered output cannot be written, it
will be lost, and if a new file is being written, it may or may
not exist.
is closed ＝ proc (s: istream) returns (bool)
effects Returns true if and only if s is closed.
equal ＝ proc (s1, s2: istream) returns (bool)
effects Returns true if and only both arguments are the same istream.
similar ＝ proc (s1, s2: istream) returns (bool)
effects Returns true if and only both arguments are the same istream.
copy ＝ proc (s: istream) returns (istream)
effects Returns a stream that is equal to s.
end istream
Dates are immutable objects that represent calendar dates and times.
Operations
create ＝ proc (day, month, year, hour, minute, second: int)
returns (date) signals (bad format)
effects Creates the specified date. The ranges for the arguments
are (1 .. 31), (1 .. 12), (1 .. ), (0 .. 23), (0 .. 59), (0 .. 59),
respectively; bad format is signaled if an argument is out of
range.
get_all ＝ proc (d: date) returns (int, int, int, int, int, int)
effects Returns the components in the same order as given to create.
get_day ＝ proc (d: date) returns (int)
get_month ＝ proc (d: date) returns (int)
get_year ＝ proc (d: date) returns (int)
get_hour ＝ proc (d: date) returns (int)
get_minute ＝ proc (d: date) returns (int)
get_second ＝ proc (d: date) returns (int)
effects Returns the specified component of d.
unparse ＝ proc (d: date) returns (string)
effects Returns a string representation of d|for example, \12
January 1978 01:36:59".
unparse date ＝ proc (d: date) returns (string)
effects Returns a string representation of the date part of d|for
example, "12 January 1978".
unparse time ＝ proc (d: date) returns (string)
effects Returns a string representation of the time part of d|for
example, "01:36:59".
lt ＝ proc (d1, d2: date) returns (bool))
le ＝ proc (d1, d2: date) returns (bool)
ge ＝ proc (d1, d2: date) returns (bool)
gt ＝ proc (d1, d2: date) returns (bool)
equal ＝ proc (d1, d2: date) returns (bool)
effects The obvious relational operations;
if d1 < d2 , then d1 occurs earlier than d2.
similar ＝ proc (d1, d2: date) returns (bool)
effects The same as the equal operation.
copy ＝ proc (d: date) returns (date)
effects Returns a date equal to d.
end date