<<>> <> <> <> <> <> <> <> 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 <> <<(AmpersandVars always contain Nodes)>> 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..