-- ThreeC4RootImpl.ThreeC4
-- Sturgis, May 10, 1986 3:40:32 pm PDT

Include[ThreeC4BaseDecl, ThreeC4RecFcnDecl, ThreeC4BasicAbTypes, ThreeC4RootAbGram];

ThreeC4RootImpl: Module =
Begin


for MainGoal: AbstractProduction[WholeFile]
 let FormFileSeq[tree, context] ← BuildEmptyFileSeq[];

for WholeFile: AbstractProduction[IncludeClause, ModuleList]
 let FormFileSeq[tree, context] ← ConcatFileSeq[files1, files2]
   -- note: context will contain only the parse trees of previously read files
           
   where junk ← TearDownGraphs[lookupContext]
   
   where <files2, use> ← if TestFormControlFile[ModuleList] then
         (FormControlFileList[ModuleList,
          nProds,
          ConcatCode2[
           ConcatCodePairs2[
            SyntaxFileCodes[ModuleList, lookupContext],
            SyntaxFileCodes[IncludeClause, lookupContext]]],
          ConcatCode2[linkCallCode1, linkCallCode2],
          linkUsage]
         where <linkCallCode2, linkUsage> ←
            FormLinkCallCode[
             IncludeClause,
             lookupContext,
             linkUsage1]
         where <linkCallCode1, linkUsage1> ←
            FormLinkCallCode[
             ModuleList,
             lookupContext,
             BuildEmptyUsage[]])
       else <BuildEmptyFileSeq[], BuildEmptyUsage[]>
      
   where files1 ← MakeFileSeq[ModuleList, lookupContext]
   where check1 ← InspectContext[lookupContext]
   where lookupContext ← BuildBasicLookupContext[context7]
   where context7 ← CollectRightSideSymbols[ModuleList, context6]
   where context6 ← CollectRightSideSymbols[IncludeClause, context5]
   where context5 ← CollectFunctionTypes[ModuleList, context4]
   where context4 ← CollectFunctionTypes[IncludeClause, context3]
   where context3 ← CollectValueTypes[ModuleList, context2]
   where context2 ← CollectValueTypes[IncludeClause, context1]
   where <nProds, context1> ← CollectProductions[ModuleList, 0, baseContext]
   where baseContext ←
    RecordGlobalTreeType[
     context,
     BuildRopeName["Tree"],
     RopeCode["REF ANY"]]
     
 let CollectValueTypes[tree, context] ← CollectValueTypes[ModuleList, context]
 let CollectFunctionTypes[tree, context] ← CollectFunctionTypes[ModuleList, context]
 let CollectRightSideSymbols[tree, context] ← CollectRightSideSymbols[ModuleList, context]
 let FormLinkCallCode[tree, context, usage] ← FormLinkCallCode[ModuleList, context, usage]
 let SyntaxFileCodes[tree, context] ← SyntaxFileCodes[ModuleList, context];

for IncludeClause: AbstractProduction[IdList]
 let CollectValueTypes[tree, context] ← CollectValueTypes[IdList, context]
 let CollectFunctionTypes[tree, context] ← CollectFunctionTypes[IdList, context]
 let CollectRightSideSymbols[tree, context] ← CollectRightSideSymbols[IdList, context]
 let FormLinkCallCode[tree, context, usage] ← FormLinkCallCode[IdList, context, usage]
 let SyntaxFileCodes[tree, context] ← SyntaxFileCodes[IdList, context];


for ModuleList.One: AbstractProduction[ModuleBody]
 let CollectValueTypes[tree, context] ← CollectValueTypes[ModuleBody, context]
 let CollectFunctionTypes[tree, context] ← CollectFunctionTypes[ModuleBody, context]
 let CollectProductions[tree, first, context] ← CollectProductions[ModuleBody, first, context]
 let CollectRightSideSymbols[tree, context] ← CollectRightSideSymbols[ModuleBody, context]
 let SyntaxFileCodes[tree, context] ← SyntaxFileCodes[ModuleBody, context]
 let MakeFileSeq[tree, context] ← MakeFileSeq[ModuleBody, context]
 let TestFormControlFile[tree] ← TestFormControlFile[ModuleBody]
 let FormLinkCallCode[tree, context, usage] ← FormLinkCallCode[ModuleBody, context, usage]
 let FormControlFileList[tree, nProds, syntax, linkCalls, linkUsage] ←
   FormControlFileList[ModuleBody, nProds, syntax, linkCalls, linkUsage];


for ModuleList.Many: AbstractProduction[ModuleList, ModuleBody]
 let CollectValueTypes[tree, context] ←
   CollectValueTypes[ModuleBody, CollectValueTypes[ModuleList, context]]
 let CollectFunctionTypes[tree, context] ←
   CollectFunctionTypes[ModuleBody, CollectFunctionTypes[ModuleList, context]]
 let CollectProductions[tree, first, context] ←
   CollectProductions[ModuleBody, CollectProductions[ModuleList, first, context]]
 let CollectRightSideSymbols[tree, context] ←
   CollectRightSideSymbols[ModuleBody, CollectRightSideSymbols[ModuleList, context]]
 let SyntaxFileCodes[tree, context] ← ConcatCodePairs2[
   SyntaxFileCodes[ModuleList, context],
   SyntaxFileCodes[ModuleBody, context]]
 let MakeFileSeq[tree, context] ← ConcatFileSeq[
    MakeFileSeq[ModuleList, context],
    MakeFileSeq[ModuleBody, context]]
 let TestFormControlFile[tree] ←
   Or[TestFormControlFile[ModuleList], TestFormControlFile[ModuleBody]]
 let FormLinkCallCode[tree, context, usage] ← <ConcatCode2[listCode, oneBodyCode], use2>
   where <oneBodyCode, use2> ← FormLinkCallCode[ModuleBody, context, use1]
   where <listCode, use1> ← FormLinkCallCode[ModuleList, context, usage]
 let FormControlFileList[tree, nProds, syntax, linkCalls, linkUsage] ←
  <ConcatFileSeq[file1, file2], use1>
   where <file1, use1> ←
    FormControlFileList[ModuleList, nProds, syntax1, linkCalls1, use2]
   where <file2, use2> ←
    FormControlFileList[ModuleBody, nProds, syntax2, linkCalls2, linkUsage]
   where syntax1 ← RopeCode1["%g", CodeFill[syntax2]]
   where syntax2 ← RopeCode1["%g", CodeFill[syntax]]
   where linkCalls1 ← RopeCode1["%g", CodeFill[linkCalls2]]
   where linkCalls2 ← RopeCode1["%g", CodeFill[linkCalls]];

for ModuleBody.control: AbstractProduction[Identifier]
 let CollectValueTypes[tree, context] ←
  RecordControlModule[context, ConcatRopes2[RopeFromIdentifierNode[Identifier], "Def"]]
 let CollectFunctionTypes[tree, context] ← FakeCopyContextForConditional[context]
 let CollectProductions[tree, first, context] ←
  <FakeCopyInt[first], FakeCopyContextForConditional[context]>
 let CollectRightSideSymbols[tree, context] ← FakeCopyContextForConditional[context]
 let SyntaxFileCodes[tree, context] ← <BuildEmptyCode[], BuildEmptyCode[]>
 let MakeFileSeq[tree, context] ← BuildEmptyFileSeq[]
 let TestFormControlFile[tree] ← EqualRopes["True", "True"]
 let FormLinkCallCode[tree, context, usage] ← <BuildEmptyCode[], FakeUsageCopy[usage]>
 let FormControlFileList[tree, nProds, syntax, linkCalls, linkUsage] ←
   <ConcatFileSeq[syntaxFiles, ConcatFileSeq[defFiles, implFiles]], use5>
     
  where syntaxFiles ← BuildOneFileSeq[RopeCode1["%g.OneCasaba", IdFill[Identifier]],
     ConcatCode3[
      RopeCode["Begin\N"],
      RopeCode1["%g", CodeFill[syntax]],
      RopeCode["End."]]]
      
  where defFiles ← BuildOneFileSeq[RopeCode1["%gDef.mesa", IdFill[Identifier]],
     ConcatCode5[
      defDirCode,
      RopeCode1["%gDef: CEDAR DEFINITIONS =\N", IdFill[Identifier]],
      RopeCode["BEGIN\N\N"],
      RopeCode["ParseOneStream: PROC[from: IO.STREAM, debugFlags: CARDINAL, debuggingTextTo: IO.STREAM] RETURNS[REF ANY];\N\N"],
      RopeCode["END..\N"]]]
  
  where defDirCode ← ConcatCode2[
      RopeCode["DIRECTORY\N"],
      RopeCode["\TIO USING[STREAM];\N"]]
        
  where implFiles ← BuildOneFileSeq[RopeCode1["%gImpl.mesa", IdFill[Identifier]],
     ConcatCode6[
      ConcatCode6[
       implDirCode,
       RopeCode1["%gImpl: CEDAR PROGRAM", IdFill[Identifier]],
       implImpCode,
       implExpCode,
       RopeCode["= \NBEGIN\N"],
       implOpenCode],
      table,
      driverProced,
      linkProced,
      getTable,
      RopeCode["END..\N"]]]
  
  where <implDirCode, implImpCode, implExpCode, implOpenCode> ←
   BuildImplUseCode[use5]
  where use5 ← RecordDefFileUse[use4, "FS", Use.import]
  where use4 ← RecordDefFileUse[use3, "OneCasabaParser", Use.import]
  where use3 ← RecordDefFileUse[use2, ConcatRopes2[RopeFromIdentifierNode[Identifier], "Def"], Use.export]
  where use2 ← RecordDefFileUse[use1, "ThreeC4Support", Use.import]
  where use1 ← RecordDefFileUse[linkUsage, "IO", Use.import]
  
  where table ← RopeCode["ParseTable: OneCasabaParser.ParserTable ← NIL;\N\N"]

  where driverProced ← ConcatCode4[
     RopeCode["ParseOneStream: PUBLIC PROC[from: IO.STREAM, debugFlags: CARDINAL, debuggingTextTo: IO.STREAM] RETURNS[REF ANY] =\N"],
     RopeCode["BEGIN\N"],
     RopeCode1["RETURN[ThreeC4Support.ParseOneStream[from, ParseTable, SetUpLinks, %g, debugFlags, debuggingTextTo]]\N", IntFill[nProds]],
     RopeCode["END;\N\N"]]
     
  
  where linkProced ← ConcatCode4[
     RopeCode["SetUpLinks: PROC[prodLinkArray: SeeProdLinkArray, tknLinkArray: TokenLinkArray] =\N"],
     RopeCode["BEGIN\N"],
     RopeCode1["%g", CodeFill[linkCalls]],
     RopeCode["END;\N\N"]]
  
  where getTable ← ConcatCode6[
     RopeCode["\N-- obtain parser table\N\N"],
     RopeCode["\TBEGIN\N"],
     RopeCode1["\TtableStream: IO.STREAM ← FS.StreamOpen[\"%g.kipperedParseTables\"];\N",
       IdFill[Identifier]],
     RopeCode["\TParseTable ← OneCasabaParser.BuildParserTableFromKipperedStream[tableStream];\N"],
     RopeCode["\TIO.Close[tableStream];\N"],
     RopeCode["\TEND;\N\N"]];

for ModuleBody.normal: AbstractProduction[Identifier, ModuleItemList]
 let CollectValueTypes[tree, context] ←
   CollectModuleValueTypes[ModuleItemList, defFileName, context]
  where defFileName ← ConcatRopes2[RopeFromIdentifierNode[Identifier], "Def"]
 let CollectFunctionTypes[tree, context] ←
   CollectModuleFunctionTypes[ModuleItemList, defFileName, context]
  where defFileName ← ConcatRopes2[RopeFromIdentifierNode[Identifier], "Def"]
 let CollectProductions[tree, first, context] ← CollectProductions[ModuleItemList, first, context]
 let CollectRightSideSymbols[tree, context] ← CollectRightSideSymbols[ModuleItemList, context]
 let SyntaxFileCodes[tree, context] ← SyntaxFileCodes[ModuleItemList, context]
 let MakeFileSeq[tree, context] ← seq2
  where seq2 ← if TestEmptyCode[defCode] then FakeCopyFileSeqForConditional[seq1]
   else AppendToFileSeq[seq1,
     RopeCode1["%gDef.mesa", IdFill[Identifier]],
     ConcatCode6[
      defDirCode,
      RopeCode1["%gDef: CEDAR DEFINITIONS = \N", IdFill[Identifier]],
      RopeCode["BEGIN\N"],
      defOpenCode,
      RopeCode1["%g", CodeFill[defCode]],
      RopeCode["END..\N"]]]
      
  where seq1 ← if TestEmptyCode[implCode] then BuildEmptyFileSeq[]
    else BuildOneFileSeq[
     RopeCode1["%gImpl.mesa", IdFill[Identifier]],
     ConcatCode9[
      implDirCode,
      RopeCode1["%gImpl: CEDAR PROGRAM", IdFill[Identifier]],
      implImpCode,
      implExpCode,
      RopeCode["= \NBEGIN\N"],
      implOpenCode,
      linkProcedCode,
      implCode,
      RopeCode["END..\N"]]]
      
  where <defDirCode, defOpenCode> ←
   BuildDefUseCode[dUse, defFileName]
  
  
  where dUse ← if noLinks then FakeUsageCopy[dUse1]
      else RecordDefFileUse[dUse1, "ThreeC4Support", Use.ref]
  
  where defCode ← ConcatCode2[
        linkDefCode,
        defCode1]
   
  where <defCode1, dUse1> ← DefFileCode[ModuleItemList, context, BuildEmptyUsage[]]

  where <implDirCode, implImpCode, implExpCode, implOpenCode> ←
   BuildImplUseCode[iUse]
  
            
  where linkProcedCode ← if noLinks then BuildEmptyCode[]
   else ConcatCode4[
     RopeCode1["%gLinkProc: PUBLIC PROC[prodLinkArray: SeeProdLinkArray, tknLinkArray: TokenLinkArray] =\N",
      IdFill[Identifier]],
     RopeCode["BEGIN\N"],
     linkCode,
     RopeCode["END;\N\N"]]
     
  where linkDefCode ← if noLinks then BuildEmptyCode[]
       else RopeCode1["%gLinkProc: PROC[SeeProdLinkArray, TokenLinkArray];\N",
            IdFill[Identifier]]
  
  where iUse ← if noLinks then FakeUsageCopy[iUse2]
   else (RecordDefFileUse[iUse3, defFileName, Use.export]
     where iUse3 ← RecordDefFileUse[iUse2, "ThreeC4Support", Use.ref])
  
  where defFileName ← ConcatRopes2[RopeFromIdentifierNode[Identifier], "Def"]
  
  where noLinks ← TestEmptyCode[linkCode]
            
  where <linkCode, iUse2> ← LinkFileCode[ModuleItemList, context, iUse1] 
  where <implCode, iUse1> ← ImplFileCode[ModuleItemList, context, iUse0]
  where iUse0 ← BuildEmptyUsage[]
 let TestFormControlFile[tree] ← EqualRopes["True", "False"]
 let FormLinkCallCode[tree, context, usage] ← if TestLinkPresent[ModuleItemList]
         then
          (<RopeCode1["%gLinkProc[prodLinkArray, tknLinkArray];\N",
             IdFill[Identifier]],
          RecordDefFileUse[usage, defFileName, Use.import]>
          where defFileName ←
           ConcatRopes2[RopeFromIdentifierNode[Identifier], "Def"])
        else <BuildEmptyCode[], FakeUsageCopy[usage]>
 let FormControlFileList[tree, nProds, syntax, linkCalls, linkUsage] ←
  <BuildEmptyFileSeq[], FakeUsageCopy[linkUsage]>;


for ModuleItemList.One: AbstractProduction[ModuleItem]
 let CollectModuleValueTypes[tree, defFileName, context] ←
   CollectModuleValueTypes[ModuleItem, defFileName, context]
 let CollectModuleFunctionTypes[tree, defFileName, context] ←
   CollectModuleFunctionTypes[ModuleItem, defFileName, context]
 let CollectProductions[tree, first, context] ← CollectProductions[ModuleItem, first, context]
 let CollectRightSideSymbols[tree, context] ← CollectRightSideSymbols[ModuleItem, context]
 let DefFileCode[tree, context, usage] ← DefFileCode[ModuleItem, context, usage]
 let ImplFileCode[tree, context, usage] ← ImplFileCode[ModuleItem, context, usage]
 let LinkFileCode[tree, context, usage] ← LinkFileCode[ModuleItem, context, usage]
 let SyntaxFileCodes[tree, context] ← SyntaxFileCodes[ModuleItem, context]
 let TestLinkPresent[tree] ← TestLinkPresent[ModuleItem];

for ModuleItemList.Many: AbstractProduction[ModuleItemList, ModuleItem]
 let CollectModuleValueTypes[tree, defFileName, context] ←
   CollectModuleValueTypes[ModuleItem, defFileName,
    CollectModuleValueTypes[ModuleItemList, defFileName, context]]
 let CollectModuleFunctionTypes[tree, defFileName, context] ←
   CollectModuleFunctionTypes[ModuleItem, defFileName,
    CollectModuleFunctionTypes[ModuleItemList, defFileName, context]]
 let CollectProductions[tree, first, context] ←
   CollectProductions[ModuleItem, CollectProductions[ModuleItemList, first, context]]
 let CollectRightSideSymbols[tree, context] ←
   CollectRightSideSymbols[ModuleItem,
     CollectRightSideSymbols[ModuleItemList, context]]
 let DefFileCode[tree, context, usage] ← <code, use2>
   where code ← ConcatCode2[code1, code2]
   where <code2, use2> ← DefFileCode[ModuleItem, context, use1]
   where <code1, use1> ← DefFileCode[ModuleItemList, context, usage]
 let ImplFileCode[tree, context, usage] ← <code, use2>
   where code ← ConcatCode2[code1, code2]
   where <code2, use2> ← ImplFileCode[ModuleItem, context, use1]
   where <code1, use1> ← ImplFileCode[ModuleItemList, context, usage]
 let LinkFileCode[tree, context, usage] ← <code, use2>
  where code ← ConcatCode2[code1, code2]
   where <code2, use2> ← LinkFileCode[ModuleItem, context, use1]
   where <code1, use1> ← LinkFileCode[ModuleItemList, context, usage]

 let SyntaxFileCodes[tree, context] ← ConcatCodePairs2[
   SyntaxFileCodes[ModuleItemList, context],
   SyntaxFileCodes[ModuleItem, context]]

 let TestLinkPresent[tree] ←
    Or[TestLinkPresent[ModuleItemList], TestLinkPresent[ModuleItem]]

End.