<> <> DIRECTORY ThreeC4Support USING[GetReportStream], ThreeC4BaseDecl1Def USING[AppendToTypeList, BuildEmptyCode, BuildEmptyTypeList, BuildName, BuildName2, BuildRopeName, CodeFill, ConcatCode2, GetTheOneType, IdentifierNode, IdFill2, MesaCodeNode, NameFill, NameListNode, NameNode, RopeCode, RopeCode1, RopeFromRopeNode, RopeNode, TestEmptyCode, TypeListNode, TypeNode], ThreeC4BaseDecl2Def USING[FcnDefGraphNode, FunctionCase, Use], ThreeC4BasicAbTypesDef USING[IdListNode, WholeFileNode], ThreeC4RootAbGramDef USING[], ThreeC4PrimImplDefs USING[BuildType, CopyTypeList, CreateHashTable, EnumerateHashTable, EqualNames, FindEntry, FindExistingEntry, GenNames, GenNameTypePairs, GenTypeList, GetNameIds, GetNameInfo, GetTypeInfo, HashTable, MakeEntry, RopeFromCode, ShowCode, ShowName, ShowNameList], ThreeC4FlowAnalDefs USING[ShowFcnDefGraph], IO USING[PutF, PutRope, rope, STREAM], Rope USING[Equal, ROPE]; ThreeC4PrimImpl3: CEDAR PROGRAM IMPORTS ThreeC4Support, ThreeC4BaseDecl1Def, ThreeC4PrimImplDefs, ThreeC4FlowAnalDefs, IO, Rope EXPORTS ThreeC4BaseDecl1Def, ThreeC4BaseDecl2Def, ThreeC4BasicAbTypesDef, ThreeC4RootAbGramDef, ThreeC4PrimImplDefs = BEGIN OPEN ThreeC4BaseDecl1Def, ThreeC4BaseDecl2Def, ThreeC4BasicAbTypesDef, ThreeC4PrimImplDefs, ThreeC4FlowAnalDefs; -- symbol table stuff ContextNode: TYPE = REF ContextNodeBody; ContextNodeBody: PUBLIC TYPE = RECORD[ types: HashTable, abstProds: HashTable, functions: HashTable, values: HashTable, grammarSymbols: HashTable, -- except genericTokens, which are in types -- productions: HashTable, parseTrees: HashTable]; AbstractTypeInfo: TYPE = REF AbstractTypeInfoBody; AbstractTypeInfoBody: TYPE = RECORD[ abstractTypeId: IdentifierNode, -- named to make this record different type from others, due to unpainted record types in Cedar Program modules. mesaDefFileName: Rope.ROPE, textCodeName: Rope.ROPE, recFcnIdList: IdListNode, recFcnNameList: NameListNode]; SimpleBaseTypeInfo: TYPE = REF SimpleBaseTypeInfoBody; SimpleBaseTypeInfoBody: TYPE = RECORD[ simpleBaseTypeId: IdentifierNode, mesaDefFileName: Rope.ROPE, textCodeName: Rope.ROPE]; EnumeratedBaseTypeInfo: TYPE = REF EnumeratedBaseTypeInfoBody; EnumeratedBaseTypeInfoBody: TYPE = RECORD[ enumeratedBaseTypeId: IdentifierNode, mesaDefFileName: Rope.ROPE, names: NameListNode, textCodeName: Rope.ROPE]; AbstractProductionInfo: TYPE = REF AbstractProductionInfoBody; AbstractProductionInfoBody: TYPE = RECORD[ abstractTypeId: IdentifierNode, caseId: IdentifierNode, -- might be NIL mesaDefFileName: Rope.ROPE, rightSideNames: NameListNode, productionContext: ContextNode]; AbstractRightSideSymbolInfo: TYPE = REF AbstractRightSideSymbolInfoBody; AbstractRightSideSymbolInfoBody: TYPE = RECORD[ typeName: NameNode]; GenericTokenTypeInfo: TYPE = REF GenericTokenTypeInfoBody; GenericTokenTypeInfoBody: TYPE = RECORD[ genericTokenTypeId: IdentifierNode, mesaDefFileName: Rope.ROPE, textCodeName: Rope.ROPE]; PreDefinedCedarTypeInfo: TYPE = REF PreDefinedCedarTypeInfoBody; PreDefinedCedarTypeInfoBody: TYPE = RECORD[ preDefinedCedarTypeId: IdentifierNode, textCodeName: Rope.ROPE]; CedarTypeInfo: TYPE = REF CedarTypeInfoBody; CedarTypeInfoBody: TYPE = RECORD[ cedarTypeId: IdentifierNode, mesaDefFileName: Rope.ROPE, textCodeName: Rope.ROPE]; <> TreeTypeInfo: TYPE = REF TreeTypeInfoBody; TreeTypeInfoBody: TYPE = RECORD[ treeTypeId: IdentifierNode, -- always nil textCodeName: Rope.ROPE]; RecFcnInfo: TYPE = REF RecFcnInfoBody; RecFcnInfoBody: TYPE = RECORD[ recFcnId: IdentifierNode, -- always nil, to make unique record type mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode, defGraph: FcnDefGraphNode]; BaseFcnInfo: TYPE = REF BaseFcnInfoBody; BaseFcnInfoBody: TYPE = RECORD[ baseFcnId: IdentifierNode, -- always nil, to make unique record type mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode, defGraph: FcnDefGraphNode]; CedarFcnInfo: TYPE = REF CedarFcnInfoBody; CedarFcnInfoBody: TYPE = RECORD[ cedarFcnId: IdentifierNode, -- always nil, to make unique record type mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode, defGraph: FcnDefGraphNode]; RopeTokenInfo: TYPE = REF RopeTokenInfoBody; RopeTokenInfoBody: TYPE = RECORD[ ropeTknId: IdentifierNode, -- always nil, to make unique record type name: NameNode]; NonTerminalTokenInfo: TYPE = REF NonTerminalTokenInfoBody; NonTerminalTokenInfoBody: TYPE = RECORD[ nonTerminalTokenId: IdentifierNode, -- always nil, to make unique record type name: NameNode, builds: TypeNode]; ProductionInfo: TYPE = REF ProductionInfoBody; ProductionInfoBody: TYPE = RECORD[ productionInfoId: IdentifierNode, -- always nil, to make unique record type name: NameNode, index: INT]; ControlModuleInfo: TYPE = REF ControlModuleInfoBody; ControlModuleInfoBody: TYPE = RECORD[ controlModuleInfoId: IdentifierNode, -- always nil, to make unique record type mesaDefFileName: Rope.ROPE]; ParseTreeInfo: TYPE = REF ParseTreeInfoBody; ParseTreeInfoBody: TYPE = RECORD[ parseTreeInfoId: IdentifierNode, -- always nil, to make unique record type tree: WholeFileNode]; <> <<>> <<>> BuildEmptyContext: PUBLIC PROC RETURNS[ContextNode] = BEGIN RETURN[NEW[ContextNodeBody_[ CreateHashTable[10], CreateHashTable[10], CreateHashTable[10], CreateHashTable[10], CreateHashTable[10], CreateHashTable[10], CreateHashTable[10]]]]; END; FakeCopyContextForConditional: PUBLIC PROC[arg: ContextNode] RETURNS[ContextNode] = {RETURN[arg]}; RecordAbstractType: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, codeName: MesaCodeNode, recFcnIdList: IdListNode, recFcnNameList: NameListNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[AbstractTypeInfoBody_[id1, mesaDefFileName, RopeFromCode[codeName], recFcnIdList, recFcnNameList]]]; RETURN[context]; END; RecordSimpleBaseType: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[SimpleBaseTypeInfoBody_[id1, mesaDefFileName, RopeFromCode[codeName]]]]; RETURN[context]; END; <> RecordEnumeratedBaseType: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, names: NameListNode, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[EnumeratedBaseTypeInfoBody_[id1, mesaDefFileName, names, RopeFromCode[codeName]]]]; RETURN[context]; END; <> <> RecordAbstractProduction: PUBLIC PROC[context: ContextNode, productionName: NameNode, mesaDefFileName: Rope.ROPE, rightSideNames: NameListNode, productionContext: ContextNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[productionName]; MakeEntry[context.abstProds, productionName, NEW[AbstractProductionInfoBody_[id1, id2, mesaDefFileName, rightSideNames, productionContext]]]; RETURN[context]; END; <> RecordAbstRightSideSymbol: PUBLIC PROC[context: ContextNode, name: NameNode, typeName: NameNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.values, name, NEW[AbstractRightSideSymbolInfoBody_[typeName]]]; RETURN[context]; END; <> RecordGenericToken: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[GenericTokenTypeInfoBody_[id1, mesaDefFileName, RopeFromCode[codeName]]]]; RETURN[context]; END; <> RecordGenericTokenFrom: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[GenericTokenTypeInfoBody_[id1, mesaDefFileName, RopeFromCode[codeName]]]]; RETURN[context]; END; <> RecordPreDefinedCedarType: PUBLIC PROC[context: ContextNode, type: NameNode, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[PreDefinedCedarTypeInfoBody_[id1, RopeFromCode[codeName]]]]; RETURN[context]; END; <> RecordCedarType: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[CedarTypeInfoBody_[id1, mesaDefFileName, RopeFromCode[codeName]]]]; RETURN[context]; END; <> <> RecordCedarFunction: PUBLIC PROC[context: ContextNode, name: NameNode, mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.functions, name, NEW[CedarFcnInfoBody_[NIL, mesaDefFileName, argTypes, resultTypes]]]; RETURN[context]; END; <> <> RecordBaseFunction: PUBLIC PROC[context: ContextNode, name: NameNode, mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode, defGraph: FcnDefGraphNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.functions, name, NEW[BaseFcnInfoBody_[NIL, mesaDefFileName, argTypes, resultTypes, defGraph]]]; RETURN[context]; END; <> <> RecordRecFcnDef: PUBLIC PROC[context: ContextNode, name: NameNode, mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode, defGraph: FcnDefGraphNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.functions, name, NEW[RecFcnInfoBody_[NIL, mesaDefFileName, argTypes, resultTypes, defGraph]]]; RETURN[context] END; <> <> RecordBaseFcnDef: PUBLIC PROC[context: ContextNode, name: NameNode, mesaDefFileName: Rope.ROPE, argTypes: TypeListNode, resultTypes: TypeListNode, defGraph: FcnDefGraphNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.functions, name, NEW[BaseFcnInfoBody_[NIL, mesaDefFileName, argTypes, resultTypes, defGraph]]]; RETURN[context] END; <<>> <> RecordGlobalTreeType: PUBLIC PROC[context: ContextNode, name: NameNode, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.types, name, NEW[TreeTypeInfoBody_[NIL, RopeFromCode[codeName]]]]; RETURN[context]; END; <> RecordRopeToken: PUBLIC PROC[context: ContextNode, rope: RopeNode] RETURNS[ContextNode] = BEGIN name: NameNode _ BuildRopeName[RopeFromRopeNode[rope]]; MakeEntry[context.grammarSymbols, name, NEW[RopeTokenInfoBody_[NIL, name]]]; RETURN[context]; END; <> RecordNonTerminalToken: PUBLIC PROC[context: ContextNode, name: NameNode, builds: NameNode] RETURNS[ContextNode] = BEGIN type: TypeNode _ FindType[context, builds]; IF GetNameIds[name].id2 # NIL THEN ERROR; MakeEntry[context.grammarSymbols, name, NEW[NonTerminalTokenInfoBody_[NIL, name, type]]]; RETURN[context]; END; <> RecordProduction: PUBLIC PROC[context: ContextNode, name: NameNode, index: INT] RETURNS[ContextNode] = BEGIN MakeEntry[context.productions, name, NEW[ProductionInfoBody_[NIL, name, index]]]; RETURN[context]; END; <> RecordControlModule: PUBLIC PROC[context: ContextNode, mesaDefFileName: Rope.ROPE] RETURNS[ContextNode] = BEGIN MakeEntry[context.types, BuildRopeName["$Control"], NEW[ControlModuleInfoBody_[NIL, mesaDefFileName]]]; RETURN[context]; END; <> RecordAbstractTypeFrom: PUBLIC PROC[context: ContextNode, type: NameNode, mesaDefFileName: Rope.ROPE, codeName: MesaCodeNode] RETURNS[ContextNode] = BEGIN id1, id2: IdentifierNode; [id1, id2] _ GetNameIds[type]; IF id2 # NIL THEN ERROR; MakeEntry[context.types, type, NEW[AbstractTypeInfoBody_[id1, mesaDefFileName, RopeFromCode[codeName], NIL, NIL]]]; RETURN[context]; END; RecordParseTree: PUBLIC PROC[context: ContextNode, name: NameNode, tree: WholeFileNode] RETURNS[ContextNode] = BEGIN MakeEntry[context.parseTrees, name, NEW[ParseTreeInfoBody_[NIL, tree]]]; RETURN[context] END; FindParseTree: PUBLIC PROC[context: ContextNode, name: NameNode] RETURNS[WholeFileNode] = BEGIN info: ParseTreeInfo _ NARROW[FindEntry[context.parseTrees, name]]; RETURN[IF info = NIL THEN NIL ELSE info.tree] END; <> RecordOtherParseTree: PUBLIC PROC[context: ContextNode, name: NameNode, info: REF ANY] RETURNS[ContextNode] = BEGIN MakeEntry[context.parseTrees, name, info]; RETURN[context] END; <<>> <> FindOtherParseTree: PUBLIC PROC[context: ContextNode, name: NameNode] RETURNS[REF ANY] = BEGIN info: REF ANY _ FindExistingEntry[context.parseTrees, name]; RETURN[info] END; <> <> RecordOtherType: PUBLIC PROC[context: ContextNode, name: NameNode, info: REF ANY] RETURNS[ContextNode] = BEGIN MakeEntry[context.types, name, info]; RETURN[context] END; FindType: PUBLIC PROC[context: ContextNode, name: NameNode] RETURNS[TypeNode] = {RETURN[BuildType[FindExistingEntry[context.types, name]]]}; GetTypeCodeName: PUBLIC PROC[type: TypeNode] RETURNS[MesaCodeNode] = BEGIN WITH GetTypeInfo[type] SELECT FROM ati: AbstractTypeInfo => RETURN[RopeCode[ati.textCodeName]]; sbti: SimpleBaseTypeInfo => RETURN[RopeCode[sbti.textCodeName]]; gtti: GenericTokenTypeInfo => RETURN[RopeCode[gtti.textCodeName]]; pdcti: PreDefinedCedarTypeInfo => RETURN[RopeCode[pdcti.textCodeName]]; cti: CedarTypeInfo => RETURN[RopeCode[cti.textCodeName]]; tti: TreeTypeInfo => RETURN[RopeCode[tti.textCodeName]]; ebti: EnumeratedBaseTypeInfo => RETURN[RopeCode[ebti.textCodeName]]; ENDCASE => ERROR; END; CompareValTypeWithVarType: PUBLIC PROC[val: TypeNode, var: TypeNode] RETURNS[BOOLEAN] = BEGIN IF val = var THEN RETURN[TRUE]; IF GetTypeInfo[val] = GetTypeInfo[var] THEN RETURN[TRUE]; WITH GetTypeInfo[var] SELECT FROM tti: TreeTypeInfo => NULL; ENDCASE => ERROR; WITH GetTypeInfo[val] SELECT FROM ati: AbstractTypeInfo => NULL; ENDCASE => ERROR; RETURN[TRUE]; END; ShortShowType: PUBLIC PROC[type: TypeNode, on: IO.STREAM] = BEGIN WITH GetTypeInfo[type] SELECT FROM ati: AbstractTypeInfo => ShowId[ati.abstractTypeId, on]; sbti: SimpleBaseTypeInfo => ShowId[sbti.simpleBaseTypeId, on]; gtti: GenericTokenTypeInfo => ShowId[gtti.genericTokenTypeId, on]; pdcti: PreDefinedCedarTypeInfo => ShowId[pdcti.preDefinedCedarTypeId, on]; cti: CedarTypeInfo => ShowId[cti.cedarTypeId, on]; tti: TreeTypeInfo => IO.PutF[on, "Tree$"]; ebti: EnumeratedBaseTypeInfo => ShowId[ebti.enumeratedBaseTypeId, on]; ENDCASE => ERROR; END; ShowTypeList: PUBLIC PROC[typeList: TypeListNode, on: IO.STREAM] = BEGIN oneShown: BOOLEAN _ FALSE; seeOneType: PROC[type: TypeNode] = BEGIN IF oneShown THEN IO.PutRope[on, ", "] ELSE oneShown _ TRUE; ShortShowType[type, on]; END; GenTypeList[typeList, seeOneType]; END; CheckForBOOLEANType: PUBLIC PROC[type: TypeNode] RETURNS[BOOLEAN] = BEGIN WITH GetTypeInfo[type] SELECT FROM pdcti: PreDefinedCedarTypeInfo => IF Rope.Equal["BOOLEAN", pdcti.textCodeName] THEN RETURN[TRUE] ELSE ERROR; ENDCASE => ERROR; END; CheckForOneBoolean: PUBLIC PROC[list: TypeListNode] RETURNS[BOOLEAN] = BEGIN RETURN[CheckForBOOLEANType[GetTheOneType[list]]]; END; <> LookupContextNode: TYPE = REF LookupContextNodeBody; LookupContextNodeBody: PUBLIC TYPE = RECORD[ global: ContextNode, production: ContextNode, vars: VarItem, rightSideSymbols: RSSItem]; VarItem: TYPE = REF VarItemBody; VarItemBody: TYPE = RECORD[ name: NameNode, type: TypeNode, next: VarItem]; RSSItem: TYPE = REF RSSItemBody; RSSItemBody: TYPE = RECORD[ name: NameNode, type: TypeNode, next: RSSItem]; <> BuildBasicLookupContext: PUBLIC PROC[context: ContextNode] RETURNS[LookupContextNode] = {RETURN[NEW[LookupContextNodeBody_[context, NIL, NIL, NIL]]]}; FakeCopyLookupContext: PUBLIC PROC[lookup: LookupContextNode] RETURNS[LookupContextNode] = {RETURN[lookup]}; <> PushProductionContext: PUBLIC PROC[lookup: LookupContextNode, production: ContextNode] RETURNS[LookupContextNode] = BEGIN IF lookup.production # NIL THEN ERROR; RETURN[NEW[LookupContextNodeBody_[lookup.global, production, NIL]]]; END; <> RecordVarSeq: PUBLIC PROC[lookup: LookupContextNode, names: NameListNode, types: TypeListNode] RETURNS[LookupContextNode] = BEGIN newContext: LookupContextNode _ NEW[LookupContextNodeBody_[lookup.global, lookup.production, lookup.vars]]; SeePair: PROC[name: NameNode, type: TypeNode] = BEGIN newItem: VarItem _ NEW[VarItemBody_[name, type, newContext.vars]]; newContext.vars _ newItem; END; GenNameTypePairs[names, types, SeePair]; RETURN[newContext]; END; LookUpAbTypeRecFcnsIdList: PUBLIC PROC[lookup: LookupContextNode, typeName: NameNode] RETURNS[IdListNode] = {RETURN[(NARROW[FindExistingEntry[lookup.global.types, typeName], AbstractTypeInfo]).recFcnIdList]}; <<1st arg shared with both results>> LookUpAbProduction: PUBLIC PROC[lookup: LookupContextNode, prodName: NameNode] RETURNS[NameListNode, ContextNode] = BEGIN info: AbstractProductionInfo _ NARROW[FindExistingEntry[lookup.global.abstProds, prodName]]; RETURN[info.rightSideNames, info.productionContext] END; <<1st arg shared with first result>> LookUpRecFcnDef: PUBLIC PROC[lookup: LookupContextNode, funName: NameNode] RETURNS[TypeListNode, TypeListNode] = BEGIN info: RecFcnInfo _ NARROW[FindExistingEntry[lookup.global.functions, funName]]; RETURN[info.argTypes, CopyTypeList[info.resultTypes]]; END; <<1st arg shared with result>> LookUpFcnDefGraph: PUBLIC PROC[lookup: LookupContextNode, funName: NameNode] RETURNS[FcnDefGraphNode] = BEGIN info: REF ANY _ FindExistingEntry[lookup.global.functions, funName]; WITH info SELECT FROM rfi: RecFcnInfo => RETURN[rfi.defGraph]; bfi: BaseFcnInfo => RETURN[bfi.defGraph]; ENDCASE => ERROR; END; LookUpType: PUBLIC PROC[lookup: LookupContextNode, typeName: NameNode] RETURNS[TypeNode] = BEGIN RETURN[BuildType[FindExistingEntry[lookup.global.types, typeName]]]; END; <> <> LookUpOtherType: PUBLIC PROC[lookup: LookupContextNode, typeName: NameNode] RETURNS[REF ANY] = BEGIN RETURN[FindExistingEntry[lookup.global.types, typeName]]; END; LookUpSimpleValue: PUBLIC PROC[lookup: LookupContextNode, id: IdentifierNode] RETURNS[TypeNode, MesaCodeNode] = BEGIN name: NameNode _ BuildName[id]; -- see if its a local variable FOR varItem: VarItem _ lookup.vars, varItem.next WHILE varItem # NIL DO IF EqualNames[varItem.name, name] THEN RETURN[varItem.type, RopeCode1["%g", NameFill[name]]]; ENDLOOP; -- see if we find it in production context BEGIN info: AbstractRightSideSymbolInfo _ NARROW[FindEntry[lookup.production.values, name]]; type: TypeNode _ IF info # NIL THEN LookUpType[lookup, info.typeName] ELSE NIL; IF type # NIL THEN RETURN[type, RopeCode1["treeData.%g", NameFill[name]]]; END; -- so, we can't find it ERROR; END; LookUpValue2: PUBLIC PROC[lookup: LookupContextNode, id1, id2: IdentifierNode] RETURNS[TypeNode, MesaCodeNode] = BEGIN -- see if we find it in production context BEGIN nameA: NameNode _ BuildName2[id1, id2]; info: AbstractRightSideSymbolInfo _ NARROW[FindEntry[lookup.production.values, nameA]]; type: TypeNode _ IF info # NIL THEN LookUpType[lookup, info.typeName] ELSE NIL; IF type # NIL THEN RETURN[type, RopeCode1["treeData.%g", IdFill2[id1, id2]]]; END; -- see if it is an enumerated type value BEGIN type: TypeNode; code: MesaCodeNode; [type, code] _ LookUpEnumTypeVal[lookup, BuildName[id1], BuildName[id2]]; IF type # NIL THEN RETURN[type, code]; END; -- so, we can't find it ERROR; END; LookUpEnumTypeVal: PUBLIC PROC[lookup: LookupContextNode, nameB1: NameNode, nameB2: NameNode] RETURNS[TypeNode, MesaCodeNode] = BEGIN type: TypeNode _ LookUpType[lookup, nameB1]; info : REF ANY _ GetTypeInfo[type]; WITH info SELECT FROM ebti: EnumeratedBaseTypeInfo => BEGIN -- check for legal value name legal: BOOLEAN _ FALSE; seeName: PROC[nm: NameNode] = {IF EqualNames[nm, nameB2] THEN legal _ TRUE}; GenNames[ebti.names, seeName]; IF legal THEN RETURN[type, ConcatCode2[RopeCode[ebti.textCodeName], RopeCode1[".%g", NameFill[nameB2]]]]; ERROR; END; ENDCASE => NULL; RETURN[NIL, BuildEmptyCode[]]; END; <> LookUpFunction: PUBLIC PROC[lookup: LookupContextNode, funName: NameNode] RETURNS[case: FunctionCase, argTypes: TypeListNode, resultTypes: TypeListNode] = BEGIN info: REF ANY _ FindExistingEntry[lookup.global.functions, funName]; WITH info SELECT FROM rfi: RecFcnInfo => RETURN[recursive, rfi.argTypes, CopyTypeList[rfi.resultTypes]]; bfi: BaseFcnInfo => RETURN[base, bfi.argTypes, CopyTypeList[bfi.resultTypes]]; cfi: CedarFcnInfo => RETURN[base, cfi.argTypes, CopyTypeList[cfi.resultTypes]]; ENDCASE => ERROR; END; LookUpProduction: PUBLIC PROC[lookup: LookupContextNode, name: NameNode] RETURNS[INT] = BEGIN info: REF ANY _ FindExistingEntry[lookup.global.productions, name]; WITH info SELECT FROM pi: ProductionInfo => RETURN[pi.index]; ENDCASE => ERROR; END; LookUpParseTree: PUBLIC PROC[lookup: LookupContextNode, name: NameNode] RETURNS[WholeFileNode] = BEGIN info: ParseTreeInfo _ NARROW[FindExistingEntry[lookup.global.parseTrees, name]]; RETURN[info.tree] END; EqualFunCase: PUBLIC PROC[c1, c2: FunctionCase] RETURNS[BOOLEAN] = {RETURN[c1 = c2]}; CheckLegalRopeToken: PUBLIC PROC [lookup: LookupContextNode, rope: RopeNode] RETURNS[BOOLEAN] = BEGIN name: NameNode _ BuildRopeName[RopeFromRopeNode[rope]]; info: RopeTokenInfo _ NARROW[FindExistingEntry[lookup.global.grammarSymbols, name]]; RETURN[TRUE]; END; PushLocalRSS: PUBLIC PROC[lookup: LookupContextNode, name: NameNode, type: TypeNode] RETURNS[LookupContextNode] = BEGIN item: RSSItem _ NEW[RSSItemBody_[name, type, lookup.rightSideSymbols]]; newLookup: LookupContextNode _ NEW[LookupContextNodeBody_[lookup.global, lookup.production, lookup.vars, item]]; RETURN[newLookup]; END; <> LookUpGrammarSymbol: PUBLIC PROC[lookup: LookupContextNode, name: NameNode] RETURNS[TypeNode] = BEGIN info: REF ANY _ FindEntry[lookup.global.grammarSymbols, name]; IF info # NIL THEN WITH info SELECT FROM rti: RopeTokenInfo => ERROR; ntti: NonTerminalTokenInfo => RETURN[ntti.builds]; ENDCASE => ERROR; -- might be a generic token or abstract type info _ FindEntry[lookup.global.types, name]; WITH info SELECT FROM gtti: GenericTokenTypeInfo => RETURN[BuildType[info]]; ati: AbstractTypeInfo => ERROR; -- some day I want to have a concrete production build a pure value. This requires some more work in Tran2B.1casaba. ENDCASE => ERROR; END; LookUpAbstractProduction: PUBLIC PROC[lookup: LookupContextNode, name: NameNode] RETURNS[TypeNode, TypeListNode] = BEGIN info: REF ANY _ FindEntry[lookup.global.abstProds, name]; WITH info SELECT FROM api: AbstractProductionInfo => BEGIN type: TypeNode _ LookUpType[lookup, BuildName[api.abstractTypeId]]; -- why didnt I record the type typeList: TypeListNode _ BuildEmptyTypeList[]; seeAName: PROC[argName: NameNode] = {typeList _ AppendToTypeList[typeList, LookUpType[lookup, BuildName[GetNameIds[argName].id1]]]}; GenNames[api.rightSideNames, seeAName]; RETURN[type, typeList] END; ENDCASE => ERROR; END; LookUpRightSideSymbol: PUBLIC PROC[lookup: LookupContextNode, name: NameNode] RETURNS[TypeNode] = BEGIN FOR item: RSSItem _ lookup.rightSideSymbols, item.next WHILE item # NIL DO IF EqualNames[item.name, name] THEN RETURN[item.type]; ENDLOOP; RETURN[NIL]; END; EmptyRSContext: PUBLIC PROC[lookup: LookupContextNode] RETURNS[BOOLEAN] = {RETURN[lookup.rightSideSymbols = NIL]}; -- usage info UsageNode: TYPE = REF UsageNodeBody; UsageNodeBody: PUBLIC TYPE = RECORD[ usageHT: HashTable]; UseInfo: TYPE = REF UseInfoBody; UseInfoBody: TYPE = RECORD[ bits: ARRAY Use OF BOOLEAN]; BuildEmptyUsage: PUBLIC PROC RETURNS[UsageNode] = {RETURN[NEW[UsageNodeBody_[CreateHashTable[10]]]]}; <> RecordTypeUse: PUBLIC PROC[usage: UsageNode, type: TypeNode] RETURNS[UsageNode] = BEGIN fileName: Rope.ROPE; info: REF ANY _ GetTypeInfo[type]; WITH info SELECT FROM ati: AbstractTypeInfo => fileName _ ati.mesaDefFileName; sbti: SimpleBaseTypeInfo => fileName _ sbti.mesaDefFileName; gtti: GenericTokenTypeInfo => fileName _ gtti.mesaDefFileName; pdcti: PreDefinedCedarTypeInfo => RETURN[usage]; cti: CedarTypeInfo => fileName _ cti.mesaDefFileName; tti: TreeTypeInfo => RETURN[usage]; ebti: EnumeratedBaseTypeInfo => fileName _ ebti.mesaDefFileName; ENDCASE => ERROR; RecordUse[usage, BuildRopeName[fileName], ref]; RETURN[usage] END; <> RecordTypesUse: PUBLIC PROC[usage: UsageNode, types: TypeListNode] RETURNS[UsageNode] = BEGIN seeType: PROC[type: TypeNode] = {usage _ RecordTypeUse[usage, type]}; GenTypeList[types, seeType]; RETURN[usage]; END; <> RecordFcnUse: PUBLIC PROC[usage: UsageNode, name: NameNode, use: Use, context: LookupContextNode] RETURNS[UsageNode] = BEGIN info: REF ANY _ FindExistingEntry[context.global.functions, name]; fileName: Rope.ROPE; WITH info SELECT FROM rfi: RecFcnInfo => fileName _ rfi.mesaDefFileName; bfi: BaseFcnInfo => fileName _ bfi.mesaDefFileName; cfi: CedarFcnInfo => fileName _ cfi.mesaDefFileName; ENDCASE => ERROR; RecordUse[usage, BuildRopeName[fileName], use]; RETURN[usage] END; <> RecordAbstProdUse: PUBLIC PROC[usage: UsageNode, name: NameNode, use: Use, context: LookupContextNode] RETURNS[UsageNode] = BEGIN info: AbstractProductionInfo _ NARROW[FindExistingEntry[context.global.abstProds, name]]; fileName: Rope.ROPE _ info.mesaDefFileName; RecordUse[usage, BuildRopeName[fileName], use]; RETURN[usage] END; <> RecordGenericTokenUse: PUBLIC PROC[usage: UsageNode, name: NameNode, use: Use, context: LookupContextNode] RETURNS[UsageNode] = BEGIN info: GenericTokenTypeInfo _ NARROW[FindExistingEntry[context.global.types, name]]; fileName: Rope.ROPE _ info.mesaDefFileName; RecordUse[usage, BuildRopeName[fileName], use]; RETURN[usage] END; <> RecordLinkExport: PUBLIC PROC[usage: UsageNode, context: LookupContextNode] RETURNS[UsageNode] = BEGIN info: ControlModuleInfo _ NARROW[FindExistingEntry[context.global.types, BuildRopeName["$Control"]]]; RecordUse[usage, BuildRopeName["ParserDriver"], ref]; RecordUse[usage, BuildRopeName[info.mesaDefFileName], export]; RETURN[usage] END; RecordDefFileUse: PUBLIC PROC[usage: UsageNode, fNameText: Rope.ROPE, use: Use] RETURNS[UsageNode] = BEGIN RecordUse[usage, BuildRopeName[fNameText], use]; RETURN[usage]; END; Hello: SIGNAL = CODE; interestingFileName: Rope.ROPE _ NIL; interestingUse: Use _ import; RecordUse: PROC[usage: UsageNode, fileName: NameNode, use: Use] = BEGIN info: UseInfo _ NARROW[FindEntry[usage.usageHT, fileName]]; nameText: Rope.ROPE _ GetNameInfo[fileName].text; IF Rope.Equal[nameText, interestingFileName] AND use = interestingUse THEN Hello; IF info = NIL THEN BEGIN info _ NEW[UseInfoBody_[[FALSE, FALSE, FALSE]]]; MakeEntry[usage.usageHT, fileName, info]; END; info.bits[use] _ TRUE; END; BuildDefUseCode: PUBLIC PROC[usage: UsageNode, self: Rope.ROPE] RETURNS[directoryCode, openCode: MesaCodeNode] = BEGIN selfName: NameNode _ BuildRopeName[self]; ViewUseEntry: PROC[info: REF ANY, name: NameNode] = BEGIN useInfo: UseInfo _ NARROW[info]; IF EqualNames[name, selfName] THEN RETURN; IF useInfo.bits[ref] OR useInfo.bits[import] THEN BEGIN newCode: MesaCodeNode; IF directoryCode # NIL THEN newCode _ RopeCode1[",\N\T%g", NameFill[name]] ELSE newCode _ RopeCode1["\N\T%g", NameFill[name]]; directoryCode _ ConcatCode2[directoryCode, newCode]; END; IF useInfo.bits[export] AND NOT (useInfo.bits[ref] OR useInfo.bits[import]) THEN BEGIN newCode: MesaCodeNode; IF directoryCode # NIL THEN newCode _ RopeCode1[",\N\T%g USING[]", NameFill[name]] ELSE newCode _ RopeCode1["\N\T%g USING[]", NameFill[name]]; directoryCode _ ConcatCode2[directoryCode, newCode]; END; IF useInfo.bits[ref] OR useInfo.bits[import] THEN BEGIN newCode: MesaCodeNode; IF openCode # NIL THEN newCode _ RopeCode1[", %g", NameFill[name]] ELSE newCode _ RopeCode1["%g", NameFill[name]]; openCode _ ConcatCode2[openCode, newCode]; END; END; directoryCode _ BuildEmptyCode[]; openCode _ BuildEmptyCode[]; EnumerateHashTable[usage.usageHT, ViewUseEntry]; IF NOT TestEmptyCode[openCode] THEN openCode _ RopeCode1["OPEN %g;\N", CodeFill[openCode]]; RETURN[ RopeCode1["DIRECTORY%g;\N\N", CodeFill[directoryCode]], openCode]; END; BuildImplUseCode: PUBLIC PROC[usage: UsageNode] RETURNS[directoryCode, importsCode, exportsCode, openCode: MesaCodeNode] = BEGIN ViewUseEntry: PROC[info: REF ANY, name: NameNode] = BEGIN useInfo: UseInfo _ NARROW[info]; IF useInfo.bits[ref] OR useInfo.bits[import] THEN BEGIN newCode: MesaCodeNode; IF directoryCode # NIL THEN newCode _ RopeCode1[",\N\T%g", NameFill[name]] ELSE newCode _ RopeCode1["\N\T%g", NameFill[name]]; directoryCode _ ConcatCode2[directoryCode, newCode]; END; IF useInfo.bits[export] AND NOT (useInfo.bits[ref] OR useInfo.bits[import]) THEN BEGIN newCode: MesaCodeNode; IF directoryCode # NIL THEN newCode _ RopeCode1[",\N\T%g USING[]", NameFill[name]] ELSE newCode _ RopeCode1["\N\T%g USING[]", NameFill[name]]; directoryCode _ ConcatCode2[directoryCode, newCode]; END; IF useInfo.bits[import] THEN BEGIN newCode: MesaCodeNode; IF importsCode # NIL THEN newCode _ RopeCode1[", %g", NameFill[name]] ELSE newCode _ RopeCode1["%g", NameFill[name]]; importsCode _ ConcatCode2[importsCode, newCode]; END; IF useInfo.bits[export] THEN BEGIN newCode: MesaCodeNode; IF exportsCode # NIL THEN newCode _ RopeCode1[", %g", NameFill[name]] ELSE newCode _ RopeCode1["%g", NameFill[name]]; exportsCode _ ConcatCode2[exportsCode, newCode]; END; IF useInfo.bits[ref] OR useInfo.bits[import] THEN BEGIN newCode: MesaCodeNode; IF openCode # NIL THEN newCode _ RopeCode1[", %g", NameFill[name]] ELSE newCode _ RopeCode1["%g", NameFill[name]]; openCode _ ConcatCode2[openCode, newCode]; END; END; directoryCode _ BuildEmptyCode[]; importsCode _ BuildEmptyCode[]; exportsCode _ BuildEmptyCode[]; openCode _ BuildEmptyCode[]; EnumerateHashTable[usage.usageHT, ViewUseEntry]; IF NOT TestEmptyCode[importsCode] THEN importsCode _ RopeCode1[" IMPORTS %g", CodeFill[importsCode]]; IF NOT TestEmptyCode[exportsCode] THEN exportsCode _ RopeCode1[" EXPORTS %g", CodeFill[exportsCode]]; IF NOT TestEmptyCode[openCode] THEN openCode _ RopeCode1["OPEN %g;\N", CodeFill[openCode]]; RETURN[ RopeCode1["DIRECTORY%g;\N\N", CodeFill[directoryCode]], importsCode, exportsCode, openCode]; END; <> FakeUsageCopy: PUBLIC PROC[usage: UsageNode] RETURNS[UsageNode] = {RETURN[usage]}; <<>> <<>> <> ShowIndent: PROC[indent: CARDINAL, on: IO.STREAM] = BEGIN FOR I: CARDINAL IN [0..indent) DO IO.PutRope[on, " "] ENDLOOP; END; InspectContext: PUBLIC PROC[lookup: LookupContextNode] RETURNS[BOOLEAN] = BEGIN IF FALSE THEN ShowContext[lookup.global, 0, ThreeC4Support.GetReportStream[]]; RETURN[TRUE]; END; ShowContext: PUBLIC PROC[context: ContextNode, indent: CARDINAL, on: IO.STREAM] = BEGIN IF context = NIL THEN RETURN; ShowHashTable[context.types, indent, on, ShowTypeInfo]; ShowHashTable[context.abstProds, indent, on, ShowAbstractProductionInfo]; ShowHashTable[context.functions, indent, on, ShowFunctionInfo]; ShowHashTable[context.values, indent, on, ShowValueInfo]; END; ShowHashTable: PROC[table: HashTable, indent: CARDINAL, on: IO.STREAM, show: PROC[REF ANY, CARDINAL, IO.STREAM]] = BEGIN SeeOneEntry: PROC[info: REF ANY, name: NameNode] = BEGIN ShowIndent[indent, on]; ShowName[name, on]; IO.PutRope[on, "\N"]; show[info, indent+5, on]; END; EnumerateHashTable[table, SeeOneEntry]; END; ShowTypeInfo: PROC[info: REF ANY, indent: CARDINAL, on: IO.STREAM] = BEGIN WITH info SELECT FROM ati: AbstractTypeInfo => ShowAbstractTypeInfo[ati, indent, on]; sbti: SimpleBaseTypeInfo => ShowSimpleBaseTypeInfo[sbti, indent, on]; gtti: GenericTokenTypeInfo => ShowGenericTokenTypeInfo[gtti, indent, on]; pdcti: PreDefinedCedarTypeInfo => ShowPreDefinedCedarTypeInfo[pdcti, indent, on]; cti: CedarTypeInfo => ShowCedarTypeInfo[cti, indent, on]; tti: TreeTypeInfo => ShowTreeTypeInfo[tti, indent, on]; ebti: EnumeratedBaseTypeInfo => ShowEnumeratedBaseTypeInfo[ebti, indent, on]; cmi: ControlModuleInfo => ShowControlModuleInfo[cmi, indent, on]; ENDCASE => ERROR; END; ShowFunctionInfo: PROC[info: REF ANY, indent: CARDINAL, on: IO.STREAM] = BEGIN WITH info SELECT FROM rfib: RecFcnInfo => ShowRecFcnInfo[rfib, indent, on]; bfib: BaseFcnInfo => ShowBaseFcnInfo[bfib, indent, on]; ENDCASE => ERROR; END; ShowValueInfo: PROC[info: REF ANY, indent: CARDINAL, on: IO.STREAM] = BEGIN WITH info SELECT FROM arssi: AbstractRightSideSymbolInfo => ShowAbstractRightSideSymbolInfo[arssi, indent, on]; ENDCASE => ERROR; END; ShowAbstractTypeInfo: PROC[info: AbstractTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "is an abstract type, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowCodeNameText[info.textCodeName, indent+3, on]; ShowIndent[indent, on]; IO.PutRope[on, "\Tdefined recursive functions = ("]; ShowNameList[info.recFcnNameList, on]; IO.PutRope[on, ")\N"]; END; ShowSimpleBaseTypeInfo: PROC[info: SimpleBaseTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a simple base type, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowCodeNameText[info.textCodeName, indent+3, on]; END; ShowGenericTokenTypeInfo: PROC[info: GenericTokenTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a generic token type, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowCodeNameText[info.textCodeName, indent+3, on]; END; ShowPreDefinedCedarTypeInfo: PROC[info: PreDefinedCedarTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a pre defined Cedar type\N"]; ShowCodeNameText[info.textCodeName, indent+3, on]; END; ShowCedarTypeInfo: PROC[info: CedarTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a Cedar type, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowCodeNameText[info.textCodeName, indent+5, on]; END; ShowTreeTypeInfo: PROC[info: TreeTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a Tree type\N"]; ShowCodeNameText[info.textCodeName, indent+5, on]; END; ShowEnumeratedBaseTypeInfo: PROC[info: EnumeratedBaseTypeInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis an Enumerated Base Type, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowCodeNameText[info.textCodeName, indent+5, on]; ShowIndent[indent+5, on]; IO.PutRope[on, "value names = ("]; ShowNameList[info.names, on]; IO.PutF[on, ")\N"]; END; ShowControlModuleInfo: PROC[info: ControlModuleInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis control module info, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; END; ShowRecFcnInfo: PROC[info: RecFcnInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a recursive function, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowIndent[indent, on]; IO.PutF[on, "\Twith arg types = ("]; ShowTypeList[info.argTypes, on]; IO.PutF[on, "), result types = ("]; ShowTypeList[info.resultTypes, on]; IO.PutF[on, ")\N"]; ShowFcnDefGraph[info.defGraph, indent+2, on]; END; ShowBaseFcnInfo: PROC[info: BaseFcnInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "\Tis a base function, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowIndent[indent, on]; IO.PutF[on, "\Twith arg types = ("]; ShowTypeList[info.argTypes, on]; IO.PutF[on, "), result types = ("]; ShowTypeList[info.resultTypes, on]; IO.PutF[on, ")\N"]; ShowFcnDefGraph[info.defGraph, indent+2, on]; END; ShowAbstractProductionInfo: PROC[api: REF ANY, indent: CARDINAL, on: IO.STREAM] = BEGIN info: AbstractProductionInfo _ NARROW[api]; ShowIndent[indent, on]; IO.PutF[on, "is an abstract production, mesaDefFileName = %g\N", IO.rope[info.mesaDefFileName]]; ShowIndent[indent+5, on]; IO.PutF[on, "type = %g, case = %g\N", IO.rope[info.abstractTypeId.text], IF info.caseId # NIL THEN IO.rope[info.caseId.text] ELSE IO.rope[""]]; ShowIndent[indent+5, on]; IO.PutRope[on, "right side names = ("]; ShowNameList[info.rightSideNames, on]; IO.PutRope[on, ")\N"]; ShowIndent[indent+5, on]; IO.PutRope[on, "local context follows:\N"]; ShowContext[info.productionContext, indent+10, on]; END; ShowAbstractRightSideSymbolInfo: PROC[info: AbstractRightSideSymbolInfo, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutRope[on, "type = "]; ShowName[info.typeName, on]; IO.PutRope[on, "\N"]; END; ShowCodeName: PROC[codeName: MesaCodeNode, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "with codeName = "]; ShowCode[codeName, on]; IO.PutRope[on, "\N"]; END; ShowCodeNameText: PROC[text: Rope.ROPE, indent: CARDINAL, on: IO.STREAM] = BEGIN ShowIndent[indent, on]; IO.PutF[on, "with codeName = %g\N", IO.rope[text]]; END; ShowId: PROC[id: IdentifierNode, on: IO.STREAM] = {IO.PutF[on, "%g", IO.rope[id.text]]}; END..