<<>> <> <> <> <> <> <> DIRECTORY CCTypes USING[Apply, ApplyOperand, IndexOperand, BinaryOperandTypes, BinaryTargetTypes, BreakObject, CCError, CCErrorCase, CCTypeProcs, CheckConformance, CheckFamilyInclusion, ConformanceCheck, CreateCedarType, ExtractIdField, GetIndirectType, GetProcDataFromGroundType, GetProcDataFromType, HasIdField, Index, LR, SelectIdField, PrintType], CedarCode USING[BreakShowNode, Code, CodeToExtractField, CodeToSelectField, ConcatCode, CreateCedarNode, GetDataFromNode, GetTypeOfNode, LoadThroughIndirectNode, NodeAsIndex, OperationsBody, Operator, ShowNode], CirioSyntacticOperations USING[ParseTree], CirioTypes USING[CompilerContext, Mem, Node, Type, TypedCode], IO, Rope, Sequences USING[SequenceTypeProcs, IndirectSRProcs]; SequencesImpl: CEDAR PROGRAM IMPORTS CCTypes, CedarCode, IO, Rope EXPORTS Sequences = BEGIN CC: TYPE = CirioTypes.CompilerContext; Code: TYPE = CedarCode.Code; Type: TYPE = CirioTypes.Type; TypedCode: TYPE = CirioTypes.TypedCode; Mem: TYPE = CirioTypes.Mem; Node: TYPE = CirioTypes.Node; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; Operator: TYPE = CedarCode.Operator; <<>> <> <<>> <> <<>> <> SRInfo: TYPE = REF SRInfoBody; SRInfoBody: TYPE = RECORD[ self: Type, indirect: Type, procs: REF Sequences.SequenceTypeProcs, preamble: Type, tailName: Rope.ROPE, tailType: Type, data: REF ANY]; <> CreateSequenceRecordType: PUBLIC PROC[preamble: Type, tailName: Rope.ROPE, tagName: Rope.ROPE, indexType: Type, procs: REF Sequences.SequenceTypeProcs, cc: CC, data: REF ANY] RETURNS[Type] = BEGIN unionTailType: Type _ CreateUnionTailType[tagName, indexType, procs, cc, data]; info: SRInfo _ NEW[SRInfoBody_[NIL, NIL, procs, preamble, tailName, unionTailType, data]]; type: Type _ CCTypes.CreateCedarType[$sequence, SequenceCCTypeProcs, IndirectSequenceCCTypeProcs, cc, info]; info.self _ type; RETURN[type]; END; SequenceCCTypeProcs: REF CCTypes.CCTypeProcs _ NEW[CCTypes.CCTypeProcs _[ checkConformance: SRCCTypesCheckConformance, checkFamilyInclusion: SRCCTypesCheckFamilyInclusion, getFieldsType: SRCCTypesGetFieldsType, containsVariance: SRCCTypesContainsVariance, operand: SRCCTypesOperand, applyOperand: SRCCTypesApplyOperand, binaryOperandTypes: SRCCTypesBinaryOperandTypes, extractIdField: SRCCTypesExtractIdField, apply: SRCCTypesApply, printType: SRCCTypesPrintType]]; SRCCTypesCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valInfo: SRInfo _ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: SRInfo => BEGIN conforms1: CCTypes.ConformanceCheck; conforms2: CCTypes.ConformanceCheck; conforms1 _ CCTypes.CheckConformance[valInfo.preamble, varInfo.preamble, cc]; IF conforms1 = no THEN RETURN[no]; conforms2 _ CCTypes.CheckConformance[valInfo.tailType, varInfo.tailType, cc]; IF conforms2 = no THEN RETURN[no]; IF conforms1 = yes AND conforms2 = yes THEN RETURN[yes]; RETURN[dontKnow]; END; ENDCASE => RETURN[no]; END; SRCCTypesCheckFamilyInclusion: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = BEGIN valInfo: SRInfo _ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: SRInfo => BEGIN IF NOT CCTypes.CheckFamilyInclusion[valInfo.preamble, varInfo.preamble, cc] THEN RETURN[FALSE]; IF NOT CCTypes.CheckFamilyInclusion[valInfo.tailType, varInfo.tailType, cc] THEN RETURN[FALSE]; RETURN[TRUE]; END; ENDCASE => RETURN[FALSE]; END; SRCCTypesGetFieldsType: PROC[rcdType: Type, cc: CC, procData: REF ANY] RETURNS[Type] = BEGIN info: SRInfo _ NARROW[procData]; RETURN[info.preamble]; END; SRCCTypesContainsVariance: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[TRUE]}; SRCCTypesOperand: PROC[op: CedarCode.Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $dot, $extractId => RETURN[tc]; $apply => SELECT lr FROM left => RETURN[tc]; ENDCASE => CCE[operation]; ENDCASE => CCE[operation]; -- client error, invalid operation END; SRCCTypesApplyOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: SRInfo _ NARROW[procData]; RETURN[CCTypes.ApplyOperand[info.tailType, operand, cc]]; END; SRCCTypesBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN info: SRInfo _ NARROW[procData]; subTypes: CCTypes.BinaryTargetTypes _ CCTypes.BinaryOperandTypes[op, info.tailType, right, cc]; RETURN[[left, subTypes.tRight]]; END; SRCCTypesExtractIdField: PROC[id: Rope.ROPE, fieldContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: SRInfo _ NARROW[procData]; IF CCTypes.HasIdField[id, info.preamble, cc] = yes THEN BEGIN -- note: it should be impossible to return possible code1: Code _ CedarCode.CodeToExtractField["&Preamble", fieldContext]; tc2: TypedCode _ CCTypes.ExtractIdField[id, info.preamble, cc]; code: Code _ CedarCode.ConcatCode[code1, tc2.code]; RETURN[[code, tc2.type]]; END ELSE IF Rope.Equal[id, info.tailName] THEN BEGIN code: Code _ CedarCode.CodeToExtractField["&Tail", fieldContext]; RETURN[[code, info.tailType]]; END ELSE CCE[operation, Rope.Cat["field ", id, " does not exist"]]; -- client error, no such field name END; SRCCTypesApply: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: SRInfo _ NARROW[procData]; code1: Code _ CedarCode.ConcatCode[ operator.code, CedarCode.CodeToExtractField["&Tail", info.self]]; RETURN[CCTypes.Apply[[code1, info.tailType], operand, cc]]; END; SRCCTypesPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = { info: SRInfo _ NARROW[procData]; tailInfo: SRTailInfo _ NARROW[CCTypes.GetProcDataFromType[info.tailType]]; PrintTail: PROC ~ { to.PutRope[info.tailName]; to.PutChar[':]; CCTypes.BreakObject[to, PrintIndex, " "]; CCTypes.BreakObject[to, PrintRange, " "]}; PrintIndex: PROC ~ { to.PutRope["SEQUENCE "]; CCTypes.PrintType[to, tailInfo.indexType, printDepth-1, printWidth, cc]}; PrintRange: PROC ~ { to.PutRope["OF "]; CCTypes.PrintType[to, tailInfo.procs.getEntryType[cc, tailInfo.data], printDepth-1, printWidth, cc]}; to.PutChar['[]; CCTypes.PrintType[to, info.preamble, printDepth-1, printWidth, cc]; to.PutChar[',]; IF info.tailName.Length[]>0 THEN CCTypes.BreakObject[to, PrintTail, " "] ELSE { CCTypes.BreakObject[to, PrintIndex, " "]; CCTypes.BreakObject[to, PrintRange, " "]}; to.PutChar[']]; RETURN}; IndirectSequenceCCTypeProcs: REF CCTypes.CCTypeProcs _ NEW[CCTypes.CCTypeProcs _[ createIndirectNode: SequenceCreateIndirect, getBitSize: SequenceBitSize, operand: ISRCCTypesOperand, indexOperand: SRCCTypesApplyOperand, store: ISRCCTypesStore, selectIdField: ISRCCTypesSelectIdField, index: ISRCCTypesIndex, printType: SRCCTypesPrintType]]; SequenceCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { info: SRInfo ~ NARROW[procData]; RETURN info.procs.createIndirectNode[cc, info.data, indirectType, targetType, mem]}; SequenceBitSize: PROC[indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS[CARD] ~ { info: SRInfo ~ NARROW[procData]; RETURN info.procs.getBitSize[indirectType, cc, info.data]}; ISRCCTypesOperand: PROC[op: Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $selectId, $address => RETURN[tc]; $index => SELECT lr FROM left => RETURN[tc]; ENDCASE => CCE[operation]; ENDCASE => CCE[operation]; -- client error; invalid operation END; ISRCCTypesStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = {CCE[operation, "attempt to store a sequence"]}; ISRCCTypesSelectIdField: PROC[id: Rope.ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: SRInfo _ NARROW[procData]; IF CCTypes.HasIdField[id, info.preamble, cc] = yes THEN BEGIN -- note: it should be impossible to return possible code1: Code _ CedarCode.CodeToSelectField["&Preamble", fieldIndirectContext]; tc2: TypedCode _ CCTypes.SelectIdField[id, CCTypes.GetIndirectType[info.preamble], cc]; code: Code _ CedarCode.ConcatCode[code1, tc2.code]; RETURN[[code, tc2.type]]; END ELSE IF Rope.Equal[id, info.tailName] THEN BEGIN code: Code _ CedarCode.CodeToSelectField["&Tail", fieldIndirectContext]; RETURN[[code, info.tailType]]; END ELSE CCE[operation, Rope.Cat["field ", id, " does not exist"]]; -- client error, no such field name END; ISRCCTypesIndex: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: SRInfo _ NARROW[procData]; code1: Code _ CedarCode.ConcatCode[ operator.code, CedarCode.CodeToSelectField["&Tail", info.self]]; RETURN[CCTypes.Index[[code1, CCTypes.GetIndirectType[info.tailType]], operand, cc]]; END; <> <> <> <<>> SRTailInfo: TYPE = REF SRTailInfoBody; SRTailInfoBody: TYPE = RECORD[ self: Type, indirect: Type, tagName: Rope.ROPE, indexType: Type, procs: REF Sequences.SequenceTypeProcs, data: REF ANY]; CreateUnionTailType: PROC[tagName: Rope.ROPE, indexType: Type, procs: REF Sequences.SequenceTypeProcs, cc: CC, data: REF ANY] RETURNS[Type] = BEGIN tailInfo: SRTailInfo _ NEW[SRTailInfoBody_[NIL, NIL, tagName, indexType, procs, data]]; tailType: Type _ CCTypes.CreateCedarType[$sequenceUnionTail, SRUTailCCTypeProcs, ISRUTailCCTypeProcs, cc, tailInfo]; tailInfo.self _ tailType; RETURN[tailType]; END; SRUTailCCTypeProcs: REF CCTypes.CCTypeProcs _ NEW[CCTypes.CCTypeProcs _[ checkConformance: SRUTCCTypesCheckConformance, operand: SRUTCCTypesOperand, applyOperand: SRUTCCTypesApplyOperand, indexOperand: SRUTCCTypesIndexOperand, binaryOperandTypes: SRUTCCTypesBinaryOperandTypes, extractIdField: SRUTCCTypesExtractIdField, apply: SRUTCCTypesApply, index: SRUTCCTypesIndex]]; SRUTCCTypesCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valTailInfo: SRTailInfo _ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varTailInfo: SRTailInfo => BEGIN conforms1: CCTypes.ConformanceCheck; conforms2: CCTypes.ConformanceCheck; IF NOT Rope.Equal[valTailInfo.tagName, varTailInfo.tagName] THEN RETURN[no]; conforms1 _ CCTypes.CheckConformance[valTailInfo.indexType, varTailInfo.indexType, cc]; IF conforms1 = no THEN RETURN[no]; conforms2 _ CCTypes.CheckConformance[valTailInfo.procs.getEntryType[cc, valTailInfo.data], varTailInfo.procs.getEntryType[cc, varTailInfo.data], cc]; IF conforms2 = no THEN RETURN[no]; IF conforms1 = yes AND conforms2 = yes THEN RETURN[yes]; RETURN[dontKnow]; END; ENDCASE => RETURN[no]; END; SRUTCCTypesOperand: PROC[op: CedarCode.Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $apply, $index => SELECT lr FROM left => RETURN[tc]; ENDCASE => CCE[operation]; ENDCASE => CCE[operation]; -- client error, invalid operation END; SRUTCCTypesApplyOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; RETURN[CCTypes.ApplyOperand[operatorType, operand, cc, tailInfo.procs.getNominalArrayType[cc, tailInfo.data]]]; END; SRUTCCTypesIndexOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; RETURN[CCTypes.IndexOperand[operatorType, operand, cc, CCTypes.GetIndirectType[tailInfo.procs.getNominalArrayType[cc, tailInfo.data]]]]; END; SRUTCCTypesBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; RETURN[CCTypes.BinaryOperandTypes[op, left, right, cc, tailInfo.procs.getNominalArrayType[cc, tailInfo.data]]]; END; SRUTCCTypesExtractIdField: PROC[id: Rope.ROPE, fieldContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; IF Rope.Equal[id, tailInfo.tagName] THEN BEGIN code: Code _ CedarCode.CodeToExtractField["&Tag", fieldContext]; RETURN[[code, tailInfo.indexType]]; END ELSE CCE[operation, Rope.Cat["field ", id, " does not exist"]] -- client type error, no such field END; SRUTCCTypesApply: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; RETURN[CCTypes.Apply[operator, operand, cc, tailInfo.procs.getNominalArrayType[cc, tailInfo.data]]]; END; SRUTCCTypesIndex: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; RETURN[CCTypes.Index[operator, operand, cc, CCTypes.GetIndirectType[tailInfo.procs.getNominalArrayType[cc, tailInfo.data]]]]; END; ISRUTailCCTypeProcs: REF CCTypes.CCTypeProcs _ NEW[CCTypes.CCTypeProcs _[ store: ISRUTCCTypesStore, selectIdField: ISRUTCCTypesSelectIdField, index: ISRUTCCTypesIndex]]; ISRUTCCTypesStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = {CCE[operation, "attempt to store a sequence"]}; <<>> <> ISRUTCCTypesSelectIdField: PROC[id: Rope.ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; IF Rope.Equal[id, tailInfo.tagName] THEN BEGIN code: Code _ CedarCode.CodeToSelectField["&Tag", fieldIndirectContext]; RETURN[[code, tailInfo.indexType]]; END ELSE CCE[operation, Rope.Cat["field ", id, " does not exist"]] -- client type error, no such field END; ISRUTCCTypesIndex: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN tailInfo: SRTailInfo _ NARROW[procData]; indirectNominalArrayType: Type _ CCTypes.GetIndirectType[tailInfo.procs.getNominalArrayType[cc, tailInfo.data]]; RETURN[CCTypes.Index[operator, operand, cc, indirectNominalArrayType]]; END; <> <<>> <> <<>> <> IndirectSRProcs: TYPE = Sequences.IndirectSRProcs; IndirectSRData: TYPE = REF IndirectSRDataBody; IndirectSRDataBody: TYPE = RECORD[ targetSeqType: Type, procs: REF IndirectSRProcs, procsData: REF ANY, indirectTail: CirioTypes.Node]; CreateIndirectSequenceNode: PUBLIC PROC[targetSeqType: Type, procs: REF IndirectSRProcs, procsData: REF ANY, cc: CC] RETURNS[Node] = BEGIN srTypeInfo: SRInfo _ NARROW[CCTypes.GetProcDataFromGroundType[targetSeqType, cc]]; isrData: IndirectSRData _ NEW[IndirectSRDataBody _ [targetSeqType, procs, procsData, NIL]]; node: Node _ CedarCode.CreateCedarNode[IndirectSROps, CCTypes.GetIndirectType[targetSeqType], isrData]; isrData.indirectTail _ CreateIndirectSequenceTail[srTypeInfo.tailType, isrData, cc]; RETURN[node]; END; IndirectSROps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ unaryOp: IndirectSRUnaryOp, load: IndirectSRLoad, selectField: IndirectSRSelectField, show: IndirectSRShow]]; <<>> IndirectSRUnaryOp: PROC [op: CedarCode.Operator, type: CirioTypes.Type, node: CirioTypes.Node, cc: CC] RETURNS [CirioTypes.Node] = BEGIN indirectNodeData: IndirectSRData _ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[indirectNodeData.procs.getPointer[indirectNodeData.procsData, cc]]; END; IndirectSRLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[CirioTypes.Node] = BEGIN isrData: IndirectSRData _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; RETURN[CreateSequenceRecordNode[isrData.targetSeqType, DLSRProcs, isrData, cc, FALSE]]; END; IndirectSRSelectField: PROC[id: Rope.ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN isrData: IndirectSRData _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; SELECT TRUE FROM Rope.Equal[id, "&Preamble"] => RETURN[isrData.procs.selectPreamble[isrData.procsData, cc]]; Rope.Equal[id, "&Tail"] => RETURN[isrData.indirectTail]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; IndirectSRShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { to.PutChar['^]; IF depth = 0 THEN {to.PutRope["[...]"]; RETURN}; { isrType: Type _ CedarCode.GetTypeOfNode[node]; sr: Node _ CedarCode.LoadThroughIndirectNode[isrType, node, cc]; CedarCode.ShowNode[to, sr, depth-1, width, cc]; RETURN}}; DLSRProcs: REF SRNodeProcs _ NEW[SRNodeProcs_[ extractPreamble: DLSRExtractPreamble, extractTag: DLSRExtractTag, extractTailEntry: DLSRExtractTailEntry]]; DLSRExtractPreamble: PROC[procsData: REF ANY, cc: CC] RETURNS[CirioTypes.Node] = BEGIN isrData: IndirectSRData _ NARROW[procsData]; indirectPreamble: Node _ isrData.procs.selectPreamble[isrData.procsData, cc]; indirectPreambleType: Type _ CedarCode.GetTypeOfNode[indirectPreamble]; RETURN[CedarCode.LoadThroughIndirectNode[indirectPreambleType, indirectPreamble, cc]]; END; DLSRExtractTag: PROC[procsData: REF ANY, cc: CC] RETURNS[CirioTypes.Node] = BEGIN isrData: IndirectSRData _ NARROW[procsData]; indirectTag: Node _ isrData.procs.selectTag[isrData.procsData, cc]; indirectTagType: Type _ CedarCode.GetTypeOfNode[indirectTag]; RETURN[CedarCode.LoadThroughIndirectNode[indirectTagType, indirectTag, cc]]; END; DLSRExtractTailEntry: PROC[index: CARD, procsData: REF ANY, cc: CC] RETURNS[CirioTypes.Node] = BEGIN isrData: IndirectSRData _ NARROW[procsData]; indirectEntry: Node _ isrData.procs.selectTailEntry[index, isrData.procsData, cc]; indirectEntryType: Type _ CedarCode.GetTypeOfNode[indirectEntry]; RETURN[CedarCode.LoadThroughIndirectNode[indirectEntryType, indirectEntry, cc]]; END; <<>> <> CreateIndirectSequenceTail: PROC[stType: Type, isrData: IndirectSRData, cc: CC] RETURNS[Node] = BEGIN node: Node _ CedarCode.CreateCedarNode[IndirectSTOps, CCTypes.GetIndirectType[stType], isrData]; RETURN[node]; END; IndirectSTOps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ load: IndirectSTLoad, selectField: IndirectSTSelectField, index: IndirectSTIndex, show: IndirectSTShow]]; IndirectSTLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN CCE[cirioError]; -- one should always load the whole sequence record then extract the tail. END; IndirectSTSelectField: PROC[id: Rope.ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN isrData: IndirectSRData _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; SELECT TRUE FROM Rope.Equal[id, "&Tag"] => RETURN[isrData.procs.selectTag[isrData.procsData, cc]]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; IndirectSTIndex: PROC[indirectOperatorType: Type, operandType: Type, indirectOperator: Node, operand: Node, cc: CC] RETURNS[Node] = BEGIN isrData: IndirectSRData _ NARROW[CedarCode.GetDataFromNode[indirectOperator]]; index: CARD _ CedarCode.NodeAsIndex[operandType, operand, cc]; <> indirectTag: Node _ isrData.procs.selectTag[isrData.procsData, cc]; indirectTagType: Type _ CedarCode.GetTypeOfNode[indirectTag]; tag: Node _ CedarCode.LoadThroughIndirectNode[indirectTagType, indirectTag, cc]; limit: CARD _ CedarCode.NodeAsIndex[operandType, tag, cc]; IF index >= limit THEN CCE[operation, "bounds check"]; RETURN[isrData.procs.selectTailEntry[index, isrData.procsData, cc]]; END; IndirectSTShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = BEGIN CCE[cirioError]; -- can this happen? VariantRecordsImpl provides a procedure here. However, it calls LoadThroughIndirect, which should in turn call IndirectVTLoad. But, VariantRecordsImpl does not provide IndirectVTLoad. So, I am unsure. END; <<>> <> SRData: TYPE = REF SRDataBody; SRDataBody: TYPE = RECORD[ procs: REF SRNodeProcs, procsData: REF ANY, tail: Node]; SRNodeProcs: TYPE = RECORD[ extractPreamble: PROC[procsData: REF ANY, cc: CC] RETURNS[CirioTypes.Node], extractTag: PROC[procsData: REF ANY, cc: CC] RETURNS[CirioTypes.Node], extractTailEntry: PROC[index: CARD, procsData: REF ANY, cc: CC] RETURNS[CirioTypes.Node]]; CreateSequenceRecordNode: PROC[type: Type, procs: REF SRNodeProcs, procsData: REF ANY, cc: CC, alreadyLoaded: BOOLEAN] RETURNS[Node] = BEGIN srData: SRData _ NEW[SRDataBody_[procs, procsData, NIL]]; srTypeInfo: SRInfo _ NARROW[CCTypes.GetProcDataFromGroundType[type, cc]]; srData.tail _ CreateSequenceRecordTailNode[srTypeInfo.tailType, srData, cc]; RETURN[CedarCode.CreateCedarNode[SequenceRecordOps, type, srData]]; END; SequenceRecordOps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ forceIn: SRForceIn, extractField: SRExtractField, show: SRShow]]; SRForceIn: PROC[type: Type, node: Node, cc: CC] RETURNS[Node] = {CCE[unimplemented, "can not force in a sequence record"]}; SRExtractField: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN srData: SRData _ NARROW[CedarCode.GetDataFromNode[node]]; SELECT TRUE FROM Rope.Equal[id, "&Preamble"] => RETURN[srData.procs.extractPreamble[srData.procsData, cc]]; Rope.Equal[id, "&Tail"] => RETURN[srData.tail]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; SRShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { srData: SRData _ NARROW[CedarCode.GetDataFromNode[node]]; to.PutChar['[]; IF depth = 0 THEN to.PutRope["..."] ELSE { CedarCode.ShowNode[to, srData.procs.extractPreamble[srData.procsData, cc], depth-1, width, cc]; to.PutChar[',]; CedarCode.BreakShowNode[to, srData.tail, depth-1, width, cc, " "]}; to.PutChar[']]; RETURN}; <> CreateSequenceRecordTailNode: PROC[tailType: Type, srData: SRData, cc: CC] RETURNS[Node] = BEGIN node: Node _ CedarCode.CreateCedarNode[SRTOps, tailType, srData]; RETURN[node]; END; SRTOps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ forceIn: SRTForceIn, extractField: SRTExtractField, apply: SRTApply, show: SRTShow]]; SRTForceIn: PROC[type: Type, node: Node, cc: CC] RETURNS[Node] = {CCE[unimplemented, "can not force in a sequence record"]}; SRTExtractField: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN srData: SRData _ NARROW[CedarCode.GetDataFromNode[node]]; SELECT TRUE FROM Rope.Equal[id, "&Tag"] => RETURN[srData.procs.extractTag[srData.procsData, cc]]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; SRTApply: PROC[operatorType: Type, operandType: Type, operator: Node, operand: Node, cc: CC] RETURNS[Node] = BEGIN srData: SRData _ NARROW[CedarCode.GetDataFromNode[operator]]; index: CARD _ CedarCode.NodeAsIndex[operandType, operand, cc]; <> tag: Node _ srData.procs.extractTag[srData.procsData, cc]; limit: CARD _ CedarCode.NodeAsIndex[operandType, tag, cc]; IF index >= limit THEN CCE[operation, "bounds check"]; RETURN[srData.procs.extractTailEntry[index, srData.procsData, cc]]; END; SRTShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { srData: SRData _ NARROW[CedarCode.GetDataFromNode[node]]; tag: Node _ srData.procs.extractTag[srData.procsData, cc]; tagType: Type _ CedarCode.GetTypeOfNode[tag]; limit: CARD _ CedarCode.NodeAsIndex[tagType, tag, cc]; to.PutF["(%g)[", [cardinal[limit]] ]; IF depth = 0 THEN to.PutRope["..."] ELSE { cWidth: INT _ width; FOR I: CARD IN [0..limit) DO entry: Node _ srData.procs.extractTailEntry[I, srData.procsData, cc]; IF I>0 THEN to.PutChar[',]; IF cWidth < 0 THEN {to.PutRope["..."]; EXIT}; CedarCode.BreakShowNode[to, entry, depth-1, width, cc, " "]; cWidth _ cWidth-1; ENDLOOP; }; to.PutChar[']]; RETURN}; <<>> END.