IPVectorImpl.mesa
Last edited by:
Doug Wyatt, March 1, 1984 4:50:45 pm PST
DIRECTORY
IP USING [Any, AnyFromInteger, Array, ArrayRep, EqName, Integer, IntegerFromAny, MasterError, MasterWarning, maxInteger, Pop, PopInteger, PopVector, Push, PushBool, PushInteger, PushVector, State, Vector, VectorRep, VectorShape],
IPBase USING [];
IPVectorImpl: CEDAR PROGRAM
IMPORTS IP
EXPORTS IP, IPBase
~ BEGIN OPEN IP;
Shape: PUBLIC PROC[v: Vector] RETURNS[VectorShape] ~ { RETURN[v.shape[v.data]] };
Get: PUBLIC PROC[v: Vector, j: Integer] RETURNS[Any] ~ {
IF v.get#NIL THEN RETURN[v.get[v.data, j]]
ELSE RETURN[AnyFromInteger[v.getInteger[v.data, j]]];
};
GetInteger: PUBLIC PROC[v: Vector, j: Integer] RETURNS[Integer] ~ {
IF v.getInteger#NIL THEN RETURN[v.getInteger[v.data, j]]
ELSE RETURN[IntegerFromAny[v.get[v.data, j]]];
};
GetProp: PUBLIC PROC[v: Vector, propName: Any] RETURNS[value: Any, found: BOOL] ~ {
IF v.getProp#NIL THEN [value, found] ← v.getProp[v.data, propName]
ELSE {
shape: VectorShape ~ Shape[v];
IF (shape.n MOD 2)#0 THEN MasterError[$invalidArgs, "Property vector has illegal shape."];
FOR i: Integer ← shape.l, i+2 WHILE i<(shape.l+shape.n) DO
IF EqName[Get[v, i], propName] THEN RETURN[Get[v, i+1], TRUE];
ENDLOOP;
RETURN[NIL, FALSE];
};
};
GetP: PUBLIC PROC[v: Vector, propName: Any] RETURNS[value: Any] ~ {
found: BOOL; [value, found] ← GetProp[v, propName];
IF NOT found THEN MasterError[$undefinedProperty, "Undefined property."];
};
RunSize: PUBLIC PROC[r: Vector] RETURNS[Integer] ~ {
shape: VectorShape ~ Shape[r];
s: Integer ← 0; -- sum of the run lengths
IF shape.l#0 OR (shape.n MOD 2)#0 THEN
MasterError[$invalidArgs, "Run encoded vector has illegal shape."];
FOR j: Integer ← 0, j+2 WHILE j<shape.n DO
c: Integer ~ GetInteger[r, j];
IF c<=(maxInteger-s) THEN s ← s + c
ELSE MasterError[$limitExceeded, "Result of *RUNSIZE exceeds maxInteger."];
ENDLOOP;
RETURN[s];
};
RunGet: PUBLIC PROC[r: Vector, i: Integer] RETURNS[Any] ~ {
shape: VectorShape ~ Shape[r];
s: Integer ← 0; -- sum of the run lengths
IF shape.l#0 OR (shape.n MOD 2)#0 THEN
MasterError[$invalidArgs, "Run encoded vector has illegal shape."];
IF i<1 THEN MasterError[$boundsFault, "Index too small for *RUNGET."];
FOR j: Integer ← 0, j+2 WHILE j<shape.n DO
c: Integer ~ GetInteger[r, j];
IF (i-s)<=c THEN RETURN[Get[r, j+1]];
IF c<=(maxInteger-s) THEN s ← s + c
ELSE MasterError[$limitExceeded, "Result of *RUNSIZE exceeds maxInteger."];
ENDLOOP;
MasterError[$boundsFault, "Index too large for *RUNGET."];
RETURN[NIL];
};
Null vectors (used for top frame, empty vector)
NullData: TYPE ~ REF NullDataRep;
NullDataRep: TYPE ~ RECORD[shape: VectorShape];
NullShape: PROC[data: REF] RETURNS[VectorShape] ~ {
d: NullData ~ NARROW[data];
RETURN[d.shape];
};
NullGet: PROC[data: REF, j: Integer] RETURNS[Any] ~ {
d: NullData ~ NARROW[data];
shape: VectorShape ~ d.shape;
IF j NOT IN[shape.l..shape.l+shape.n) THEN
MasterError[$boundsFault, "Vector index out of bounds."];
RETURN[NIL];
};
NullVector: PUBLIC PROC[shape: VectorShape] RETURNS[Vector] ~ {
d: NullData ~ NEW[NullDataRep ← [shape: shape]];
RETURN[NEW[VectorRep ← [class: $Null, shape: NullShape, get: NullGet, data: d]]];
};
maxVecSize: NAT ~ (LAST[NAT]-SIZE[ArrayRep[0]])/SIZE[Any];
ANew: PROC[shape: VectorShape] RETURNS[a: Array ← NIL] ~ {
IF shape.n>0 AND (shape.n-1)>(maxInteger-shape.l) THEN
MasterError[$invalidArgs, "Illegal shape for an Array."];
IF shape.n>maxVecSize THEN
MasterError[$limitExceeded, "Array size exceeds maxVecSize."];
a ← NEW[ArrayRep[shape.n] ← [shape: shape, array: ]];
FOR i: NAT IN[0..a.size) DO a[i] ← NIL ENDLOOP;
};
ACopy: PROC[a: Array] RETURNS[Array] ~ {
new: Array ~ NEW[ArrayRep[a.size] ← [shape: a.shape, array: ]];
FOR i: NAT IN[0..new.size) DO new[i] ← a[i] ENDLOOP;
RETURN[new];
};
AGet: PUBLIC PROC[a: Array, n: Integer] RETURNS[x: Any ← NIL] ~ {
IF n IN[a.shape.l .. a.shape.l+a.shape.n) THEN x ← a[n-a.shape.l]
ELSE MasterError[$boundsFault, "Index out of bounds."];
};
ASet: PUBLIC PROC[a: Array, x: Any, n: Integer] ~ {
IF n IN[a.shape.l .. a.shape.l+a.shape.n) THEN a[n-a.shape.l] ← x
ELSE MasterError[$boundsFault, "Index out of bounds."];
};
ArrayShape: PROC[data: REF] RETURNS[VectorShape] ~ {
a: Array ~ NARROW[data];
RETURN[a.shape];
};
ArrayGet: PROC[data: REF, j: Integer] RETURNS[Any] ~ {
a: Array ~ NARROW[data];
RETURN[AGet[a, j]]
};
ArrayCreate: PROC[a: Array] RETURNS[Vector] ~ {
RETURN[NEW[VectorRep ← [class: $Array,
shape: ArrayShape, get: ArrayGet, data: a]]];
};
VectorFromArray: PUBLIC PROC[a: Array] RETURNS[Vector] ~ {
RETURN[ArrayCreate[ACopy[a]]];
};
ArrayFromVector: PUBLIC PROC[v: Vector] RETURNS[Array] ~ {
IF v.class=$Array THEN RETURN[ACopy[NARROW[v.data, Array]]]
ELSE {
shape: VectorShape ~ Shape[v];
a: Array ~ ANew[shape];
FOR i: Integer IN[shape.l..shape.l+shape.n) DO ASet[a, Get[v, i], i] ENDLOOP;
RETURN[a];
};
};
Merged: TYPE ~ REF MergedRep;
MergedRep: TYPE ~ RECORD[v1, v2: Vector];
MergedShape: PROC[data: REF] RETURNS[VectorShape] ~ {
m: Merged ~ NARROW[data];
MasterError[$undefinedOperation, "SHAPE is undefined for the result of MERGEPROP."];
RETURN[[0, 0]];
};
MergedGet: PROC[data: REF, j: Integer] RETURNS[Any] ~ {
m: Merged ~ NARROW[data];
MasterError[$undefinedOperation, "GET is undefined for the result of MERGEPROP."];
RETURN[NIL];
};
MergedGetProp: PROC[data: REF, propName: Any] RETURNS[value: Any, found: BOOL] ~ {
m: Merged ~ NARROW[data];
[value, found] ← GetProp[m.v2, propName];
IF NOT found THEN [value, found] ← GetProp[m.v1, propName];
};
MergeProp: PUBLIC PROC[v1, v2: Vector] RETURNS[Vector] ~ {
m: Merged ~ NEW[MergedRep ← [v1: v1, v2: v2]];
RETURN[NEW[VectorRep ← [class: $Merged,
shape: MergedShape, get: MergedGet, getProp: MergedGetProp, data: m]]];
};
CharAction: TYPE ~ PROC[c: CARDINAL] RETURNS[quit: BOOLFALSE];
StringMap: PROC[text: REF TEXT, action: CharAction] RETURNS[BOOL] ~ {
offset: CARDINAL ← 0;
state: {run, escape, escape2, extended, extended2} ← run;
FOR i: NAT IN[0..text.length) DO
b: [0..255] ~ LOOPHOLE[text[i]];
SELECT state FROM
run => IF b=255 THEN state ← escape ELSE IF action[offset+b] THEN RETURN[TRUE];
escape => IF b=255 THEN state ← escape2 ELSE { offset ← b*256; state ← run };
escape2 => IF b=0 THEN state ← extended ELSE ERROR;
extended => IF b=255 THEN state ← escape ELSE { offset ← b*256; state ← extended2 };
extended2 => { IF action[offset+b] THEN RETURN[TRUE]; state ← extended };
ENDCASE;
ENDLOOP;
IF NOT(state=run OR state=extended) THEN
MasterWarning[$illegalString, "Encoded string ended in wrong state."];
RETURN[FALSE];
};
StringShape: PROC[data: REF] RETURNS[VectorShape] ~ {
text: REF TEXT ~ NARROW[data];
n: Integer ← 0;
action: CharAction ~ { n ← n+1 };
[] ← StringMap[text, action];
RETURN[[l: 0, n: n]];
};
StringGetInteger: PROC[data: REF, j: Integer] RETURNS[result: Integer] ~ {
text: REF TEXT ~ NARROW[data];
n: Integer ← 0;
action: CharAction ~ { IF n=j THEN { result ← c; RETURN[TRUE] } ELSE n ← n+1 };
IF StringMap[text, action] THEN NULL
ELSE MasterError[$boundsFault, "Invalid index for string."];
};
VectorFromString: PUBLIC PROC[text: REF TEXT] RETURNS[Vector] ~ {
len: NAT ~ text.length; string: REF TEXT ~ NEW[TEXT[len]];
FOR i: NAT IN[0..len) DO string[i] ← text[i] ENDLOOP; string.length ← len;
RETURN[NEW[VectorRep ← [class: $String,
shape: StringShape, getInteger: StringGetInteger, data: string]]];
};
MakeVec: PROC[self: State, shape: VectorShape] RETURNS[Vector] ~ {
a: Array ~ ANew[shape];
FOR i: NAT DECREASING IN[0..a.size) DO a[i] ← Pop[self] ENDLOOP;
RETURN[ArrayCreate[a]];
};
ApplyGET: PUBLIC PROC[self: State] ~ {
j: Integer ~ PopInteger[self];
v: Vector ~ PopVector[self];
Push[self, Get[v, j]];
};
ApplyMAKEVECLU: PUBLIC PROC[self: State] ~ {
u: Integer ~ PopInteger[self];
l: Integer ~ PopInteger[self];
n: INT ~ u-l+1;
IF n IN[0..maxInteger] THEN PushVector[self, MakeVec[self, [l: l, n: n]]]
ELSE MasterError[$invalidArgs, "Illegal vector bounds."];
};
ApplyMAKEVEC: PUBLIC PROC[self: State] ~ {
n: Integer ~ PopInteger[self];
PushVector[self, MakeVec[self, [l: 0, n: n]]];
};
ApplySHAPE: PUBLIC PROC[self: State] ~ {
v: Vector ~ PopVector[self];
shape: VectorShape ~ Shape[v];
PushInteger[self, shape.l]; PushInteger[self, shape.n];
};
ApplyOPENVEC: PUBLIC PROC[self: State] ~ {
v: Vector ~ PopVector[self];
shape: VectorShape ~ Shape[v];
FOR i: Integer IN[shape.l..shape.l+shape.n) DO Push[self, Get[v, i]] ENDLOOP;
};
ApplyGETPROP: PUBLIC PROC[self: State] ~ {
propName: Any ~ Pop[self];
v: Vector ~ PopVector[self];
value: Any; found: BOOL;
[value, found] ← GetProp[v, propName];
IF found THEN Push[self, value];
PushBool[self, found];
};
ApplyGETP: PUBLIC PROC[self: State] ~ {
propName: Any ~ Pop[self];
v: Vector ~ PopVector[self];
Push[self, GetP[v, propName]];
};
ApplyMERGEPROP: PUBLIC PROC[self: State] ~ {
v2: Vector ~ PopVector[self];
v1: Vector ~ PopVector[self];
PushVector[self, MergeProp[v1, v2]];
};
END.