-- ThreeC4RecFcnImplImpl.ThreeC4
-- Sturgis, May 9, 1986 9:54:38 am PDT
-- Shoup, June 23, 1986 9:39:03 am PDT
-- Bhargava, July 1, 1986 10:23:54 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 ← BPrintError[CompareNameLists[oldRightSideList, newRightSideList], "name lists do not match"]
		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 ← (if AreErrors[] then False[] else
			CheckFcnImpl[
				prodContext,
				FormFcnImplGraph[
					RecExpression,
					prodContext,
					BuildFcnImplGraph[prodContext, Identifier, FormNameList[IdList]]]])
				
		where check1 ← CompareValTypesWithVarTypes[varTypes, fcnResultTypes]
		
		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]]
				
		where check0 ← MarkErrors[];

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 ← BAbort[BPrintError[CompareNameLists[restNames, BuildEmptyNameList[]], "name lists do not match"]]
		
		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 ← BAbort[BPrintError[CompareNameLists[rn2, rn3], "name lists do not match"]]
			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], use>
			where argCode ← code
			where firstArgCode ← if EqualTreeCallFlags[treeCallFlag, TreeCallFlag.yes]
					then RopeCode1["%g", CodeFill[code]]
					else BuildEmptyCode[]
			where idTypes ← BuildOneTypeList[type]	
			where use ← RecordTypeUse[usage, 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.