Conversion and IO
Recast:
PUBLIC AC.BinaryOp = {
Args are a StructureElement and a Structure
thisSequenceStructure: Object ← secondArg;
thisSequenceStructureData: SequenceStructureData ← NARROW[thisSequenceStructure.data];
thisStructureElementStructure: Object ← thisSequenceStructureData.elementStructure;
canRecastMethod: Method ← AC.LookupMethodInStructure[$canRecast, thisStructureElementStructure];
recastMethod: Method ← AC.LookupMethodInStructure[$recast, thisStructureElementStructure];
flag: BOOL;
IF AC.StructureEqual[firstArg.class, secondArg] THEN RETURN[firstArg]; -- nothing to do
See if can recast firstArg into thisStructureElementStructure
flag ← AC.ApplyPredNoLkpNoRecast[canRecastMethod,LIST[firstArg.class, thisStructureElementStructure] ];
IF flag
THEN {
recastElement: Object ← AC.ApplyNoLkpNoRecastObject[recastMethod, LIST[firstArg, thisStructureElementStructure] ];
RETURN[ MakeSequence[LIST[recastElement], thisSequenceStructure] ];
};
If firstArg is a Sequence, see if can recast its elementStructure into thisStructureElementStructure; if so, recast all its elements.
IF
AC.LookupMethodInStructure[$sequenceStructure, firstArg.class]#
NIL
THEN {
inputSequenceStructure: Object ← firstArg.class;
inputSequenceStructureData: SequenceStructureData ← NARROW[inputSequenceStructure.data];
inputStructureElementStructure: Object ← inputSequenceStructureData.elementStructure;
argData: SequenceData ← NARROW[firstArg.data];
resultData: SequenceData;
flag ← AC.ApplyPredNoLkpNoRecast[canRecastMethod,LIST[inputStructureElementStructure, thisStructureElementStructure] ];
IF NOT flag THEN RETURN[NIL]; -- give up
resultData ← NEW[SequenceDataRec[argData.lengthPlus1 - 1] ];
FOR i:
NAT
IN [1..argData.lengthPlus1)
DO
resultData[i] ← AC.ApplyNoLkpNoRecastObject[recastMethod, LIST[argData[i], thisStructureElementStructure] ];
ENDLOOP;
RETURN[
NEW[
AC.ObjectRec ← [
flavor: StructureElement,
class: thisSequenceStructure,
data: resultData
] ] ];
};
Can't do it
RETURN[NIL];
};
CanRecast:
PUBLIC AC.BinaryPredicate = {
Args are either [Structure, Structure] or [StructureElement, Structure]
thisSequenceStructure: Object ← secondArg;
thisSequenceStructureData: SequenceStructureData ← NARROW[thisSequenceStructure.data];
thisStructureElementStructure: Object ← thisSequenceStructureData.elementStructure;
canRecastMethod: Method ← AC.LookupMethodInStructure[$canRecast, thisStructureElementStructure];
flag: BOOL;
firstArgStructure: Object ← IF firstArg.flavor = StructureElement THEN firstArg.class ELSE IF firstArg.flavor = Structure THEN firstArg ELSE ERROR;
IF AC.StructureEqual[firstArgStructure, thisSequenceStructure] THEN RETURN[TRUE];
flag ← AC.ApplyPredNoLkpNoRecast[canRecastMethod,LIST[firstArgStructure, thisStructureElementStructure] ];
IF flag THEN RETURN[TRUE];
IF
AC.LookupMethodInStructure[$sequenceStructure, firstArgStructure]#
NIL
THEN {
inputSequenceStructure: Object ← firstArgStructure;
inputSequenceStructureData: SequenceStructureData ← NARROW[inputSequenceStructure.data];
inputStructureElementStructure: Object ← inputSequenceStructureData.elementStructure;
flag ← AC.ApplyPredNoLkpNoRecast[canRecastMethod,LIST[inputStructureElementStructure, thisStructureElementStructure] ];
RETURN[flag];
};
RETURN[FALSE];
};
ToExpr:
PUBLIC AC.ToExprOp = {
sequenceData: SequenceData ← NARROW[in.data];
sequenceStructureData: SequenceStructureData ← NARROW[in.class.data];
size: CARDINAL ← sequenceData.lengthPlus1 - 1;
outColumn: LIST OF MathExpr.EXPR ← NIL;
method: Method ← AC.LookupMethodInStructure[$toExpr, sequenceStructureData.elementStructure];
FOR j:
NAT
DECREASING
IN [1..size]
DO
outColumn ← CONS[NARROW[AC.ApplyNoLkpNoRecastRef[method, LIST[sequenceData[j]] ]] , outColumn];
ENDLOOP;
out ← MathConstructors.MakeSequence[size, outColumn, sequenceStructureData.row]; -- row (not column) sequence
};
LegalFirstChar:
PUBLIC AC.LegalFirstCharOp = {
SELECT char
FROM
'< => RETURN[TRUE];
ENDCASE;
RETURN[FALSE];
};
Read:
PUBLIC
AC.ReadOp ~ {
structureData: SequenceStructureData ← NARROW[structure.data];
elementStructure: AC.Object ← structureData.elementStructure;
readMethod: AC.Method ← AC.LookupMethodInStructure[$read, elementStructure];
puncChar: CHAR;
nextElement: AC.Object;
length: NAT ← 0;
ReadFail: PUBLIC ERROR [subclass: ATOM ← $Unspecified] = CODE;
list, listTail: LIST OF AC.Object ← NIL;
outData: SequenceData;
[]← in.SkipWhitespace[];
puncChar ← in.GetChar[];
[]← in.SkipWhitespace[];
IF puncChar # '< THEN ReadFail[$LeftParenExpected];
[]← in.SkipWhitespace[];
puncChar ← in.PeekChar[];
IF puncChar = '> THEN puncChar ← in.GetChar[];
WHILE puncChar # '>
DO
nextElement ← AC.ApplyReadMethod[readMethod, in, elementStructure];
length ← length + 1;
[]← in.SkipWhitespace[];
IF list=
NIL
THEN list ← listTail ←
LIST[nextElement]
ELSE
{ listTail.rest ← LIST[nextElement]; listTail ← listTail.rest };
puncChar ← in.GetChar[];
[]← in.SkipWhitespace[];
IF puncChar # '>
THEN
IF puncChar # ', THEN ReadFail[$CommaExpected];
ENDLOOP;
outData ← NEW[SequenceDataRec[length] ];
FOR i:
NAT
IN [1..length]
DO
outData[i] ← list.first;
list ← list.rest;
ENDLOOP;
out ← NEW[AC.ObjectRec ← [flavor: StructureElement, class: structure, data: outData] ];
};
FromRope:
PUBLIC
AC.FromRopeOp ~ {
out ← Read[IO.RIS[in], structure];
};
ToRope:
PUBLIC
AC.ToRopeOp ~ {
sequenceStructureData: SequenceStructureData ← NARROW[in.class.data];
elementStructure: AC.Object ← sequenceStructureData.elementStructure;
toRopeMethod: AC.Method ← AC.LookupMethodInStructure[$toRope, elementStructure];
inData: SequenceData ← NARROW[in.data];
out ← "< ";
out ← "( "; -- temp change 5/21/87 for SAC-2
FOR i:
NAT
IN [1..inData.lengthPlus1)
DO
out ← Rope.Concat[ out, NARROW[AC.ApplyNoLkpNoRecastRef[toRopeMethod, LIST[inData[i] ] ] ] ];
IF i < inData.lengthPlus1-1 THEN out ← Rope.Concat[out,", "];
ENDLOOP;
out ← Rope.Concat[ out, " >" ];
out ← Rope.Concat[ out, " )" ]; -- temp change 5/21/87 for SAC-2
};
Write:
PUBLIC AC.WriteOp ~ {
stream.PutRope[ ToRope[in] ]
};
Operations
Paren:
PUBLIC
AC.UnaryOp ~ {
RETURN[
NEW[
AC.ObjectRec ← [
flavor: arg.flavor,
class: arg.class,
data: arg.data
] ] ];
};
Equal:
PUBLIC
AC.BinaryPredicate ~ {
firstArgData: SequenceData ← NARROW[firstArg.data];
secondArgData: SequenceData ← NARROW[secondArg.data];
sequenceStructureData: SequenceStructureData ← NARROW[firstArg.class.data];
elementEqualsMethod: Method ← AC.LookupMethodInStructure[$eqFormula, sequenceStructureData.elementStructure];
IF firstArgData.lengthPlus1 # secondArgData.lengthPlus1 THEN RETURN[FALSE];
FOR j:
NAT
IN [1..firstArgData.lengthPlus1)
DO
IF NOT AC.ApplyPredNoLkpNoRecast[elementEqualsMethod, LIST[firstArgData[j], secondArgData[j] ] ] THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE];
};
Prepend:
PUBLIC
AC.BinaryOp ~ {
RETURN[ Insert[firstArg, Ints.FromINT[0], secondArg] ];
};
Append:
PUBLIC
AC.BinaryOp ~ {
firstData: SequenceData ← NARROW[firstArg.data];
RETURN[ Insert[firstArg, Ints.FromINT[firstData.lengthPlus1 - 1], secondArg] ];
};
Insert:
PUBLIC
AC.TernaryOp ~ {
firstArg is a Sequence, secondArg is an Ints.Int specifying position after which to insert new item, thirdArg is new item. secondArg = 0 means insert at beginning, secondArg = i means insert after ith element of sequence. thirdArg must belong to firstArg's elementStructure.
Error if secondArg > Length[firstArg].
sequenceStructureData: SequenceStructureData ← NARROW[firstArg.class.data];
elementStructure: Object ← sequenceStructureData.elementStructure;
recastMethod: Method ← AC.LookupMethodInStructure[$recast, elementStructure];
newElement: Object ← AC.ApplyNoLkpNoRecastObject[recastMethod, LIST[thirdArg, elementStructure] ];
firstData: SequenceData ← NARROW[firstArg.data];
length: INT ← firstData.lengthPlus1 -1;
insertAfter: INT ← Ints.ToINT[secondArg];
newData: SequenceData;
IF insertAfter>length THEN ERROR;
IF newElement = NIL THEN TypeError[]; -- recast failed
newData ← NEW[SequenceDataRec[length+1] ];
FOR i:INT IN [1..insertAfter] DO newData[i] ← firstData[i] ENDLOOP;
newData[insertAfter+1] ← thirdArg;
FOR j:INT IN [insertAfter+1..length] DO newData[j+1] ← firstData[j] ENDLOOP;
RETURN[
NEW[
AC.ObjectRec ← [
flavor: StructureElement,
class: firstArg.class,
data: newData
] ] ];
};
Delete:
PUBLIC
AC.BinaryOp ~ {
firstArg is a Sequence, secondArg is a positive Ints.Int specifying position to delete.
Error if secondArg<1 OR secondArg > Length[firstArg].
firstData: SequenceData ← NARROW[firstArg.data];
delete: INT ← Ints.ToINT[secondArg];
length: INT ← firstData.lengthPlus1-1;
newData: SequenceData;
IF delete<1 OR delete>length THEN ERROR;
newData ← NEW[SequenceDataRec[length-1] ];
FOR i:INT IN [1..delete-1] DO newData[i] ← firstData[i] ENDLOOP;
FOR j:INT IN [delete+1..length] DO newData[j-1] ← firstData[j] ENDLOOP;
RETURN[
NEW[
AC.ObjectRec ← [
flavor: StructureElement,
class: firstArg.class,
data: newData
] ] ];
};
DeleteLast:
PUBLIC
AC.UnaryOp ~ {
data: SequenceData ← NARROW[arg.data];
IF data.lengthPlus1-1 = 0 THEN RETURN[arg];
RETURN[Delete[arg, Ints.FromINT[data.lengthPlus1-1] ] ];
};
Find:
PUBLIC
AC.BinaryOp ~ {
seqData: SequenceData ← NARROW[firstArg.data];
sequenceStructureData: SequenceStructureData ← NARROW[firstArg.class.data];
elementStructure: Object ← sequenceStructureData.elementStructure;
equalMethod: Method ← AC.LookupMethodInStructure[$eqFormula, elementStructure];
test: BOOL;
FOR i:
INT
IN [1..seqData.lengthPlus1)
DO
test ← AC.ApplyPredNoLkpRecast[equalMethod, elementStructure, LIST[seqData[i], secondArg] ];
IF test THEN RETURN[Ints.FromINT[i] ];
ENDLOOP;
RETURN[NIL];
};
Concatenate:
PUBLIC
AC.BinaryOp ~ {
Concatenate two Sequences. Must have same elementStructure.
firstData: SequenceData ← NARROW[firstArg.data];
firstLengthPlus1: INT ← firstData.lengthPlus1;
secondData: SequenceData ← NARROW[secondArg.data];
newData: SequenceData ← NEW[SequenceDataRec[firstLengthPlus1+secondData.lengthPlus1-2] ];
IF NOT AC.StructureEqual[firstArg.class, secondArg.class] THEN ERROR;
FOR i:INT IN [1..firstLengthPlus1) DO newData[i] ← firstData[i] ENDLOOP;
FOR j:INT IN [firstLengthPlus1..firstLengthPlus1+secondData.lengthPlus1-1) DO newData[j] ← secondData[j - firstLengthPlus1 + 1] ENDLOOP;
RETURN[
NEW[
AC.ObjectRec ← [
flavor: StructureElement,
class: firstArg.class,
data: newData
] ] ];
};
MapUnaryElementOp:
PUBLIC
AC.BinaryMixedOp ~ {
firstArg is a Sequence, secondArg is a unary Method (e.g. UnaryOp, UnaryPredicate) on its elementStructure, result is Sequence of results of applications of the unary operation to the elements of firstArg.
seqData: SequenceData ← NARROW[firstArg.data];
method: Method ← NARROW[secondArg];
newElementStructure, newSeqStructure: AC.Object ← NIL;
newData: SequenceData ← NEW[SequenceDataRec[seqData.lengthPlus1-1] ];
FOR i:
INT
IN [1..seqData.lengthPlus1)
DO
newData[i] ← AC.ApplyNoLkpNoRecastObject[method, LIST[seqData[i] ] ];
IF newData[i]# NIL THEN newElementStructure ← newData[i].class;
ENDLOOP;
IF newElementStructure = NIL THEN RETURN[firstArg]; -- map has trivial result
newSeqStructure ← MakeSequenceStructure[newElementStructure];
RETURN[
NEW[
AC.ObjectRec ← [
flavor: StructureElement,
class: newSeqStructure,
data: newData
] ] ];
};
Start Code
sequencesClass: AC.Object ← AC.MakeClass["SequenceClass", NIL, NIL];
setCategoryMethod: Method ← AC.MakeMethod[Value, FALSE, NEW[AC.Category ← set], NIL, NIL];
sequenceStructureMethod: Method ← AC.MakeMethod[Value, FALSE, NIL, NIL, "sequenceStructure"];
shortPrintNameMethod: Method ← AC.MakeMethod[ToRopeOp, FALSE, NEW[AC.ToRopeOp ← ShortPrintName], NIL, "shortPrintName"];
recastMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Recast], NIL, "recast"];
canRecastMethod: Method ← AC.MakeMethod[BinaryPredicate, TRUE, NEW[AC.BinaryPredicate ← CanRecast], NIL, "canRecast"];
toExprMethod: Method ← AC.MakeMethod[ToExprOp, FALSE, NEW[AC.ToExprOp ← ToExpr], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "toExpr"];
legalFirstCharMethod: Method ← AC.MakeMethod[LegalFirstCharOp, FALSE, NEW[AC.LegalFirstCharOp ← LegalFirstChar], NIL, "legalFirstChar"];
readMethod: Method ← AC.MakeMethod[ReadOp, FALSE, NEW[AC.ReadOp ← Read], NIL, "read"];
fromRopeMethod: Method ← AC.MakeMethod[FromRopeOp, TRUE, NEW[AC.FromRopeOp ← FromRope], NIL, "fromRope"];
toRopeMethod: Method ← AC.MakeMethod[ToRopeOp, FALSE, NEW[AC.ToRopeOp ← ToRope], NIL, "toRope"];
parenMethod: Method ← AC.MakeMethod[UnaryOp, FALSE, NEW[AC.UnaryOp ← Paren], NIL, "paren"];
sequenceMethod: Method ← AC.MakeMethod[ListImbedOp, FALSE, NEW[AC.ListImbedOp ← MakeSequence], NIL, "sequence"];
selectMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Select], NEW[AC.UnaryToListOp ← ObjectAndIntDesired], "select"];
firstMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← First], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "first"];
lastMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← Last], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "last"];
lengthMethod: Method ← AC.MakeMethod[ElementRankOp, TRUE, NEW[AC.ElementRankOp ← Length], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "length"];
subsetMethod: Method ← AC.MakeMethod[BinaryPredicate, TRUE, NEW[AC.BinaryPredicate ← IsSubset], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "subset"];
equalMethod: Method ← AC.MakeMethod[BinaryPredicate, TRUE, NEW[AC.BinaryPredicate ← Equal], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "equals"];
prependMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Prepend], NEW[AC.UnaryToListOp ← SequenceAndElementDesired], "prepend"];
appendMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Append], NEW[AC.UnaryToListOp ← SequenceAndElementDesired], "append"];
insertMethod: Method ← AC.MakeMethod[TernaryOp, FALSE, NEW[AC.TernaryOp ← Insert], NEW[AC.UnaryToListOp ← SequenceIntAndElementDesired], "insert"]; -- not an operator currently since takes three args
deleteMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Delete], NEW[AC.UnaryToListOp ← ObjectAndIntDesired], "delete"];
deleteLastMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← DeleteLast], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "deleteLast"];
findMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Find], NEW[AC.UnaryToListOp ← SequenceAndElementDesired], "find"];
concatenateMethod: Method ← AC.MakeMethod[BinaryOp, TRUE, NEW[AC.BinaryOp ← Concatenate], NEW[AC.UnaryToListOp ← AC.DefaultDesiredArgStructures], "concatenate"];
mapUnaryElementOpMethod: Method ← AC.MakeMethod[BinaryMixedOp, TRUE, NEW[AC.BinaryMixedOp ← MapUnaryElementOp], NIL, "mapUnary"]; -- have to have DesiredArgStructures ← NIL since BinaryMixedOp
makeSequenceStructureMethod: Method ← AC.MakeMethod[SequenceStructureConstructor, FALSE, NEW[AC.SequenceStructureConstructor ← MakeSequenceStructure], NIL, "makeSequenceStructure"];
AC.AddMethodToClass[$category, setCategoryMethod, sequencesClass];
AC.AddMethodToClass[$sequenceStructure, sequenceStructureMethod, sequencesClass];
AC.AddMethodToClass[$shortPrintName, shortPrintNameMethod, sequencesClass];
AC.AddMethodToClass[$recast, recastMethod, sequencesClass];
AC.AddMethodToClass[$canRecast, canRecastMethod, sequencesClass];
AC.AddMethodToClass[$toExpr, toExprMethod, sequencesClass];
AC.AddMethodToClass[$legalFirstChar, legalFirstCharMethod, sequencesClass];
AC.AddMethodToClass[$read, readMethod, sequencesClass];
AC.AddMethodToClass[$fromRope, fromRopeMethod, sequencesClass];
AC.AddMethodToClass[$toRope, toRopeMethod, sequencesClass];
AC.AddMethodToClass[$paren, parenMethod, sequencesClass];
AC.AddMethodToClass[$sequence, sequenceMethod, sequencesClass];
AC.AddMethodToClass[$select, selectMethod, sequencesClass];
AC.AddMethodToClass[$first, firstMethod, sequencesClass];
AC.AddMethodToClass[$last, lastMethod, sequencesClass];
AC.AddMethodToClass[$length, lengthMethod, sequencesClass];
AC.AddMethodToClass[$subset, subsetMethod, sequencesClass];
AC.AddMethodToClass[$eqFormula, equalMethod, sequencesClass];
AC.AddMethodToClass[$prepend, prependMethod, sequencesClass];
AC.AddMethodToClass[$append, appendMethod, sequencesClass];
AC.AddMethodToClass[$insert, insertMethod, sequencesClass];
AC.AddMethodToClass[$delete, deleteMethod, sequencesClass];
AC.AddMethodToClass[$deleteLast, deleteLastMethod, sequencesClass];
AC.AddMethodToClass[$find, findMethod, sequencesClass];
AC.AddMethodToClass[$concatenate, concatenateMethod, sequencesClass];
AC.AddMethodToClass[$mapUnary, mapUnaryElementOpMethod, sequencesClass];
AC.AddMethodToClass[$makeSequenceStructure, makeSequenceStructureMethod, Structures.StructuresClass];