DIRECTORY Atom, Rope, IO, List, Convert, Basics, MathDB, MathExpr, AlgebraClasses; AlgebraClassesImpl: CEDAR PROGRAM IMPORTS Atom, Rope, List, Convert, MathDB EXPORTS AlgebraClasses = BEGIN OPEN AlgebraClasses; ROPE: TYPE ~ Rope.ROPE; EXPR: TYPE ~ MathExpr.EXPR; MakeMethod: PUBLIC PROC [type: MethodType, operator: BOOL, value: REF, desiredArgStructures: REF UnaryToListOp, doc: ROPE] RETURNS[Method] ~ { RETURN[ NEW[MethodRec _ [ type: type, operator: operator, value: value, desiredArgStructures: desiredArgStructures, doc: doc ] ] ] }; DesiredArgStructures: PUBLIC PROC [methodSelector: ATOM, structure: Object] RETURNS[LIST OF Object] = { method: Method _ LookupMethodInStructure[methodSelector, structure]; IF method.desiredArgStructures = NIL THEN RETURN[NIL] ELSE RETURN[ method.desiredArgStructures^[structure] ]; }; DefaultDesiredArgStructures: PUBLIC UnaryToListOp ~ { RETURN[ LIST[arg] ]; -- arg assumed to be a Structure }; GetMethodAndRecastArgs: PUBLIC PROC [methodSelector: ATOM, structure: Object, inArgs: LIST OF Object] RETURNS [ok: BOOL, method: Method, outArgs: LIST OF Object _ NIL] ~ { method _ LookupMethodInStructure[methodSelector, structure]; IF method = NIL THEN RETURN[FALSE, NIL, NIL]; IF inArgs = NIL THEN RETURN[TRUE, method, NIL]; -- nothing to do if no args [ok, outArgs] _ RecastArgs[method, structure, inArgs]; RETURN[ok, method, outArgs]; }; RecastArgs: PUBLIC PROC [method: Method, structure: Object, inArgs: LIST OF Object] RETURNS [ok: BOOL, outArgs: LIST OF Object _ NIL] ~ { desiredArgStructures: LIST OF Object; desiredArgStructure: Object; recastArg, arg: Object; outArgsPointer: LIST OF Object; IF method = NIL THEN RETURN[FALSE, NIL]; IF inArgs = NIL THEN RETURN[TRUE, NIL]; -- nothing to do if no args IF method.desiredArgStructures=NIL THEN RETURN[TRUE, inArgs]; desiredArgStructures _ method.desiredArgStructures^[structure]; desiredArgStructure _ NIL; FOR l: LIST OF Object _ inArgs, l.rest WHILE l # NIL DO IF desiredArgStructures # NIL THEN { -- retain last desiredArgStructure if no more desiredArgStructure _ desiredArgStructures.first; desiredArgStructures _ desiredArgStructures.rest; }; recastArg _ arg _ l.first; IF desiredArgStructure # NIL AND NOT StructureEqual[desiredArgStructure, arg.class] THEN { -- recast if there is some desiredArgStructure canRecastMethod: Method _ LookupMethodInStructure[$canRecast, desiredArgStructure]; recastMethod: Method _ LookupMethodInStructure[$recast, desiredArgStructure]; IF ApplyPredNoLkpNoRecast[canRecastMethod, LIST[arg, desiredArgStructure] ] THEN recastArg _ ApplyNoLkpNoRecastObject[recastMethod, LIST[arg, desiredArgStructure] ] -- apply canRecastMethod to arg, not arg.class, so arg is avail if needed ELSE RETURN[FALSE, NIL]; -- recast failed }; IF outArgs = NIL THEN outArgs _ outArgsPointer _ LIST[recastArg] ELSE outArgsPointer _ outArgsPointer.rest _ LIST[recastArg]; ENDLOOP; RETURN[TRUE, outArgs]; }; ApplyLegalFirstCharMethod: PUBLIC PROC [method: Method, char: CHAR, structure: Object _ NIL] RETURNS[BOOL]~{ RETURN[ NARROW[method.value, REF LegalFirstCharOp]^[char, structure] ] }; ApplyFromRopeMethod: PUBLIC PROC [method: Method, in: ROPE, structure: Object _ NIL] RETURNS[Object]~{ RETURN[ NARROW[method.value, REF FromRopeOp]^[in, structure] ] }; ApplyReadMethod: PUBLIC PROC [method: Method, in: STREAM, structure: Object _ NIL] RETURNS[Object]~{ RETURN[ NARROW[method.value, REF ReadOp]^[in, structure] ] }; ApplyFromExprMethod: PUBLIC PROC [method: Method, in: EXPR, structure: Object] RETURNS[Object]~{ RETURN[ NARROW[method.value, REF FromExprOp]^[in, structure] ] }; ApplyCompareToZeroMethod: PUBLIC PROC [method: Method, arg: Object] RETURNS[Basics.Comparison]~{ RETURN[ NARROW[method.value, REF CompareToZeroOp]^[arg] ] }; ApplyBinaryCompareMethod: PUBLIC PROC [method: Method, firstArg, secondArg: Object] RETURNS[Basics.Comparison]~{ RETURN[ NARROW[method.value, REF BinaryCompareOp]^[firstArg, secondArg] ] }; ApplyBinaryImbedMethod: PUBLIC PROC [method: Method, data1: Object, data2: REF, structure: Object] RETURNS[Object]~{ RETURN[ NARROW[method.value, REF BinaryImbedOp]^[data1, data2, structure] ] }; ApplyMixedMethod: PUBLIC PROC [method: Method, objectArgs: LIST OF Object, refArg: REF] RETURNS[Object] ~ { SELECT method.type FROM BinaryMixedOp => RETURN[ NARROW[method.value, REF BinaryMixedOp]^[objectArgs.first, refArg] ]; TernaryMixedOp => RETURN[NARROW[method.value, REF TernaryMixedOp]^[objectArgs.first, objectArgs.rest.first, refArg] ]; ENDCASE => ERROR; }; ApplyPredNoLkpNoRecast: PUBLIC PROC [method: Method, argList: LIST OF Object] RETURNS[BOOL] ~ { SELECT method.type FROM BinaryPredicate => RETURN[ NARROW[method.value, REF BinaryPredicate]^[argList.first, argList.rest.first] ]; UnaryPredicate => RETURN[NARROW[method.value, REF UnaryPredicate]^[argList.first] ]; ENDCASE => ERROR; }; ApplyPredNoLkpRecast: PUBLIC PROC [method: Method, structure: Object, argList: LIST OF Object] RETURNS[BOOL] ~ { ok: BOOL; outArgs: LIST OF Object; [ok, outArgs] _ RecastArgs[method, structure, argList]; IF ok THEN RETURN[ApplyPredNoLkpNoRecast[method, outArgs] ] ELSE ERROR; }; ApplyPredLkpNoRecast: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[BOOL] ~ { method: Method _ LookupMethodInStructure[methodSelector, structure]; RETURN[ApplyPredNoLkpNoRecast[method, argList] ]; }; ApplyPredLkpRecast: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[BOOL] = { ok: BOOL; method: Method; outArgs: LIST OF Object; [ok, method, outArgs] _ GetMethodAndRecastArgs[methodSelector, structure, argList]; IF ok THEN RETURN[ApplyPredNoLkpNoRecast[method, outArgs] ] ELSE ERROR; }; ApplyNoLkpNoRecastRef: PUBLIC PROC [method: Method, argList: LIST OF Object] RETURNS[value: REF] = { SELECT method.type FROM Value => RETURN[method.value]; ToRopeOp => RETURN[NARROW[method.value, REF ToRopeOp]^[argList.first] ]; ToExprOp => RETURN[NARROW[method.value, REF ToExprOp]^[argList.first] ]; ElementRankOp => RETURN[NEW[CARDINAL _ NARROW[method.value, REF ElementRankOp]^[argList.first] ] ]; -- Return REF CARDINAL UnaryPredicate => RETURN[NEW[BOOL _ NARROW[method.value, REF UnaryPredicate]^[argList.first] ] ]; -- Return REF BOOL BinaryPredicate => RETURN[NEW[BOOL _ NARROW[method.value, REF BinaryPredicate]^[argList.first, argList.rest.first] ] ]; -- Return REF BOOL StructuredToGroundOp => RETURN[NARROW[method.value, REF StructuredToGroundOp]^[argList.first] ]; TrueNullaryOp => RETURN[NARROW[method.value, REF TrueNullaryOp]^[] ]; NullaryOp => RETURN[NARROW[method.value, REF NullaryOp]^[argList.first] ]; -- arg here expected to be a Structure UnaryOp => RETURN[NARROW[method.value, REF UnaryOp]^[argList.first] ]; -- 6/4/87 - ??? unclear why ApplyNoLkpNoRecastRef would ever be used for method.type's like UnaryOp that return Objects. same for BinaryOp, ListImbedOp, etc.; should use ApplyNoLkpNoRecastObject BinaryOp => RETURN[NARROW[method.value, REF BinaryOp]^[argList.first, argList.rest.first] ]; ListImbedOp => RETURN[NARROW[method.value, REF ListImbedOp]^[argList.rest, argList.first] ]; -- first Arg here is a Structure MatrixImbedOp => RETURN[NARROW[method.value, REF MatrixImbedOp]^[argList.rest, argList.first] ]; -- first Arg here is a Structure ENDCASE => ERROR; }; ApplyNoLkpRecastRef: PUBLIC PROC [method: Method, structure: Object, argList: LIST OF Object] RETURNS[value: REF] ~ { ok: BOOL; outArgs: LIST OF Object; [ok, outArgs] _ RecastArgs[method, structure, argList]; IF ok THEN RETURN[ApplyNoLkpNoRecastRef[method, outArgs] ] ELSE ERROR; }; ApplyLkpNoRecastRef: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[value: REF] ~ { method: Method _ LookupMethodInStructure[methodSelector, structure]; RETURN[ApplyNoLkpNoRecastRef[method, argList] ]; }; ApplyLkpRecastRef: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[value: REF] = { ok: BOOL; method: Method; outArgs: LIST OF Object; [ok, method, outArgs] _ GetMethodAndRecastArgs[methodSelector, structure, argList]; IF ok THEN RETURN[ApplyNoLkpNoRecastRef[method, outArgs] ] ELSE ERROR; }; ApplyNoLkpNoRecastObject: PUBLIC PROC [method: Method, argList: LIST OF Object] RETURNS[value: Object] ~ { SELECT method.type FROM UnaryPredicate => { fromBOOLMethod: Method; structure: Object; val: BOOL _ NARROW[method.value, REF UnaryPredicate]^[argList.first]; [fromBOOLMethod, structure] _ LookupMethodInAllStructures[$fromBOOL]; RETURN[NARROW[fromBOOLMethod.value, REF FromBOOLOp]^[val] ]; }; BinaryPredicate => { fromBOOLMethod: Method; structure: Object; val: BOOL _ NARROW[method.value, REF BinaryPredicate]^[argList.first, argList.rest.first]; [fromBOOLMethod, structure] _ LookupMethodInAllStructures[$fromBOOL]; RETURN[NARROW[fromBOOLMethod.value, REF FromBOOLOp]^[val] ]; }; ElementRankOp => { fromINTMethod: Method; structure: Object; val: CARDINAL _ NARROW[method.value, REF ElementRankOp]^[argList.first]; [fromINTMethod, structure] _ LookupMethodInAllStructures[$fromINT]; RETURN[NARROW[fromINTMethod.value, REF FromINTOp]^[val] ]; }; StructuredToGroundOp => RETURN[NARROW[method.value, REF StructuredToGroundOp]^[argList.first] ]; TrueNullaryOp => RETURN[NARROW[method.value, REF TrueNullaryOp]^[] ]; NullaryOp => RETURN[NARROW[method.value, REF NullaryOp]^[argList.first] ]; -- arg here expected to be a Structure UnaryOp => RETURN[NARROW[method.value, REF UnaryOp]^[argList.first] ]; BinaryOp => RETURN[NARROW[method.value, REF BinaryOp]^[argList.first, argList.rest.first] ]; TernaryOp => RETURN[NARROW[method.value, REF TernaryOp]^[argList.first, argList.rest.first, argList.rest.rest.first] ]; QuaternaryOp => RETURN[NARROW[method.value, REF QuaternaryOp]^[argList.first, argList.rest.first, argList.rest.rest.first, argList.rest.rest.rest.first] ]; UnaryImbedOp => RETURN[NARROW[method.value, REF UnaryImbedOp]^[argList.first, argList.rest.first] ]; BinaryImbedOp => RETURN[NARROW[method.value, REF BinaryImbedOp]^[argList.first, argList.rest.first, argList.rest.rest.first] ]; ListImbedOp => RETURN[NARROW[method.value, REF ListImbedOp]^[argList.rest, argList.first] ]; -- first Arg here is a Structure MatrixImbedOp => RETURN[NARROW[method.value, REF MatrixImbedOp]^[argList.rest, argList.first] ]; -- first Arg here is a Structure ENDCASE => ERROR; }; ApplyNoLkpRecastObject: PUBLIC PROC [method: Method, structure: Object, argList: LIST OF Object] RETURNS[value: Object]~ { ok: BOOL; outArgs: LIST OF Object; [ok, outArgs] _ RecastArgs[method, structure, argList]; IF ok THEN RETURN[ApplyNoLkpNoRecastObject[method, outArgs] ] ELSE ERROR; }; ApplyLkpNoRecastObject: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[value: Object] ~ { method: Method _ LookupMethodInStructure[methodSelector, structure]; RETURN[ApplyNoLkpNoRecastObject[method, argList] ]; }; ApplyLkpRecastObject: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[value: Object] = { ok: BOOL; method: Method; outArgs: LIST OF Object; [ok, method, outArgs] _ GetMethodAndRecastArgs[methodSelector, structure, argList]; IF ok THEN RETURN[ApplyNoLkpNoRecastObject[method, outArgs] ] ELSE ERROR; }; ApplyNoLkpNoRecastExpr: PUBLIC PROC [method: Method, argList: LIST OF Object] RETURNS[value: EXPR] ~ { RETURN[NARROW[ApplyNoLkpNoRecastRef[method, argList] ] ]; }; ApplyLkpNoRecastExpr: PUBLIC PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[value: EXPR] ~ { method: Method _ LookupMethodInStructure[methodSelector, structure]; RETURN[NARROW[ApplyNoLkpNoRecastRef[method, argList] ] ]; }; MakeClass: PUBLIC PROC [name: Rope.ROPE, superClass: Object, methodDictionary: MethodDictionary] RETURNS[class: Object] ~ { RETURN[NEW[ObjectRec _ [ flavor: Class, name: name, class: superClass, data: methodDictionary ] ] ]; }; AddMethodToClass: PUBLIC PROC [methodSelector: ATOM, method: Method, class: Object] = { methodDict: Atom.PropList _ NARROW[class.data]; class.data _ Atom.PutPropOnList[methodDict, methodSelector, method]; }; SetSuperClass: PUBLIC PROC [object: Object, superClass: Object] = { class: Object _ IF object.flavor = Structure THEN object.class ELSE object; IF object.flavor = StructureElement THEN ERROR; class.class _ superClass; }; LookupMethodInClass: PUBLIC PROC [methodSelector: ATOM, class: Object] RETURNS[method: Method] = { methodDict: Atom.PropList _ NARROW[class.data]; superClass: Object _ class.class; method _ NARROW[Atom.GetPropFromList[methodDict, methodSelector] ]; IF method # NIL THEN RETURN[method]; WHILE superClass#NIL DO IF superClass.flavor = Structure THEN superClass _ superClass.class; -- get a Class methodDict _ NARROW[superClass.data]; method _ NARROW[Atom.GetPropFromList[methodDict, methodSelector]]; IF method # NIL THEN RETURN[method]; superClass _ superClass.class; ENDLOOP; RETURN[NIL]; }; BuildClassOperators: PUBLIC PROC [class: Object] RETURNS[opNames: LIST OF ROPE, operators: LIST OF Method] = { opNamesPtr: LIST OF ROPE _ NIL; operatorsPtr: LIST OF Method _ NIL; superClass: Object; DoClass: PROC [c: Object] ~ { FOR methodDict: MethodDictionary _ NARROW[c.data], methodDict.rest WHILE methodDict # NIL DO method: Method _ NARROW[methodDict.first.val]; IF method.operator THEN { IF opNames = NIL THEN opNames _ opNamesPtr _ LIST[method.doc] ELSE opNamesPtr _ opNamesPtr.rest _ LIST[method.doc]; IF operators = NIL THEN operators _ operatorsPtr _ LIST[method] ELSE operatorsPtr _ operatorsPtr.rest _ LIST[method]; }; ENDLOOP; }; opNames _ NIL; operators _ NIL; DoClass[class]; superClass _ class.class; WHILE superClass # NIL DO IF superClass.flavor = Structure THEN superClass _ superClass.class; -- check whether superClass is a Structure or a Class; in former case, use the Structure's class. At present (3/87), former case will mean that methods that occur in two Structures will get listed twice. Maybe that's ok; user can know that the one listed first is most specific. DoClass[superClass]; superClass _ superClass.class; ENDLOOP; }; IsCategory: PUBLIC PROC [structure: Object, category: Category] RETURNS [BOOL] ~ { categoryMethod: Method _ LookupMethodInStructure[$category, structure]; RETURN[NARROW[categoryMethod.value, REF Category]^ = category]; }; HasProperty: PUBLIC PROC [structure: Object, property: ATOM] RETURNS [BOOL] ~ { RETURN[LookupMethodInStructure[property, structure] # NIL]; }; MakeStructure: PUBLIC PROC [name: Rope.ROPE, class: Object, instanceData: REF] RETURNS[structure: Object] ~ { RETURN[NEW[ObjectRec _ [ flavor: Structure, name: name, class: class, data: instanceData ] ] ]; }; StructureEqual: PUBLIC PROC [structure1, structure2: Object] RETURNS [BOOL] ~ { RETURN[Rope.Equal[structure1.name, structure2.name] ]; }; LookupMethodInStructure: PUBLIC PROC [methodSelector: ATOM, structure: Object] RETURNS[Method] = { RETURN[ LookupMethodInClass[methodSelector, structure.class] ]; }; LookupMethodInAllStructures: PUBLIC PROC [methodSelector: ATOM] RETURNS[method: Method, structure: Object] ~ { FOR l: List.AList _ StructureRegistry, l.rest UNTIL l = NIL DO structure: Object _ NARROW[l.first.val]; method: Method _ LookupMethodInStructure[methodSelector, structure ]; IF method # NIL THEN RETURN[method, structure]; ENDLOOP; RETURN[NIL, NIL]; }; StructureRegistry: List.AList _ NIL; StructureNames: PUBLIC LIST OF ROPE _ NIL; ResetStructureRegistry: PUBLIC PROC[] ~ { StructureRegistry _ NIL; StructureNames _ NIL; }; InstallStructure: PUBLIC PROC[structure: Object] ~ { StructureRegistry _ List.PutAssoc[key: Convert.AtomFromRope[structure.name], val: structure, aList: StructureRegistry]; -- replace by check for existence StructureNames _ CONS[structure.name, StructureNames]; }; LookupStructure: PUBLIC PROC[name: ROPE] RETURNS[structure: Object] ~ { RETURN[NARROW[List.Assoc[key: Convert.AtomFromRope[name], aList: StructureRegistry] ] ]; }; KillStructure: PUBLIC PROC[name: ROPE] ~ { StructureRegistry _ MathDB.KillAssoc[key: Convert.AtomFromRope[name], aList: StructureRegistry]; }; Copy: PUBLIC UnaryOp ~ { RETURN[NEW[ObjectRec _ [ flavor: arg.flavor, class: arg.class, data: arg.data ] ] ]; }; badAtomClass: PUBLIC ERROR = CODE; badCompoundClass: PUBLIC ERROR = CODE; badMatrixClass: PUBLIC ERROR = CODE; badExprs: PUBLIC ERROR[reason: ATOM] = CODE; exprNotFound: PUBLIC ERROR = CODE; wrongExprType: PUBLIC ERROR = CODE; parseError: PUBLIC ERROR = CODE; ResetStructureRegistry[]; END. ŽAlgebraClassesImpl.mesa Last Edited by: Arnon, June 10, 1985 4:19:22 pm PDT Type Abbreviations from Imported Interfaces Method Operations Get desiredArgStructures Try to recast args into desiredArgStructures, if there are any Class Operations Sets class field of a Class, or class.class field of a Structure 5/3/87 - should also examine operands of $superClass methods in class and each superClass, to pick up additional superclasses (multiple inheritance) Structure Operations Structure Registry Global "DataBase" List Exported DB Index effects: Resets (i.e. destroys) the global Structure DataBase effects: Installs structure in global StructureRegistry DataBase effects: Returns the Structure object associated with name. returns NIL if not found effects: delete structure from global StructureRegistry DataBase, if present. Structure Element Operations Signals & Errors Start Code ΚI˜Jšœ™J™3J˜šΟk ˜ J˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—head2šΠblœœ˜!Jšœ"˜)Jšœ˜—Jšœœ˜J˜headšΟn+œ™,Icodešœœœ˜Mšœœ œ˜—šŸ™šŸ œœœœ œœœœ ˜Žšœœ˜J˜ Jšœ˜Jšœ ˜ Jšœ+˜+J˜J˜—J˜J˜—šŸœœœœœœœ ˜gJšœE˜Eš œœœœœ˜:Jšœ,˜2—J˜J˜—šŸœœ˜5Jšœœ Οc ˜5J˜J˜—šŸœœœœœœ œœœœ œ˜«Mšœ<˜Mšœœ˜(MšœE˜EMšœ œœœ˜/Mšœ˜—Mšœœœ˜M˜——šŸ™šŸœœ˜$Mšœ™M˜—š Ÿœœœœœœ˜*Mšœ™M™—šŸœœœ˜)Mšœ>™>Mšœœ˜Mšœœ˜M˜M˜—šŸœœœ˜4MšœA™AMšœx !˜™Mšœœ!˜6M˜M˜—š Ÿœœœœœ˜GMšœ<™