Copyright (C) 1994, Digital Equipment Corp.
<* PRAGMA SPEC*>
Sequence is a generic interface defining extensible sequences.
Elements can be added or removed at either end of a sequence; they
can also be accessed or updated at specified indexes. The expected
cost of every method of a sequence is constant.
\index{stack: {\tt Sequence} generic interface}
\index{queue: {\tt Sequence} generic interface}
\index{deque: {\tt Sequence} generic interface}
GENERIC INTERFACESequence (Elem);
WhereElem.Tis a type that is not an open array type andElemcontains
CONST Brand = <text-constant>;Brandmust be a text constant. It will be used to construct a brand for the opaque typeSequence.Tand any generic types instantiated with theSequenceinterface. For a non-generic interface, we recommend choosing the name of the interface.
CONST
Brand = "(Sequence " & Elem.Brand & ")";
TYPE
T <: Public;
Public = OBJECT METHODS
init(sizeHint: CARDINAL := 5): T;
fromArray(READONLY a: ARRAY OF Elem.T): T;
addhi(READONLY x: Elem.T);
addlo(READONLY x: Elem.T);
remhi(): Elem.T;
remlo(): Elem.T;
put(i: CARDINAL; READONLY x: Elem.T);
size(): CARDINAL;
gethi(): Elem.T;
getlo(): Elem.T;
get(i: CARDINAL): Elem.T
END;
A Sequence(Elem).T (or just a {\it sequence}) represents an
extensible sequence of Elem.Ts.
The first group of methods have side effects on the sequence. The call
s.init(sizeHint)
initializes s to be the empty sequence. Furthermore init
assumes that at least sizeHint elements will be added to the
sequence; these operations may be executed more efficiently than if
sizeHint was defaulted. The call
s.fromArray(a)
initializes s to be the sequence with elements
a[0],~...,~a[LAST(a)]. The call
s.addhi(x)
appends x to the end of s. Thus it does not change the index
of any existing element. The call
s.addlo(x)
appends x to the front of s. Thus it increases the index of
all existing elements by one. The call
s.remhi()
removes and returns the last element of s. Thus it does not
change the index of any of s's other elements. If s is empty,
s.remhi() causes a checked runtime error. The call
s.remlo()
removes and returns the first element of s. Thus it decreases
the index of all other elements of s by one. If s is empty,
s.remlo() causes a checked runtime error. The call
s.put(i, x)
replaces element i of s with x. Element 0 is the first
element. It is a checked runtime error unless i is less than
s.size().
The second group of methods have no side effect on the sequence. The call
s.size()
returns the number of elements in s. The call
s.get(i)
returns element i of s. It is a checked runtime error unless
i is less than s.size(). The call
s.gethi()
returns the last element of s; that is, it is equivalent to
s.get(s.size()-1). The call
s.getlo()
returns the first element of s; that is, it is equivalent to
s.get(0).
PROCEDURE Cat(s, t: T): T;
Return a sequence whose elements are the concatenation ofsandt.
PROCEDURE Sub(s: T; start: CARDINAL;
length: CARDINAL := LAST(CARDINAL)): T;
Return a sub-sequence ofs: empty ifstart >= t.size()orlength = 0; otherwise the subsequence ranging fromstartto the minimum ofstart+length-1ands.size()-1.
Cat and Sub create new sequences; they have no side-effects.
\smallskip Sequences are unmonitored: a client accessing a sequence from multiple threads must ensure that if two operations are active concurrently, then neither of them has side effects on the sequence.
ESC Specifications.
<*SPEC VAR Valid: MAP T TO BOOLEAN *>
<*SPEC VAR Data: MAP T TO SEQ[Elem.T]*>
<*SPEC T.init(t, sizeHint)
MODIFIES Valid[t], Data[t]
ENSURES RES = t AND Valid'[t] AND NUMBER(Data'[t]) = 0 *>
<*SPEC T.fromArray(t, a)
MODIFIES Valid[t], Data[t]
ENSURES RES = t AND Valid'[t] AND NUMBER(Data'[t]) = NUMBER(a)
AND (ALL [i: INTEGER] (0 <= i AND i < NUMBER(a)) IMPLIES
Data'[t][i] = a[i]) *>
<*SPEC T.addhi(t, x)
MODIFIES Data[t]
REQUIRES Valid[t]
ENSURES NUMBER(Data'[t]) = NUMBER(Data[t])+1
AND (ALL [i: INTEGER] 0 <= i AND i < NUMBER(Data[t]) IMPLIES
Data'[t][i] = Data[t][i])
AND Data'[t][NUMBER(Data[t])] = x *>
<*SPEC T.addlo(t, x)
MODIFIES Data[t]
REQUIRES Valid[t]
ENSURES NUMBER(Data'[t]) = NUMBER(Data[t])+1
AND Data'[t][0] = x
AND (ALL [i: CARDINAL] (0 <= i AND i < NUMBER(Data[t])) IMPLIES
Data'[t][i+1] = Data[t][i]) *>
<*SPEC T.remhi(t)
MODIFIES Data[t]
REQUIRES Valid[t] AND NUMBER(Data[t]) > 0
ENSURES NUMBER(Data'[t]) = NUMBER(Data[t])-1
AND (ALL [i: INTEGER] (0 <= i AND i < NUMBER(Data'[t])) IMPLIES
Data'[t][i] = Data[t][i]) *>
<*SPEC T.remlo(t)
MODIFIES Data[t]
REQUIRES Valid[t] AND NUMBER(Data[t]) > 0
ENSURES NUMBER(Data'[t]) = NUMBER(Data[t])-1
AND (ALL [i: INTEGER] (0 <= i AND i < NUMBER(Data'[t])) IMPLIES
Data'[t][i] = Data[t][i+1]) *>
<*SPEC T.put(t, i, x)
MODIFIES Data[t][i]
REQUIRES Valid[t] AND i < NUMBER(Data[t])
ENSURES Data'[t][i] = x
*>
ENSURES Data'[t][i] = x AND NUMBER(Data'[t]) = NUMBER(Data[t]) *>
<*SPEC T.size(t)
REQUIRES Valid[t]
ENSURES RES = NUMBER(Data[t]) *>
<*SPEC T.gethi(t)
REQUIRES Valid[t] AND NUMBER(Data[t]) > 0
ENSURES RES = Data[t][NUMBER(Data[t])-1] *>
<*SPEC T.getlo(t)
REQUIRES Valid[t] AND NUMBER(Data[t]) > 0
ENSURES RES = Data[t][0] *>
<*SPEC T.get(t, i)
REQUIRES Valid[t] AND i < NUMBER(Data[t])
ENSURES RES = Data[t][i] *>
<*SPEC Cat(s, t)
MODIFIES Data[RES], Valid[RES]
REQUIRES Valid[s] AND Valid[t]
ENSURES FRESH(RES) AND Valid'[RES]
AND (ALL [i: INTEGER]
(0 <= i AND i < NUMBER(Data'[RES])) IMPLIES
Data'[RES][i] = CONCAT(Data[s], Data[t])[i])
*>
<*SPEC Sub(s, start, length)
MODIFIES Data[RES], Valid[RES]
REQUIRES Valid[s]
ENSURES Valid'[RES] AND FRESH(RES) AND
(ALL [i: INTEGER]
(0 <= i AND i < MIN(length, NUMBER(Data[s]) - start)) IMPLIES
Data'[RES][i] = SUBARRAY(Data[s],
MAX(0, MIN(start,
NUMBER(Data[s])-1)),
MIN(length, NUMBER(Data[s])
-start))[i])
*>
END Sequence.