DIRECTORY AmpersandContext USING[], CCTypes USING[BinaryTargetTypes, CCError, CCErrorCase, CCTypeProcs, CheckConformance, ConformanceCheck, Conforms, CreateCedarType, DoObject, GetAmpersandContextType, GetAmpersandVarType, GetIndirectType, GetLTargetType, GetTargetTypeOfIndirect, GetNodeType, GetRTargetType, GetTypeClass, GetWrongType, LR, GetGroundTypeClass, sia], CedarCode USING[BreakShowNode, CodeToLoadThroughIndirect, ConcatCode, CodeToDoApply, CodeToDoBinaryOp, CodeToDoIndex, CodeToDoUnaryOp, CodeToExtractField, CodeToLoadContentsOfAMNode, CodeToSelectField, CodeToStoreUnpopped, CreateCedarNode, ExamineParseTree, GetCurrentTypeOfNode, GetDataFromNode, GetTypeOfNode, Interpret, OperationsBody, Operator, ShowNodeBracketed], CedarOtherPureTypes USING[CreateParseTreeNode], CirioSyntacticOperations USING[CreateParseTree, ParseTreeFunctions, ParseTree, LHSapply, LHSFieldIdentifier, RHSApply, RHSAssignment, RHSConstructor, RHSBinaryOp, RHSFieldIdentifier, RHSUnaryOp], CirioTypes USING[Code, CompilerContext, ConformanceCheck, Node, Type, TypeClass, TypedCode], IO, Rope, StructuredStreams, SymTab USING[Create, Fetch, Insert, Ref, Key, Val, Pairs]; AmpersandContextImpl: CEDAR PROGRAM IMPORTS CCTypes, CedarCode, CedarOtherPureTypes, CirioSyntacticOperations, IO, Rope, StructuredStreams, SymTab EXPORTS AmpersandContext, CedarCode = BEGIN OPEN CCTypes, CedarCode, CirioTypes, CSO:CirioSyntacticOperations, SS:StructuredStreams; CC: TYPE = CirioTypes.CompilerContext; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; CreateAmpersandContextType: PUBLIC PROC[cc: CC] RETURNS[CirioTypes.Type] = BEGIN nominal: Type _ CCTypes.GetAmpersandContextType[cc]; IF nominal # NIL THEN RETURN[nominal]; RETURN[CCTypes.GetIndirectType[CCTypes.CreateCedarType[$ampersandContext, AmpersandContextDirectTypeProcs, AmpersandContextIndirectTypeProcs, cc]]]; END; AmpersandContextDirectTypeProcs: REF CCTypeProcs _ NEW[CCTypeProcs _[ checkConformance: AmpersandContextCheckConformance]]; AmpersandContextIndirectTypeProcs: REF CCTypeProcs _ NEW[CCTypeProcs _[ selectIdField: AmpersandContextSelectIdField, getScopeIndex: AmpersandContextGetScopeIndex]]; AmpersandContextCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[ConformanceCheck] ~ { IF GetTypeClass[varType] = $ampersandContext THEN RETURN [yes] ELSE RETURN [no]; }; AmpersandContextSelectIdField: PROC[id: Rope.ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT Rope.Fetch[id, 0] FROM '&, '_ => { -- we are expected to look into the ampersand context code: Code _ CedarCode.CodeToSelectField[id, GetAmpersandContextType[cc]]; type: Type _ GetAmpersandVarType[cc]; RETURN[[code, type]]}; ENDCASE => CCE[cirioError]; END; AmpersandContextGetScopeIndex: PROC [type: Type, cc: CC, procData: REF ANY] RETURNS [CARD] = BEGIN RETURN [0]; END; CreateAnAmpersandContext: PUBLIC PROC [cc: CC] RETURNS[CirioTypes.Node] = BEGIN table: SymTab.Ref _ SymTab.Create[]; t: Type _ GetAmpersandContextType[cc]; RETURN[CreateCedarNode[AmpersandContextOps, t, table]]; END; AmpersandContextOps: REF OperationsBody _ NEW[OperationsBody_[ getCurrentType: AmpersandContextGetCurrentType, selectField: AmpersandContextSelectField, show: AmpersandContextShow]]; AmpersandContextGetCurrentType: PROC[node: Node, cc: CC] RETURNS[Type] = {RETURN[GetTypeOfNode[node]]}; AmpersandContextSelectField: PROC[id: Rope.ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN table: SymTab.Ref _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; t: Type _ GetAmpersandVarType[cc]; var: AmpersandVar _ NARROW[SymTab.Fetch[table, id].val]; ict: Type _ GetAmpersandContextType[cc]; ct: Type _ GetTargetTypeOfIndirect[ict]; IF var = NIL THEN BEGIN var _ NEW[AmpersandVarBody_[table, NIL]]; IF NOT SymTab.Insert[table, id, var] THEN CCE[cirioError]; END; <> IF NOT CCTypes.Conforms[ct, CedarCode.GetTypeOfNode[indirectNode], cc] THEN CCE[cirioError, "an ampersand context vs. CC mismatch"]; RETURN[CreateCedarNode[AmpersandVarOps, t, var]]; END; AmpersandContextShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { table: SymTab.Ref _ NARROW[CedarCode.GetDataFromNode[node]]; ShowAmpersandVar: PROC [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL _ FALSE] = { var: AmpersandVar _ NARROW[val]; PrintVar: PROC ~ { to.PutRope[key]; to.PutChar[':]; SS.Bp[to, width, CCTypes.sia, " "]; IF var.val#NIL THEN CedarCode.ShowNodeBracketed[to, var.val, depth, width, cc] ELSE to.PutRope["--no value--"]; RETURN}; SS.Bp[to, always, CCTypes.sia]; CCTypes.DoObject[to, PrintVar]; RETURN}; to.PutChar['{]; [] _ SymTab.Pairs[table, ShowAmpersandVar]; to.PutChar['}]; RETURN}; AmpersandVarCCTypeProcs: REF CCTypeProcs _ NEW[CCTypeProcs _[ checkConformance: AmpersandVarCheckConformance, binaryOperandTypes: AmpersandVarBinaryOperandTypes, operand: AmpersandVarOperand, store: AmpersandVarStore, load: AmpersandVarLoad]]; AmpersandVarCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valTarget: Type _ CCTypes.GetRTargetType[valType, cc]; varTarget: Type _ CCTypes.GetRTargetType[varType, cc]; conforms1: CCTypes.ConformanceCheck; conforms2: CCTypes.ConformanceCheck; conforms1 _ CCTypes.CheckConformance[valTarget, varTarget, cc]; IF conforms1 = no THEN RETURN[no]; conforms2 _ CCTypes.CheckConformance[varTarget, valTarget, cc]; IF conforms2 = no THEN RETURN[no]; IF conforms1 = yes AND conforms2 = yes THEN RETURN[yes]; RETURN[dontKnow]; END; AmpersandVarBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[BinaryTargetTypes] = BEGIN rightClass: CirioTypes.TypeClass _ GetGroundTypeClass[right, cc]; SELECT op FROM $assign => SELECT rightClass FROM $wrong => RETURN[[right, right]]; ENDCASE => RETURN[[left, CCTypes.GetRTargetType[left, cc]]]; ENDCASE => CCE[cirioError]; END; AmpersandVarOperand: PROC[op: Operator, lr: LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $plus, $minus, $div, $mult, $mod, $le, $lt, $eq, $gt, $ge, $max, $min, $and, $or, $not, $index => BEGIN code: Code _ ConcatCode[tc.code, CodeToLoadThroughIndirect[tc.type]]; type: Type _ GetNodeType[cc]; RETURN[[code, type]]; END; ENDCASE => CCE[cirioError]; -- shouldn't happen END; AmpersandVarStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.ConcatCode[ indirect.code, CedarCode.ConcatCode[ value.code, CedarCode.CodeToStoreUnpopped[indirect.type, value.type]]]; type: Type _ value.type; RETURN[[code, type]]; END; AmpersandVarLoad: PROC[indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.ConcatCode[ indirect.code, CedarCode.CodeToLoadThroughIndirect[indirect.type]]; type: Type _ CCTypes.GetRTargetType[indirect.type, cc]; RETURN[[code, type]]; END; AmpersandVar: TYPE = REF AmpersandVarBody; AmpersandVarBody: TYPE = RECORD[ table: SymTab.Ref, val: Node]; AmpersandVarOps: REF OperationsBody _ NEW[OperationsBody_[ load: LoadFromAmpersandVar, store: StoreToAmpersandVar]]; LoadFromAmpersandVar: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN var: AmpersandVar _ NARROW[GetDataFromNode[indirectNode]]; IF indirectType # GetTypeOfNode[indirectNode] THEN CCE[cirioError]; -- should be a generalized Conforms test IF var.val = NIL THEN CCE[operation, "attempt to load from an uninitialized ampersandVar"]; RETURN[var.val]; END; StoreToAmpersandVar: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = BEGIN var: AmpersandVar _ NARROW[GetDataFromNode[indirectNode]]; IF indirectType # GetTypeOfNode[indirectNode] THEN CCE[cirioError]; -- should be a generalized Conforms test var.val _ valNode; END; CreateNodeType: PUBLIC PROC[cc: CC] RETURNS[CirioTypes.Type] = BEGIN nominal: Type _ CCTypes.GetNodeType[cc]; IF nominal # NIL THEN RETURN[nominal]; RETURN[CreateCedarType[$amnode, NodeCCTypeProcs, AmpersandVarCCTypeProcs, cc]]; END; NodeCCTypeProcs: REF CCTypeProcs _ NEW[CCTypeProcs _[ storable: NodeStorable, getRTargetType: NodeGetRTargetType, binaryOperandTypes: NodeBinaryOperandTypes, operand: NodeOperand, applyOperand: NodeApplyOperand, indexOperand: NodeIndexOperand, coerceToType: NodeCoerceToType, binaryOp: NodeBinaryOp, unaryOp: NodeUnaryOp, store: NodeStore, extractIdField: NodeExtractIdField, selectIdField: NodeSelectIdField, apply: NodeApply, index: NodeIndex, printType: NodePrintType]]; NodeStorable: PROC[valType, indirectType: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = BEGIN indirectTypeClass: TypeClass _ GetGroundTypeClass[indirectType, cc]; SELECT indirectTypeClass FROM $amnode => RETURN[TRUE]; ENDCASE => RETURN[CCTypes.Conforms[valType, CCTypes.GetLTargetType[indirectType, cc], cc]]; END; NodeGetRTargetType: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[Type] = {RETURN[GetNodeType[cc]]}; NodeBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[BinaryTargetTypes] = BEGIN SELECT op FROM $assign => RETURN[[left, left]]; -- is thsi right? ENDCASE => RETURN[[left, left]]; END; NodeOperand: PROC[op: Operator, lr: LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = {RETURN[tc]}; NodeApplyOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN node: Node _ CedarOtherPureTypes.CreateParseTreeNode[operand, cc]; code: CirioTypes.Code _ CedarCode.CodeToLoadContentsOfAMNode[node]; type: Type _ CCTypes.GetNodeType[cc]; RETURN[[code, type]]; END; NodeIndexOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN node: Node _ CedarOtherPureTypes.CreateParseTreeNode[operand, cc]; code: CirioTypes.Code _ CedarCode.CodeToLoadContentsOfAMNode[node]; type: Type _ CCTypes.GetNodeType[cc]; RETURN[[code, type]]; END; NodeCoerceToType: PROC[targetType: Type, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN targetClass: TypeClass _ GetGroundTypeClass[targetType, cc]; SELECT targetClass FROM $wrong => RETURN[[tc.code, GetWrongType[cc]]]; $amnode => RETURN[tc]; ENDCASE => CCE[cirioError]; -- shouldn't happen (or can it occur due to a client type error?) END; NodeBinaryOp: PROC[op: Operator, left, right: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ ConcatCode[ left.code, ConcatCode[ right.code, CodeToDoBinaryOp[op, left.type, right.type]]]; RETURN[[code, left.type]]; END; NodeUnaryOp: PROC[op: Operator, arg: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ ConcatCode[ arg.code, CodeToDoUnaryOp[op, arg.type]]; RETURN[[code, arg.type]]; END; NodeStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.ConcatCode[ indirect.code, CedarCode.ConcatCode[ value.code, CedarCode.CodeToStoreUnpopped[indirect.type, value.type]]]; type: Type _ value.type; RETURN[[code, type]]; END; NodeExtractIdField: PROC[id: Rope.ROPE, fieldContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.CodeToExtractField[id, fieldContext]; RETURN[[code, fieldContext]]; END; NodeSelectIdField: PROC[id: Rope.ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.CodeToSelectField[id, fieldIndirectContext]; RETURN[[code, fieldIndirectContext]]; END; NodeApply: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.ConcatCode[ operator.code, CedarCode.ConcatCode[ operand.code, CodeToDoApply[operator.type, operand.type]]]; type: Type _ CCTypes.GetNodeType[cc]; RETURN[[code, type]]; END; NodeIndex: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code _ CedarCode.ConcatCode[ operator.code, CedarCode.ConcatCode[ operand.code, CodeToDoIndex[operator.type, operand.type]]]; type: Type _ CCTypes.GetNodeType[cc]; RETURN[[code, type]]; END; NodePrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = {to.PutRope["Node"]}; NodeHolder: TYPE = RECORD[nd: Node]; MakeNodeFromNode: PUBLIC PROC[node: Node, cc: CC] RETURNS[Node] = {RETURN[CreateCedarNode[AMNodeOps, CCTypes.GetNodeType[cc], NEW[NodeHolder_[node]]]]}; AMNodeOps: REF OperationsBody _ NEW[OperationsBody _[ makeAMNode: AMNodeMakeAMNode, examineBoolean: AMNodeExamineBoolean, coerce: AMNodeCoerce, binaryOp: AMNodeBinaryOp, unaryOp: AMNodeUnaryOp, store: AMNodeStore, extractField: AMNodeExtractField, selectField: AMNodeSelectField, apply: AMNodeApply, index: AMNodeIndex, show: AMNodeShow ]]; AMNodeParseTreeFunctions: REF CSO.ParseTreeFunctions _ NEW[CSO.ParseTreeFunctions _ [ AMNodeCompileForRHS, AMNodeCompileForLHS]]; CreateAMNodeParseTree: PROC[node: Node, cc: CC] RETURNS[CSO.ParseTree] = {RETURN[CSO.CreateParseTree[AMNodeParseTreeFunctions, NEW[NodeHolder_[node]]]]}; AMNodeMakeAMNode: PROC[sourceType: Type, node: Node, cc: CC] RETURNS[Node] = {RETURN[MakeNodeFromNode[node, cc]]}; AMNodeExamineBoolean: PROC[node: Node, cc: CC] RETURNS[BOOLEAN] = {CCE[cirioError]}; -- shouldnt happen AMNodeCoerce: PROC[sourceType, targetType: Type, node: Node, cc: CC] RETURNS[Node] = {CCE[cirioError]}; -- shouldnt happen ??? AMNodeBinaryOp: PROC[op: CedarCode.Operator, leftType, rightType: Type, leftNode, rightNode: Node, cc: CC] RETURNS[Node] = BEGIN -- do what we would have done at compile time if we knew the contents left: Node _ StripAMNode[leftNode]; right: Node _ StripAMNode[rightNode]; leftPT: CSO.ParseTree _ CreateAMNodeParseTree[left, cc]; rightPT: CSO.ParseTree _ CreateAMNodeParseTree[right, cc]; tc: TypedCode _ CSO.RHSBinaryOp[op, leftPT, rightPT, cc]; RETURN[MakeNodeFromNode[CedarCode.Interpret[tc.code, cc], cc]]; END; AMNodeUnaryOp: PROC[op: CedarCode.Operator, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN item: Node _ StripAMNode[node]; itemPT: CSO.ParseTree _ CreateAMNodeParseTree[item, cc]; tc: TypedCode _ CSO.RHSUnaryOp[op, itemPT, cc]; RETURN[MakeNodeFromNode[Interpret[tc.code, cc], cc]] END; AMNodeConstructRecordNode: PUBLIC PROC[rcdType: Type, fields: LIST OF Node, cc: CC] RETURNS[Node] = BEGIN treeList: LIST OF CSO.ParseTree _ NIL; lastCell: LIST OF CSO.ParseTree _ NIL; tc: TypedCode; FOR fl: LIST OF Node _ fields, fl.rest WHILE fl # NIL DO node: Node _ StripAMNode[fl.first]; pt: CSO.ParseTree _ CreateAMNodeParseTree[node, cc]; cell: LIST OF CSO.ParseTree _ LIST[pt]; IF treeList = NIL THEN treeList _ cell ELSE lastCell.rest _ cell; lastCell _ cell; ENDLOOP; tc _ CSO.RHSConstructor[treeList, rcdType, cc]; RETURN[Interpret[tc.code, cc]]; END; AMNodeConstructArrayNode: PUBLIC PROC[arrayType: Type, entries: LIST OF Node, cc: CC] RETURNS[Node] = BEGIN treeList: LIST OF CSO.ParseTree _ NIL; lastCell: LIST OF CSO.ParseTree _ NIL; tc: TypedCode; FOR el: LIST OF Node _ entries, el.rest WHILE el # NIL DO node: Node _ StripAMNode[el.first]; pt: CSO.ParseTree _ CreateAMNodeParseTree[node, cc]; cell: LIST OF CSO.ParseTree _ LIST[pt]; IF treeList = NIL THEN treeList _ cell ELSE lastCell.rest _ cell; lastCell _ cell; ENDLOOP; tc _ CSO.RHSConstructor[treeList, arrayType, cc]; RETURN[Interpret[tc.code, cc]]; END; AMNodeStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = BEGIN valItem: Node _ StripAMNode[valNode]; valItemPT: CSO.ParseTree _ CreateAMNodeParseTree[valItem, cc]; indirectItem: Node _ StripAMNode[indirectNode]; indirectItemPT: CSO.ParseTree _ CreateAMNodeParseTree[indirectItem, cc]; tc: TypedCode _ CSO.RHSAssignment[indirectItemPT, valItemPT, cc]; [] _ Interpret[tc.code, cc]; END; AMNodeExtractField: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN item: Node _ StripAMNode[node]; itemType: Type _ GetTypeOfNode[item]; finaltc: TypedCode _ CSO.RHSFieldIdentifier[id, itemType, cc]; code: Code _ ConcatCode[ CodeToLoadContentsOfAMNode[item], finaltc.code]; RETURN[MakeNodeFromNode[Interpret[code, cc], cc]]; END; AMNodeSelectField: PROC[id: Rope.ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN indirectItem: Node _ StripAMNode[indirectNode]; currentIndirectItemType: Type _ CedarCode.GetCurrentTypeOfNode[indirectItem, cc]; finaltc: TypedCode _ CSO.LHSFieldIdentifier[id, currentIndirectItemType, cc]; code: Code _ ConcatCode[ CodeToLoadContentsOfAMNode[indirectItem], finaltc.code]; RETURN[MakeNodeFromNode[Interpret[code, cc], cc]]; END; AMNodeApply: PROC[operatorType: Type, operandType: Type, operator: Node, operand: Node, cc: CC] RETURNS[Node] = BEGIN operatorPT: CSO.ParseTree _ CreateAMNodeParseTree[StripAMNode[operator], cc]; operandPT: CSO.ParseTree _ CedarCode.ExamineParseTree[operand, cc]; tc: TypedCode _ CSO.RHSApply[operatorPT, operandPT, cc]; RETURN[MakeNodeFromNode[Interpret[tc.code, cc], cc]]; END; AMNodeIndex: PROC[indirectOperatorType: Type, operandType: Type, indirectOperator: Node, operand: Node, cc: CC] RETURNS[Node] = BEGIN indirectOperatorItem: Node _ StripAMNode[indirectOperator]; currentIndirectOperatorType: Type _ CedarCode.GetCurrentTypeOfNode[indirectOperatorItem, cc]; indirectOperatorPT: CSO.ParseTree _ CreateAMNodeParseTree[indirectOperatorItem, cc]; operandPT: CSO.ParseTree _ CedarCode.ExamineParseTree[operand, cc]; tc: TypedCode _ CSO.LHSapply[indirectOperatorPT, operandPT, cc]; RETURN[MakeNodeFromNode[Interpret[tc.code, cc], cc]]; END; AMNodeShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { item: Node _ StripAMNode[node]; to.PutRope["Node["]; CedarCode.BreakShowNode[to, item, depth-1, width, cc]; to.PutChar[']]}; StripAMNode: PUBLIC PROC[node: Node] RETURNS[Node] = BEGIN -- strips off one layer of node innerNode: Node _ NARROW[CedarCode.GetDataFromNode[node], REF NodeHolder].nd; RETURN[innerNode]; END; AMNodeCompileForRHS: PROC[tree: CSO.ParseTree, nominalTarget: Type, cc: CC, data: REF ANY] RETURNS[TypedCode] = BEGIN node: Node _ NARROW[data, REF NodeHolder].nd; RETURN[[CodeToLoadContentsOfAMNode[node], CedarCode.GetTypeOfNode[node]]]; END; AMNodeCompileForLHS: PROC[tree: CSO.ParseTree, cc: CC, data: REF ANY] RETURNS[TypedCode] = BEGIN node: Node _ NARROW[data, REF NodeHolder].nd; RETURN[[CodeToLoadContentsOfAMNode[node], CedarCode.GetTypeOfNode[node]]]; END; END.. 8 AmpersandContextImpl.mesa Copyright Σ 1990 by Xerox Corporation. All rights reserved. Sturgis, March 16, 1989 9:29:11 am PST Last changed by Theimer on June 11, 1989 1:42:09 pm PDT Hopcroft July 26, 1989 10:22:58 am PDT Last tweaked by Mike Spreitzer on January 9, 1992 2:28 pm PST Laurie Horton, September 16, 1991 12:53 pm PDT this module contains both the type information and the implementation of the op codes Type information the only kind of ampersandContext values that can appear on an expression stack (or in a Node) are indirects to ampersandContexts. the only legal operation on an ampersandContext is to select a field named by an ampersand identifier. an ampersand name is always defined and always has type AmpersandVar (AmpersandVars always contain Nodes) interpretation time This is the default version. It assumes that the target type is not a union type. AmpersandVars are components of an Ampersand Context (i.e., SymTab.Ref) AmpersandVars are indirects to nodes question: can AmpersandVars be made by the default indirect to type mechanism? valType is the standard control parameter This code should have some how been executed as a result of some sort of default. I don't at the moment know why I have to put it here. it should be true of any indirect type upon modification for LTargetType/RTargetType logic, we treat the target type as a singleton. we really should make a last ditch type check There is some question as to who should build the node holding an AmpersandVar. The create node call requires the operations and the type. That would be here? as it stands it is in the Select implementation up above. we get here by an object proc from the indirectNode AmpersandVars hold only Nodes we should have to package that node into a containing node for the interpreter. however, the store routine was careful not to remove the original packaging used by the interpreter, so we do not have to re-install it other object load routines would have to install such node packaging we get here by an object proc from the indirectNode valType had better be Node, as well as the type of valNode by an agreement with the above load routine, we do not strip off the outer layer of node packaging used by the interpreter. However, we would expect to find a node inside this package. Thus, the real value should be at least two node levels deep. Since ampersand vars are really indirects on Nodes, we need node types. (The node operations are currently in CedarCodeImpl.) We put the node type stuff here for the time being. The presumption is that we are compiling some ambiguous text, so the lefthand side of an assignment has produced an indirect packaged inside a node. We are to request that the right hand side also produce its value packaged inside a node. Thus, if the right hand side is a request to load the contents of an AmpersandVar or through a REF ANY, the right thing will happen. Maybe at some time I should have a type called "packagedInsideANode". I don't know if that can be carried out. This would be similar to have a type called "DeferedLoadRecord". the target type must be node Now for the node routines I am sure I am not getting the levels of stripping and adding right on this coding pass this should be an object proc of something notice that we did not package this inside a node. We are called by a run time instruction that knows that we are about to produce a rcdType value. The compiler knew that when it generated the code. So code that uses this value assumes that it is of type rcdType, and not a record packaged inside a node. this should be an object proc of something notice that we did not package this inside a node. We are called by a run time instruction that knows that we are about to produce an arrayType value. The compiler knew that when it generated the code. So code that uses this value assumes that it is of type arrayType, and not a record packaged inside a node. note: The value, currentIndirectItemType, can be a very fleeting value. That is, if the indirect is to a union type, then the type of the current value in the field pointed to by the indirect is (in principle) constantly changing. Thus, in general, this code can only be executed by an interpreter while the world is sufficiently frozen. There are at least two safe exceptions. (1) If the indirect is to a variant record, then because of the current Cedar rule that the actual type can not change once it has been initialized, we need not freeze the world. (2) If the indirect is part of a REF, then we don't really have to call GetCurrentTargetType, because this would have been called as part of loading the REF value itself, hence GetType[indirectItem] would have had the same effect as GetIndirectType[GetCurrentTargetType[indirectItem], cc]. I have changed the code to use GetCurrentType. This applies both to indirect types and to REF types. For indirect types is should be implemented as (roughly) GetIndirectType[GetCurrentTargetType[indirectItem], cc]. Warning: I am not sure how this should be coded. Using Apply as a model, I would expect to find parse trees all over the place. Using Select as a model, I should be examining current type etc. I shall attempt to combine these two models. However, I don't see how to use currentIndirectOperatorType. See AMNodeSelectField comments concerning the fleeting nature of currentIndirectOperatorType. Κ •NewlineDelimiter ™codešœ™K™K˜/K˜)K˜—˜KšœR™R—šžœœœœ˜HKšœœ˜K˜—š žœœ œ.œœ˜pKš˜Kšœœ*˜DK˜"Kšœœ˜8Kšœ(˜(Kšœ(˜(K˜šœœ˜Kš˜Kšœœœ˜)Kšœœœœ ˜:Kšœ˜—K˜KšŸœEœœŸ*˜‰KšœœAœœ5˜„K˜Kšœ+˜1K˜Kšœ˜K˜—šžœœœœœ œœ˜YKšœœ"˜<š žœœ$œœœ˜ZKšœœ˜!šžœœ˜Kšœ˜K˜Kšœ!˜#šœ ˜Kšœ;˜?Kšœ˜ —Kšœ˜—Kšœ˜K˜Kšœ˜—K˜Kšœ+˜+K˜Kšœ˜K˜—K˜K™šœG™GK˜—˜K™Kšœ$™$KšœN™N—šžœœœ˜=K˜/K˜3K˜K˜K˜—˜Kšœ)™)—š žœœœ œœœ˜yKš˜KšœQ™QKšœ5™5Kšœ&™&Kšœ]™]K˜6K˜6K˜$K˜$K˜?Kšœœœ˜"K˜?Kšœœœ˜"Kšœœœœ˜8Kšœ ˜Kšœ˜—K˜K˜š žœœ&œ œœœ˜}Kš˜K˜Ašœ˜˜ šœ ˜Kšœ œ˜!Kšœœ,˜=——Kšœœ ˜—šœ˜K˜——šžœœœœ œœœ ˜nKš˜šœ˜˜aKš˜K˜EK˜Kšœ˜Kšœ˜—KšœœŸ˜/—Kšœ˜—K˜K˜š žœœ,œ œœœ ˜nKš˜˜"K˜˜K˜ K˜;——K˜Kšœ-™-Kšœ˜Kšœ˜—K˜š žœœœ œœœ ˜[Kš˜˜"K˜K˜4—K˜7Kšœ˜Kšœ˜K˜KšœΫ™ΫK™—Kšœœœ˜*šœœœ˜ K˜K˜ —K˜šžœœœ˜:K˜K˜—K˜˜Kšœ3™3šœ™KšœO™OKšœ‡™‡KšœD™D——šžœœ-œœ˜ZKš˜Kšœœ ˜:K˜Kšœ,œœŸ(˜lKšœ œœœB˜[Kšœ ˜Kšœ˜K˜Kšœ3™3šœ:™:Kšœψ™ψ——šžœœKœ˜iKš˜Kšœœ ˜:K˜Kšœ,œœŸ(˜lK˜Kšœ˜—K˜K˜Kšœ³™³˜K˜—š žœœœœœ˜>Kš˜K˜(Kšœ œœœ ˜&KšœI˜OKšœ˜—K˜šžœœœ˜5K˜K˜#K˜+K˜K˜K˜K˜K˜K˜K˜K˜#K˜!K˜K˜K˜—K˜šž œœ"œ œœœœ˜]Kš˜K˜Dšœ˜Kšœ œœ˜KšœœJ˜[—Kšœ˜—˜Kšœυ™υKšœ±™±—š žœœœ œœœ˜OKšœœ˜—˜Kšœ™—š žœœ&œ œœœ˜uKš˜šœ˜Kšœ œŸ˜4Kšœœ˜ —Kšœ˜K˜—šž œœœœ œœœ ˜fKšœœ˜ —K˜š žœœFœ œœœ ˜‡Kš˜K˜BK˜CK˜%Kšœ˜Kšœ˜—K˜š žœœFœ œœœ ˜‡Kš˜K˜BK˜CK˜%Kšœ˜Kšœ˜K˜K˜—š žœœ&œ œœœ ˜gKš˜K˜<šœ ˜Kšœ œ˜.Kšœ œ˜KšœœŸA˜]—Kšœ˜K˜—š ž œœ+œ œœœ ˜hKš˜˜ ˜ K˜ ˜ K˜ K˜.———Kšœ˜Kšœ˜K˜—š ž œœ#œ œœœ ˜_Kš˜˜ ˜ K˜ K˜——Kšœ˜Kšœ˜—K˜š ž œœ,œ œœœ ˜fKš˜˜"K˜˜K˜ K˜;——K˜Kšœ˜Kšœ˜—K˜šžœœ œœ œœœ ˜kKš˜K˜K˜/Kšœœ5˜HKšœœ.˜AK˜Kšœ˜K˜—š žœœ œœœ˜WKš˜K˜K˜%Kšœœ&˜>˜K˜!K˜—Kšœ,˜2Kšœ˜—K˜—š žœœ œ.œœ˜fKš˜KšœΣ™ΣK™KšœΨ™ΨK™K˜/K˜QKšœœ5˜M˜K˜)K˜—Kšœ,˜2Kšœ˜—K˜šž œœKœœ˜oKš˜Kšœ œ>˜MKšœ œ5˜CKšœœ%˜8Kšœ/˜5Kšœ˜—K˜šž œœ[œœ˜Kš˜Kšœ­™­K™Kšœ]™]K™K˜;K˜]Kšœœ=˜TKšœ œ5˜CKšœœ-˜@Kšœ/˜5Kšœ˜—K˜K˜šž œœœœœ œœ˜OK˜K˜Kšœ6˜6Kšœ˜—K˜šž œœœ œ˜4KšœŸ˜&Kšœœ"œ˜MKšœ ˜Kšœ˜—K˜šžœœœ%œœœœ ˜oKš˜Kšœ œœ˜-KšœD˜JKšœ˜—K˜šžœœœœœœœ ˜ZKš˜Kšœ œœ˜-KšœD˜JKšœ˜—K˜Kšœ˜—…—Irφ