-- ThreeC4RecFcnImplImpl.ThreeC4
-- Sturgis, May 9, 1986 9:54:38 am PDT

Include[ThreeC4BaseDecl, ThreeC4RecFcnDecl, ThreeC4BasicAbTypes, ThreeC4RecFcnImplAbGram];

ThreeC4RecFcnImplImpl1: Module =
Begin

for AbProductionFcnImpl: AbstractProduction[ModId, ModIdList, RecFcnImplList]
 let ImplFileCode[tree, context, usage] ← <code, use1>
  where <code, use1> ←
   ProdImplFileCode[RecFcnImplList, localContext, abTypeName, abProdName, usage]
  where localContext ← PushProductionContext[context, prodContext]
  where check ← CompareNameLists[oldRightSideList, newRightSideList]
  where newRightSideList ← FormNameList[ModIdList]
  where <oldRightSideList, prodContext> ←
    LookUpAbProduction[context, abProdName]
  where abTypeName ← BuildName[FormFirstId[ModId]]
  where abProdName ← FormName[ModId];

for RecFcnImplList.one: AbstractProduction[Identifier, IdList, RecExpression]
 let ProdImplFileCode[tree, prodContext, abTypeName, abProdName, usage] ← <code, use>
  where code ← ConcatCode4[
       headCode,
       RopeCode["BEGIN\N"],
       bodyCode,
       RopeCode["END;\N\N"]]
    
  where headCode ← RopeCode4["%gProd%g: PUBLIC PROC[%g] RETURNS[%g] =\N",
         NameFill[abProdName],
         IdFill[Identifier],
         CodeFill[BuildArgNameTypeCode[modifiedArgNames, argTypes]],
         CodeFill[BuildArgNameTypeCode[resultNames, fcnResultTypes]]]
         
  where bodyCode ← ConcatCode7[
    RopeCode2["%g: %g← NARROW[ref];\N",
      NameFill[argName1],
      CodeFill[GetTypeCodeName[abType]]],
    RopeCode["BEGIN\N"],
    RopeCode2["ENABLE ThreeC4Support.GetSourceInfo => RESUME[%g.position, %g.length];\N",
        NameFill[argName1], NameFill[argName1]],
    treeDataCode,
    varDeclCode,
    statementCode,
    RopeCode["END\N"]]
  
  where treeDataCode ← if TestEmptyNameList[rightSideNames]
     then BuildEmptyCode[]
     else RopeCode1["treeData: %gProdData ← NARROW[tree.data];\N",
      NameFill[abProdName]]
    
  where check2 ← CompareValTypesWithVarTypes[varTypes, fcnResultTypes]
  
  where check1 ← CheckFcnImpl[
   prodContext,
   FormFcnImplGraph[
    RecExpression,
    prodContext,
    BuildFcnImplGraph[prodContext, Identifier, FormNameList[IdList]]]]
  
  where use ← RecordDefFileUse[use5, "ThreeC4Support", Use.import]
  
  where <varDeclCode, statementCode, varTypes, restNames, nextTempX, use5> ←
    CompForVars[RecExpression, resultNames, nextTempX1, varContext, use4]
    
  where varContext ← RecordVarSeq[prodContext, argNames, modifiedArgTypes]
  
  where modifiedArgTypes ← PrefixToTypeList[abType, argTypesRest]
  where <argType1, argTypesRest> ← PartitionFirstType[argTypes]
  
  where modifiedArgNames ← PrefixToNameList[BuildRopeName["ref"], argNamesRest]
  where <argName1, argNamesRest> ← PartitionFirstName[argNames]
   
  where argNames ← FormNameList[IdList]
  
  where <resultNames, nextTempX1> ←
     InventTemps[CountTypes[fcnResultTypes], IntegerFromRope["0"]]
  
  where use4 ← RecordTypesUse[RecordTypesUse[use3, fcnResultTypes], argTypes]
  
  where use3 ← RecordTypeUse[use2, abType]
  where use2 ← RecordAbstProdUse[use1, abProdName, Use.export, prodContext]
  where use1 ← RecordAbstProdUse[usage, abProdName, Use.ref, prodContext]
  
  where abType ← LookUpType[prodContext, abTypeName]
  where <rightSideNames, abProd> ← LookUpAbProduction[prodContext, abProdName]
     
  where <argTypes, fcnResultTypes> ←
    LookUpRecFcnDef[prodContext, BuildName[Identifier]];

for RecFcnImplList.many: AbstractProduction[RecFcnImplList.a, RecFcnImplList.b]
 let ProdImplFileCode[tree, context, abTypeName, abProdName, usage] ← <code, use1>
  where code ← ConcatCode2[code2, code1]
  where <code1, use1> ←
   ProdImplFileCode[RecFcnImplList.a, context, abTypeName, abProdName, use2]
  where <code2, use2> ←
   ProdImplFileCode[RecFcnImplList.b, context, abTypeName, abProdName, usage];
   

for RecExpression.withWhereList: AbstractProduction[RecExpression, WhereExpSeq]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <varDeclCode, statementCode, argCode, firstArgCode, varTypes, nextTempX, use3>
  
  where statementCode ← ConcatCode6[
      RopeCode["BEGIN\N"],
      expVarDeclCode,
      whereVarDeclCode,
      whereStatementCode,
      expStatementCode,
      RopeCode["END;\N"]]
      
  where varDeclCode ← BuildVarDeclCode[tempNames, varTypes]
  
  where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes] then RopeCode1["%g", NameFill[firstTempName]] else BuildEmptyCode[]
  
  where <firstTempName, junk> ← PartitionFirstName[tempNames]
  
  where use3 ← RecordTypesUse[use2, varTypes]
  
  where check ← CompareNameLists[restNames, BuildEmptyNameList[]]
  
  where <expVarDeclCode, expStatementCode, varTypes, restNames, nextTempX, use2> ←
    CompForVars[RecExpression, tempNames, nextTempX2, nestedContext, use1]
   
  where <whereVarDeclCode, whereStatementCode, nextTempX2, nestedContext, use1> ←
    CompWhere[WhereExpSeq, nextTempX1, context, usage]
  
  where argCode ← BuildNameSeqArgCode[tempNames]
    
  where <tempNames, nextTempX1> ←
     InventTemps[nTemps, firstTempX]
  
  where nTemps ← CountVals[RecExpression, context]  
    
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <declCode, statementCode, varTypes, restNames, nextTempX, use2>

   where statementCode ← ConcatCode6[
      RopeCode["BEGIN\N"],
      expVarDeclCode,
      whereVarDeclCode,
      whereStatementCode,
      expStatementCode,
      RopeCode["END;\N"]]
   
   where declCode ← BuildEmptyCode[] 
    
   where <expVarDeclCode, expStatementCode, varTypes, restNames, nextTempX, use2> ←
    CompForVars[RecExpression, varNames, nextTempX1, nestedContext, use1]
   
   where <whereVarDeclCode, whereStatementCode, nextTempX1, nestedContext, use1> ←
    CompWhere[WhereExpSeq, firstTempX, context, usage]
    
 let CountVals[tree, context] ← CountVals[RecExpression, context];

for RecExpression.cond:
   AbstractProduction[
    RecExpression.ifClause,
    RecExpression.thenClause,
    RecExpression.elseClause]
    
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <varDeclCode, statementCode, argCode, firstArgCode, at2, nextTempX, use>
   
   where varDeclCode ← ConcatCode3[
     BuildVarDeclCode[bt, bTypes],
     vdc3,
     vdc2]
     
   where use ← RecordTypesUse[use3, bTypes]
     
   where bTypes ←
    BuildOneTypeList[LookUpType[context, BuildRopeName["BOOLEAN"]]]
   
   where statementCode ← ConcatCode6[
     sc1,
     RopeCode2["IF %g ← %g THEN { NULL;\N", NameFill[TheOneName[bt]], CodeFill[ac1]],
     sc2,
     RopeCode["} ELSE {NULL;\N"],
     sc3,
     RopeCode["};\N"]]
   
   where argCode ← RopeCode3["(IF %g THEN %g ELSE %g)",
      NameFill[TheOneName[bt]],
      CodeFill[ac2],
      CodeFill[ac3]]
   
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes] then
    RopeCode3["(IF %g THEN %g ELSE %g)",
      NameFill[TheOneName[bt]],
      CodeFill[fac2],
      CodeFill[fac3]]
    else BuildEmptyCode[]
   
   where <bt, nextTempX> ← InventTemps[IntegerFromRope["1"], ntx3]
   
   where check2 ← CheckForEqualTypeLists[at2, at3]
   
   where <vdc3, sc3, ac3, fac3, at3, ntx3, use3> ←
    CompForArgs[RecExpression.elseClause, treeCallFlag, ntx2, context, use2]
   where <vdc2, sc2, ac2, fac2, at2, ntx2, use2> ←
    CompForArgs[RecExpression.thenClause, treeCallFlag, ntx1, context, use1]
   
   where check1 ← CheckForOneBoolean[agt1]
   where <vdc1, sc1, ac1, junk, agt1, ntx1, use1> ←
    CompForArgs[RecExpression.ifClause, TreeCallFlag.no, firstTempX, context, usage]
    
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, varTypes, restNames, nextTempX, use3>
   
   where varDeclCode ← ConcatCode3[vdc1, vdc2, vdc3]
   where statementCode ← ConcatCode2[
    sc1,
    RopeCode3["IF %g THEN {%g} ELSE {%g};\N",
      CodeFill[ac1], CodeFill[sc2], CodeFill[sc3]]]
   where varTypes ← vt2
   where restNames ← rn2
   
   where check3 ← CheckForEqualTypeLists[vt2, vt3]
   where check2 ← CompareNameLists[rn2, rn3]
   where <vdc3, sc3, vt3, rn3, nextTempX, use3> ←
    CompForVars[RecExpression.elseClause, varNames, ntx2, context, use2] 
    
   where <vdc2, sc2, vt2, rn2, ntx2, use2> ←
    CompForVars[RecExpression.thenClause, varNames, ntx1, context, use1] 
    
   where check1 ← CheckForOneBoolean[agt1]
   where <vdc1, sc1, ac1, junk, agt1, ntx1, use1> ←
    CompForArgs[RecExpression.ifClause, TreeCallFlag.no, firstTempX, context, usage]
    
 let CountVals[tree, context] ← CountVals[RecExpression.thenClause, context];
    
for RecExpression.call: AbstractProduction[Identifier, RecExpSeq]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <varDeclCode, statementCode, argCode, firstArgCode, funResultTypes, nextTempX, use> 
      
   where nextTempX ← if simple then ntx1 else ntx2
   
   where firstArgCode ← if simple then BuildEmptyCode[] else
          RopeCode1["%g", NameFill[firstLocalVar]]
   
   where argCode ← if simple then fCall else BuildNameSeqArgCode[localVars]
   
   where statementCode ← if simple then FakeCopyCodeForConditional[sc1]
          else
           (if oneResult then ConcatCode2[
            FakeCopyCodeForConditional[sc1],
            RopeCode2["%g ← %g;\N",
             CodeFill[BuildNameSeqArgCode[localVars]],
             CodeFill[fCall]]]
           else ConcatCode2[
            FakeCopyCodeForConditional[sc1],
            RopeCode2["[%g] ← %g;\N",
             CodeFill[BuildNameSeqArgCode[localVars]],
             CodeFill[fCall]]])
             
   where varDeclCode ← if simple then FakeCopyCodeForConditional[vdc1]
          else ConcatCode2[
            BuildVarDeclCode[localVars, funResultTypes],
            vdc1]
   
   where use ← if EqualFunCase[fCase, FunctionCase.recursive]
        then FakeUsageCopy[use2]
        else RecordFcnUse[use2, funName, Use.import, context]
   
   where use2 ← if simple then FakeUsageCopy[use1]
        else RecordTypesUse[use1, funResultTypes]
   
   
   where localVars ← if simple then BuildEmptyNameList[] else inventedTemps
   
   where <firstLocalVar, otherLocalVars> ← PartitionFirstName[inventedTemps]
   
   where <inventedTemps, ntx2> ← InventTemps[CountTypes[funResultTypes], ntx1]
   
   where simple ← AndLogical[EqualTreeCallFlags[treeCallFlag, TreeCallFlag.no], oneResult]
    
   where oneResult ← EqualInteger[CountTypes[funResultTypes], IntegerFromRope["1"]] 
    
   where fCall ← if EqualFunCase[fCase, FunctionCase.base]
    then RopeCode2["%g[%g]", IdFill[Identifier], CodeFill[ac]]
    else RopeCode3["%g.procs.%g[%g]", CodeFill[fac], IdFill[Identifier], CodeFill[ac]]
   
   where check1 ← CompareValTypesWithVarTypes[at, funArgTypes]  
    
   where <vdc1, sc1, ac, fac, at, ntx1, use1> ←
    CompForArgs[RecExpSeq, subTreeCallFlag, firstTempX, context, use0]
   
   where use0 ← if EqualFunCase[fCase, FunctionCase.recursive]
     then FakeUsageCopy[usage]
     else RecordFcnUse[usage, funName, Use.import, context]
   
   where subTreeCallFlag ← if EqualFunCase[fCase, FunctionCase.base]
           then TreeCallFlag.no else TreeCallFlag.yes
   
   where <fCase, funArgTypes, funResultTypes> ←
    LookUpFunction[context, funName]
   
   where funName ← BuildName[Identifier]
   
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, funResultTypes, restNames, nextTempX, use>
   
   where statementCode ← ConcatCode2[
    sc,
    RopeCode2["%g ← %g;\N",
     CodeFill[assignResultCode],
     CodeFill[fCall]]]
   
   where assignResultCode ← if oneResult then BuildNameSeqArgCode[argNames]
           else RopeCode1["[%g]",
             CodeFill[BuildNameSeqArgCode[argNames]]]
   
   where oneResult ← EqualInteger[CountTypes[funResultTypes], IntegerFromRope["1"]]
    
   where fCall ← if EqualFunCase[fCase, FunctionCase.base]
    then RopeCode2["%g[%g]", IdFill[Identifier], CodeFill[ac]]
    else RopeCode3["%g.procs.%g[%g]", CodeFill[fac], IdFill[Identifier], CodeFill[ac]]
   
   where <argNames, restNames> ←
     PartitionNames[CountTypes[funResultTypes], varNames]
   
   where check1 ← CompareValTypesWithVarTypes[at, funArgTypes]
   
   where <varDeclCode, sc, ac, fac, at, nextTempX, use> ←
    CompForArgs[RecExpSeq, subTreeCallFlag, firstTempX, context, use0]
   
   where use0 ← if EqualFunCase[fCase, FunctionCase.recursive]
     then FakeUsageCopy[usage]
     else RecordFcnUse[usage, funName, Use.import, context]
   
   where subTreeCallFlag ← if EqualFunCase[fCase, FunctionCase.base]
           then TreeCallFlag.no else TreeCallFlag.yes
   
   where <fCase, funArgTypes, funResultTypes> ← LookUpFunction[context, funName]
   
   where funName ← BuildName[Identifier]
   
 let CountVals[tree, context] ← CountTypes[resultTypes]
  where <case, argTypes, resultTypes> ← LookUpFunction[context, BuildName[Identifier]];

for RecExpression.seq: AbstractProduction[RecExpSeq]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <varDeclCode, statementCode, argCode, firstArgCode, argTypes, nextTempX, use>
   where <varDeclCode, statementCode, argCode, firstArgCode, argTypes, nextTempX, use> ←
    CompForArgs[RecExpSeq, treeCallFlag, firstTempX, context, usage]
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, varTypes, restNames, nextTempX, use>
   where <varDeclCode, statementCode, varTypes, restNames, nextTempX, use> ←
    CompForVars[RecExpSeq, varNames, firstTempX, context, usage]
 let CountVals[tree, context] ← CountVals[RecExpSeq, context];

for RecExpression.id: AbstractProduction[Identifier]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <BuildEmptyCode[], BuildEmptyCode[], argCode, firstArgCode, idTypes, FakeCopyInteger[firstTempX], FakeUsageCopy[usage]>
   where argCode ← code
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
     then RopeCode1["%g", CodeFill[code]]
     else BuildEmptyCode[]
   where idTypes ← BuildOneTypeList[type]  
   where <type, code> ← LookUpSimpleValue[context, Identifier]
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, valTypes, restNames, nextTempX, use>
     
   where statementCode ← ConcatCode4[
    RopeCode1["%g ← ", NameFill[firstName]],
    valCode,
    RopeCode[";\N"],
    valStatementCode]
   
   where <firstName, restNames> ← PartitionFirstName[varNames]
   where <varDeclCode, valStatementCode, valCode, junk, valTypes, nextTempX, use>
       ← CompForArgs[tree, TreeCallFlag.no, firstTempX, context, usage]
 let CountVals[tree, context] ← IntegerFromRope["1"];

for RecExpression.modId: AbstractProduction[Identifier.a, Identifier.b]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <BuildEmptyCode[], BuildEmptyCode[], argCode, firstArgCode, idTypes, FakeCopyInteger[firstTempX], FakeUsageCopy[usage]>
   where argCode ← code
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
     then RopeCode1["%g", CodeFill[code]]
     else BuildEmptyCode[]
   where idTypes ← BuildOneTypeList[type]  
   where <type, code> ←
    LookUpValue2[context, Identifier.a, Identifier.b]
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, valTypes, restNames, nextTempX, use>
     
   where statementCode ← ConcatCode4[
    RopeCode1["%g ← ", NameFill[firstName]],
    valCode,
    RopeCode[";\N"],
    valStatementCode]
   
   where <firstName, restNames> ← PartitionFirstName[varNames]
   where <varDeclCode, valStatementCode, valCode, junk, valTypes, nextTempX, use>
       ← CompForArgs[tree, TreeCallFlag.no, firstTempX, context, usage]
 let CountVals[tree, context] ← IntegerFromRope["1"]

End;

ThreeC4RecFcnImplImpl2: Module =
Begin

for RecExpression.rope: AbstractProduction[Rope]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <BuildEmptyCode[], BuildEmptyCode[], argCode, firstArgCode, types, FakeCopyInteger[firstTempX], FakeUsageCopy[usage]>
   where argCode ← RopeCode1["\"%g\"", CodeFill[RopeCode[RopeFromRopeNode[Rope]]]]
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
     then BuildErrorCode["rope is not a tree"]
     else BuildEmptyCode[]
   where types ← BuildOneTypeList[LookUpType[context, BuildRopeName["ROPE"]]]
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, valTypes, restNames, nextTempX, use>
   
   where statementCode ← ConcatCode4[
    RopeCode1["%g ← ", NameFill[firstName]],
    valCode,
    RopeCode[";\N"],
    valStatementCode]
   
   where <firstName, restNames> ← PartitionFirstName[varNames]
   where <varDeclCode, valStatementCode, valCode, junk, valTypes, nextTempX, use>
       ← CompForArgs[tree, TreeCallFlag.no, firstTempX, context, usage]
 let CountVals[tree, context] ← IntegerFromRope["1"];

for RecExpression.numb: AbstractProduction[NonNegInteger]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <BuildEmptyCode[], BuildEmptyCode[], argCode, firstArgCode, types, FakeCopyInteger[firstTempX], FakeUsageCopy[usage]>
   where argCode ← RopeCode[RopeFromNonNegIntegerNode[NonNegInteger]]
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
     then BuildErrorCode["number is not a tree"]
     else BuildEmptyCode[]
   where types ← BuildOneTypeList[LookUpType[context, BuildRopeName["INT"]]]

 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, valTypes, restNames, nextTempX, use>
   
   where statementCode ← ConcatCode4[
    RopeCode1["%g ← ", NameFill[firstName]],
    valCode,
    RopeCode[";\N"],
    valStatementCode]
   
   where <firstName, restNames> ← PartitionFirstName[varNames]
   where <varDeclCode, valStatementCode, valCode, junk, valTypes, nextTempX, use>
       ← CompForArgs[tree, TreeCallFlag.no, firstTempX, context, usage]

 let CountVals[tree, context] ← IntegerFromRope["1"];

for RecExpression.sourcePosition: AbstractProduction[ModId]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <BuildEmptyCode[], BuildEmptyCode[], argCode, firstArgCode, types, FakeCopyInteger[firstTempX], FakeUsageCopy[usage]>
   where argCode ← RopeCode1["%g.position", NameFill[FormName[ModId]]]
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
     then BuildErrorCode["sourcePosition is not a tree"]
     else BuildEmptyCode[]
   where types ← BuildOneTypeList[LookUpType[context, BuildRopeName["INT"]]]
   where check ← CompareValTypeWithVarType[
    vType,
    LookUpType[context, BuildRopeName["Tree"]]]
   where <vType, unused> ← FormValueInfo[ModId, context]
    
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, valTypes, restNames, nextTempX, use>
   
   where statementCode ← ConcatCode4[
    RopeCode1["%g ← ", NameFill[firstName]],
    valCode,
    RopeCode[";\N"],
    valStatementCode]
   
   where <firstName, restNames> ← PartitionFirstName[varNames]
   where <varDeclCode, valStatementCode, valCode, junk, valTypes, nextTempX, use>
       ← CompForArgs[tree, TreeCallFlag.no, firstTempX, context, usage]
       
 let CountVals[tree, context] ← IntegerFromRope["1"];

for RecExpression.sourceLength: AbstractProduction[ModId]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
    <BuildEmptyCode[], BuildEmptyCode[], argCode, firstArgCode, types, FakeCopyInteger[firstTempX], FakeUsageCopy[usage]>
   where argCode ← RopeCode1["%g.length", NameFill[FormName[ModId]]]
   where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
     then BuildErrorCode["sourceLength is not a tree"]
     else BuildEmptyCode[]
   where types ← BuildOneTypeList[LookUpType[context, BuildRopeName["INT"]]]
   where check ← CompareValTypeWithVarType[
    vType,
    LookUpType[context, BuildRopeName["Tree"]]]
   where <vType, unused> ← FormValueInfo[ModId, context]
   
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, valTypes, restNames, nextTempX, use>
   
   where statementCode ← ConcatCode4[
    RopeCode1["%g ← ", NameFill[firstName]],
    valCode,
    RopeCode[";\N"],
    valStatementCode]
   
   where <firstName, restNames> ← PartitionFirstName[varNames]
   where <varDeclCode, valStatementCode, valCode, junk, valTypes, nextTempX, use>
       ← CompForArgs[tree, TreeCallFlag.no, firstTempX, context, usage]
       
 let CountVals[tree, context] ← IntegerFromRope["1"];

for RecExpSeq.empty: AbstractProduction[]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ← <
   BuildEmptyCode[],
   BuildEmptyCode[],
   BuildEmptyCode[],
   if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
    then BuildErrorCode["expecting at least a tree argument"]
    else BuildEmptyCode[],
   BuildEmptyTypeList[],
   FakeCopyInteger[firstTempX],
   FakeUsageCopy[usage]>
   
 let CompForVars[tree, varNames, firstTempX, context, usage] ← <
   BuildEmptyCode[],
   BuildEmptyCode[],
   BuildEmptyTypeList[],
   varNames,
   FakeCopyInteger[firstTempX],
   FakeUsageCopy[usage]>
   
 let CountVals[tree, context] ← IntegerFromRope["0"];
    

for RecExpSeq.one: AbstractProduction[RecExpression]
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
   CompForArgs[RecExpression, treeCallFlag, firstTempX, context, usage]
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
   CompForVars[RecExpression, varNames, firstTempX, context, usage]
 let CountVals[tree, context] ← CountVals[RecExpression, context];

for RecExpSeq.many: AbstractProduction[RecExpSeq.a, RecExpSeq.b]
  -- concrete grammar guarantees both non empty
 let CompForArgs[tree, treeCallFlag, firstTempX, context, usage] ←
   <varDeclCode, statementCode, argCode, firstArgCode, argTypes, bNextTempX, use2>
  where varDeclCode ← ConcatCode2[bDeclCode, aDeclCode]
   where statementCode ← ConcatCode2[bStatementCode, aStatementCode]
   where argCode ← ConcatCode3[aArgCode, RopeCode[", "], bArgCode]
   where argTypes ← ConcatTypeLists[aVarTypes, bVarTypes]
    
   where <bDeclCode, bStatementCode, bArgCode, unused, bVarTypes, bNextTempX, use2> ←
    CompForArgs[RecExpSeq.b, TreeCallFlag.no, aNextTempX, context, use1]
   
   where <aDeclCode, aStatementCode, aArgCode, firstArgCode, aVarTypes, aNextTempX, use1> ←
    CompForArgs[RecExpSeq.a, treeCallFlag, firstTempX, context, usage]
    
 let CompForVars[tree, varNames, firstTempX, context, usage] ←
    <varDeclCode, statementCode, varTypes, bRestNames, bNextTempX, use2>
   
   where varDeclCode ← ConcatCode2[bDeclCode, aDeclCode]
   where statementCode ← ConcatCode2[bStatementCode, aStatementCode]
   where varTypes ← ConcatTypeLists[aVarTypes, bVarTypes]
   
   where <bDeclCode, bStatementCode, bVarTypes, bRestNames, bNextTempX, use2> ←
    CompForVars[RecExpSeq.b, aRestNames, aNextTempX, context, use1] 
    
   where <aDeclCode, aStatementCode, aVarTypes, aRestNames, aNextTempX, use1> ←
    CompForVars[RecExpSeq.a, varNames, firstTempX, context, usage]
    
 let CountVals[tree, context] ← Add[CountVals[RecExpSeq.b, context], CountVals[RecExpSeq.a, context]];


for WhereExpSeq.one: AbstractProduction[IdList, RecExpression]
 let CompWhere[tree, firstTempX, context, usage] ←
     <varDeclCode, statementCode, nextTempX, nestedContext, use>
   
   where nestedContext ←
     RecordVarSeq[context, FormNameList[IdList], expTypes]
   
   where varDeclCode ← ConcatCode2[
      FormVarDeclCode[IdList, expTypes],
      expVarDeclCode]
   
   where use ← RecordTypesUse[use1, expTypes]
   
   where <expVarDeclCode, statementCode, expTypes, expRestNames, nextTempX, use1> ←
      CompForVars[RecExpression, FormNameList[IdList], firstTempX, context, usage];

for WhereExpSeq.many: AbstractProduction[WhereExpSeq.a, WhereExpSeq.b]
 let CompWhere[tree, firstTempX, context, usage] ←
    <varDeclCode, statementCode, nextTempX, nestedContext, use2>
  where varDeclCode ← ConcatCode2[aVarDeclCode,bVarDeclCode]   
  where statementCode ← ConcatCode2[bStatementCode, aStatementCode]
  where <aVarDeclCode, aStatementCode, nextTempX, nestedContext, use2> ←
    CompWhere[WhereExpSeq.a, nextTempX1, nestedContext1, use1]
   where <bVarDeclCode, bStatementCode, nextTempX1, nestedContext1, use1> ←
    CompWhere[WhereExpSeq.b, firstTempX, context, usage]


End;

ThreeC4RecFcnImplImpl3: Module =
Begin
-- this module contains the flow analysis code for a single implementation

for RecExpression.withWhereList: AbstractProduction[RecExpression, WhereExpSeq]
 let FormFcnImplGraph[tree, lookup, graph] ← <newGraph, slots, cgNode>
  where newGraph ← CloseWithWhereList[graph4]
  where <graph4, cgNode> ← RecordSequential[graph3, whereNode, expNode]
  where <graph3, slots, expNode> ← FormFcnImplGraph[RecExpression, lookup, graph2]
  where <graph2, whereNode> ← FormFcnImplWhereGraph[WhereExpSeq, lookup, graph1]
  where graph1 ← OpenWithWhereList[graph];

for RecExpression.cond:
   AbstractProduction[
    RecExpression.ifClause,
    RecExpression.thenClause,
    RecExpression.elseClause]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordCondition[graph3,
         slotsIf, cgNodeIf,
         slotsThen, cgNodeThen,
         slotsElse, cgNodeElse]
  where <graph3, slotsIf, cgNodeIf> ←
      FormFcnImplGraph[RecExpression.ifClause, lookup, graph2]
  where <graph2, slotsThen, cgNodeThen> ←
      FormFcnImplGraph[RecExpression.thenClause, lookup, graph1]
  where <graph1, slotsElse, cgNodeElse> ←
      FormFcnImplGraph[RecExpression.elseClause, lookup, graph];

for RecExpression.call: AbstractProduction[Identifier, RecExpSeq]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordCall[graph1, lookup, Identifier, slots, cgn]
  where <graph1, slots, cgn> ← FormFcnImplGraph[RecExpSeq, lookup, graph];

for RecExpression.seq: AbstractProduction[RecExpSeq]
 let FormFcnImplGraph[tree, lookup, graph] ← FormFcnImplGraph[RecExpSeq, lookup, graph];

for RecExpression.id: AbstractProduction[Identifier]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordSimpleVarUse[graph, lookup, Identifier];

for RecExpression.modId: AbstractProduction[Identifier.a, Identifier.b]
 let FormFcnImplGraph[tree, lookup, graph] ←
   RecordModIdUse[graph, lookup, Identifier.a, Identifier.b];

for RecExpression.rope: AbstractProduction[Rope]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordLiteralUse[graph, SourcePosition[tree]];

for RecExpression.numb: AbstractProduction[NonNegInteger]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordLiteralUse[graph, SourcePosition[tree]];

for RecExpression.sourcePosition: AbstractProduction[ModId]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordLiteralUse[graph, SourcePosition[tree]];

for RecExpression.sourceLength: AbstractProduction[ModId]
 let FormFcnImplGraph[tree, lookup, graph] ← RecordLiteralUse[graph, SourcePosition[tree]];

for RecExpSeq.empty: AbstractProduction[]
 let FormFcnImplGraph[tree, lookup, graph] ←
   <FakeCopyFcnImplGraph[graph], BuildEmptySlotList[], BuildEmptyCallGraphNode[]>;

for RecExpSeq.one: AbstractProduction[RecExpression]
 let FormFcnImplGraph[tree, lookup, graph] ←
   FormFcnImplGraph[RecExpression, lookup, graph];

for RecExpSeq.many: AbstractProduction[RecExpSeq.a, RecExpSeq.b]
 let FormFcnImplGraph[tree, lookup, graph] ← <newGraph, slots, cgn>
  where <newGraph, cgn> ← RecordParallel[graph2, cgna, cgnb]
  where slots ← ConcatSlotList[slotsa, slotsb]
  where <graph2, slotsb, cgnb> ← FormFcnImplGraph[RecExpSeq.b, lookup, graph1]
  where <graph1, slotsa, cgna> ← FormFcnImplGraph[RecExpSeq.a, lookup, graph];

for WhereExpSeq.one: AbstractProduction[IdList, RecExpression]
 let FormFcnImplWhereGraph[tree, lookup, graph] ←
   RecordAssignment[graph1, FormNameList[IdList], slots, cgn1]
  where <graph1, slots, cgn1> ← FormFcnImplGraph[RecExpression, lookup, graph];

for WhereExpSeq.many: AbstractProduction[WhereExpSeq.a, WhereExpSeq.b]
 let FormFcnImplWhereGraph[tree, lookup, graph] ← RecordSequential[graph2, cgnb, cgna]
  where <graph2, cgna> ← FormFcnImplWhereGraph[WhereExpSeq.a, lookup, graph1]
  where <graph1, cgnb> ← FormFcnImplWhereGraph[WhereExpSeq.b, lookup, graph]

End.