-- ThreeC4CProdImpl.ThreeC4
-- Sturgis, May 10, 1986 3:02:00 pm PDT

Include[ThreeC4BaseDecl, ThreeC4RecFcnDecl, ThreeC4BasicAbTypes, ThreeC4CProdAbGram];

ThreeC4CProdImpl: Module =
Begin

for ConcreteProduction: AbstractProduction[ModId, ConcreteRightSideList, BuildExp]
	let CollectProductions[tree, first, context] ←
			<Add1ToInt[first], RecordProduction[context, FormName[ModId], first]>
	let ImplFileCode[tree, context, usage] ← <code, use>
		where code ← ConcatCode6[
			headCode,
			nodeVarDeclCode,
			nodeVarAssignCode,
			bodyCode,
			returnCode,
			endCode]
		
		where headCode ← ConcatCode4[	
			RopeCode1["See%g: PROC[nodes: LIST OF REF ANY, position: INT, length: INT]\N", NameFill[prodName]],
			RopeCode["\TRETURNS[LIST OF REF ANY] =\N"],
			RopeCode["BEGIN\N"],
			RopeCode["stack: LIST OF REF ANY ← nodes;\N"]]
		
		where nodeVarDeclCode ← BuildVarDeclCode[subNodeNames, subNodeTypes]
		
		where nodeVarAssignCode  ← FormNodeVarAssignCode[ConcreteRightSideList]
		
		
		where bodyCode ← RopeCode1["stack ← CONS[%g, stack];\N", CodeFill[expCode]]
		where returnCode ← RopeCode["RETURN[stack]\N"]
		where endCode ← RopeCode["END;\N\N"]
		
		where use ← RecordTypesUse[use1, subNodeTypes]
		
		where check ← CompareValTypeWithVarType[expType, prodBuildType]
		where <expCode, expType, use1> ← FormBuildExpCode[BuildExp, False, context1, usage]
		where context1 ← FormRightSideContext[ConcreteRightSideList, context]
		
		where subNodeNames ← FormNameList[ConcreteRightSideList] 
		where subNodeTypes ← FormTypeList[ConcreteRightSideList, context]
		where prodName ← FormName[ModId]
		where prodBuildType ← LookUpGrammarSymbol[context, BuildName[FormFirstId[ModId]]]
		where False ← EqualRopes["False", "True"]
	
	let LinkFileCode[tree, context, usage] ← <code, FakeUsageCopy[usage]> 
		where code ← RopeCode2["prodLinkArray[%g] ← See%g;\N",
							IntFill[index],
							NameFill[prodName]]
		where index ← LookUpProduction[context, prodName]
		where prodName ← FormName[ModId]
	
	let SyntaxFileCodes[tree, context] ← <BuildEmptyCode[], prod>
		where prod ←
			RopeCode2["%g ← %g;\N",
				DotedNameFill[FormName[ModId]],
				CodeFill[SyntaxRightSideFileCode[ConcreteRightSideList]]]
	let TestLinkPresent[tree] ← EqualRopes["True", "True"];


for ConcreteRightSideList.empty: AbstractProduction[]
	let FormRightSideContext[tree, context] ← context
	let FormNameList[tree] ← BuildEmptyNameList[]
	let FormTypeList[tree, context] ← BuildEmptyTypeList[]
	let FormNodeVarAssignCode[tree] ← BuildEmptyCode[]
	let SyntaxRightSideFileCode[tree] ← BuildEmptyCode[];
	
for ConcreteRightSideList.one: AbstractProduction[ConcreteRightSideItem]
	let FormRightSideContext[tree, context] ←
			FormRightSideContext[ConcreteRightSideItem, context]
	let FormNameList[tree] ← FormNameList[ConcreteRightSideItem]
	let FormTypeList[tree, context] ← FormTypeList[ConcreteRightSideItem, context]
	let FormNodeVarAssignCode[tree] ← FormNodeVarAssignCode[ConcreteRightSideItem]
	let SyntaxRightSideFileCode[tree] ← SyntaxRightSideFileCode[ConcreteRightSideItem];
	
for ConcreteRightSideList.many: AbstractProduction[ConcreteRightSideList, ConcreteRightSideItem]
	let FormRightSideContext[tree, context] ←
			FormRightSideContext[ConcreteRightSideItem,
				FormRightSideContext[ConcreteRightSideList, context]]
	let FormNameList[tree] ←
		ConcatNameLists[
			FormNameList[ConcreteRightSideList],
			FormNameList[ConcreteRightSideItem]]
	let FormTypeList[tree, context] ←
		ConcatTypeLists[
			FormTypeList[ConcreteRightSideList, context],
			FormTypeList[ConcreteRightSideItem, context]]
	let FormNodeVarAssignCode[tree] ← 
		ConcatCode2[
			FormNodeVarAssignCode[ConcreteRightSideItem],
			FormNodeVarAssignCode[ConcreteRightSideList]]
	let SyntaxRightSideFileCode[tree] ← 
		ConcatCode2[
			SyntaxRightSideFileCode[ConcreteRightSideList],
			SyntaxRightSideFileCode[ConcreteRightSideItem]];
			

for ConcreteRightSideItem.rope: AbstractProduction[Rope]
	let FormRightSideContext[tree, context] ← context
		where check ← CheckLegalRopeToken[context, Rope]
	let FormNameList[tree] ← BuildEmptyNameList[]
	let FormTypeList[tree, context] ← BuildEmptyTypeList[]
	let FormNodeVarAssignCode[tree] ← BuildEmptyCode[]
	let SyntaxRightSideFileCode[tree] ← ConcatCode3[
				RopeCode[" \""],
				RopeCode[itemRope],
				RopeCode["\" "]]
			where itemRope ← RopeFromRopeNode[Rope];
		
for ConcreteRightSideItem.modId: AbstractProduction[ModId]
	let FormRightSideContext[tree, context] ← PushLocalRSS[context, FormName[ModId], type]
		where type ← LookUpGrammarSymbol[context, BuildName[FormFirstId[ModId]]]
	let FormNameList[tree] ← BuildOneNameList[FormName[ModId]]
	let FormTypeList[tree, context] ← BuildOneTypeList[type]
		where type ← LookUpGrammarSymbol[context, name]
		where name ← BuildName[FormFirstId[ModId]]
	let FormNodeVarAssignCode[tree] ← ConcatCode2[
			RopeCode1["%g ← NARROW[stack.first];\N", NameFill[FormName[ModId]]],
			RopeCode["stack ← stack.rest;\N"]]
	let SyntaxRightSideFileCode[tree] ← RopeCode1["%g ", IdFill[FormFirstId[ModId]]];

for BuildExp.modId: AbstractProduction[ModId]
	let FormBuildExpCode[tree, nested, context, usage] ← FormExpCode[ModId, context, usage]
	let FormBuildPositionCode[tree, nested, context, usage] ← <code, use>
		where code ← RopeCode1["%g.position", CodeFill[nodeCode]]
		where <nodeCode, unused, use> ← FormExpCode[ModId, context, usage]
	let FormBuildLengthCode[tree, nested, context, usage] ← <code, use>
		where code ← RopeCode1["%g.length", CodeFill[nodeCode]]
		where <nodeCode, unused, use> ← FormExpCode[ModId, context, usage];
	

for BuildExp.buildNode: AbstractProduction[ModId, IntervalExp, BuildExpList]
	let FormBuildExpCode[tree, nested, context, usage] ← <code, type, use>
		where code ← RopeCode4["Build%gProdNode[%g%g%g]", NameFill[name], CodeFill[intervalCode], CodeFill[spacerCode], CodeFill[expCode]]
		where use ← RecordAbstProdUse[use1, name, Use.import, context]
		where check ← CompareValTypesWithVarTypes[expListTypes, argTypes]
		where <type, argTypes> ← LookUpAbstractProduction[context, name]
		where name ← FormName[ModId]
		where spacerCode ← if TestEmptyCode[expCode] then BuildEmptyCode[]
								else RopeCode[", "]
		where <expCode, expListTypes, use1> ← FormBuildExpListCode[BuildExpList, context, use0]
		where intervalCode ←
					RopeCode2["%g, %g", CodeFill[positionCode], CodeFill[lengthCode]]
		where <positionCode, use0> ←
			FormIntervalBuildPositionCode[IntervalExp, BuildExpList, nested, context, use00]
		where <lengthCode, use00> ←
			FormIntervalBuildLengthCode[IntervalExp, BuildExpList, nested, context, usage]
	let FormBuildPositionCode[tree, nested, context, usage] ←
			FormIntervalBuildPositionCode[IntervalExp, BuildExpList, nested, context, usage]
	let FormBuildLengthCode[tree, nested, context, usage] ←
			FormIntervalBuildLengthCode[IntervalExp, BuildExpList, nested, context, usage];
	


for BuildExpList.empty: AbstractProduction[]
	let FormBuildExpListCode[tree, context, usage] ←
			<BuildEmptyCode[], BuildEmptyTypeList[], FakeUsageCopy[usage]>
	let FormBuildPositionCode[tree, nested, context, usage] ←
			if EmptyRSContext[context]
				then <RopeCode["position"], FakeUsageCopy[usage]>
				else <BuildErrorCode["expecting a build exp list"], FakeUsageCopy[usage]>
	let FormBuildLengthCode[tree, nested, context, usage] ←
			if EmptyRSContext[context]
				then <RopeCode["length"], FakeUsageCopy[usage]>
				else <BuildErrorCode["expecting a build exp list"], FakeUsageCopy[usage]>;

for BuildExpList.one: AbstractProduction[BuildExp]
	let FormBuildExpListCode[tree, context, usage] ← <code, BuildOneTypeList[type], use>
		where <code, type, use> ← FormBuildExpCode[BuildExp, True, context, usage]
		where True ← EqualRopes["True", "True"]
	let FormBuildPositionCode[tree, nested, context, usage] ←
			FormBuildPositionCode[BuildExp, nested, context, usage]
	let FormBuildLengthCode[tree, nested, context, usage] ←
			FormBuildLengthCode[BuildExp, nested, context, usage];
	
for BuildExpList.many: AbstractProduction[BuildExpList, BuildExp]
	let FormBuildExpListCode[tree, context, usage] ← <code, types, use>
		where code ← ConcatCode3[
							listCode,
							RopeCode[", "],
							expCode]
		where types ← AppendToTypeList[types1, type]
		where <expCode, type, use> ← FormBuildExpCode[BuildExp, True, context, use1]
		where <listCode, types1, use1> ← FormBuildExpListCode[BuildExpList, context, usage]
		where True ← EqualRopes["True", "True"]
	let FormBuildPositionCode[tree, nested, context, usage] ←
			FormBuildPositionCode[BuildExpList, nested, context, usage]
	let FormBuildLengthCode[tree, nested, context, usage] ← <code, use>
			where code ← RopeCode3["%g + %g - %g",
									CodeFill[expPosCode],
									CodeFill[expLengthCode],
									CodeFill[listPosCode]]
			where <expPosCode, use> ← FormBuildPositionCode[BuildExp, nested, context, use2]
			where <expLengthCode, use2> ← FormBuildLengthCode[BuildExp, nested, context, use1]
			where <listPosCode, use1> ← FormBuildPositionCode[BuildExpList, nested, context, usage];

for IntervalExp.none: AbstractProduction[]
	let FormIntervalBuildPositionCode[tree, expList, nested, context, usage] ←
			if nested then FormBuildPositionCode[expList, nested, context, usage]
			 else <RopeCode["position"], FakeUsageCopy[usage]>
	let FormIntervalBuildLengthCode[tree, expList, nested, context, usage] ←
			if nested then FormBuildLengthCode[expList, nested, context, usage]
			 else <RopeCode["length"], FakeUsageCopy[usage]>;
			 
	
for IntervalExp.present: AbstractProduction[IntervalForm.form, ModId.left, ModId.right]
	let FormIntervalBuildPositionCode[tree, expList, nested, context, usage] ←
			if nested then
					(if EqualIntervalForm[IntervalForm.form, IntervalForm.closed] then
							(<code, use>
								where code ← RopeCode1["%g.position", CodeFill[left]]
								where <left, unused, use> ←
									FormExpCode[ModId.left, context, usage])
					else if EqualIntervalForm[IntervalForm.form, IntervalForm.leftOpen] then
							(<code, use>
								where code ← RopeCode2["%g.position + %g.length", 
									CodeFill[left], CodeFill[left]]
								where <left, unused, use> ←
									FormExpCode[ModId.left, context, usage])
					else if EqualIntervalForm[IntervalForm.form, IntervalForm.rightOpen] then
							(<code, use>
								where code ← RopeCode1["%g.position", CodeFill[left]]
								where <left, unused, use> ←
									FormExpCode[ModId.left, context, usage])
						else (<code, use>
								where code ← RopeCode2["%g.position + %g.length", 
									CodeFill[left], CodeFill[left]]
								where <left, unused, use> ←
									FormExpCode[ModId.left, context, usage]))
			
			else <RopeCode["position"], FakeUsageCopy[usage]>
			
	let FormIntervalBuildLengthCode[tree, expList, nested, context, usage] ←
			if nested then
					(if EqualIntervalForm[IntervalForm.form, IntervalForm.closed] then
							(<code, use>
								where code ← RopeCode3["%g.position + %g.length - %g.position",
									CodeFill[right],
									CodeFill[right],
									CodeFill[left]]
								where <right, unused, use> ←
									FormExpCode[ModId.right, context, use1]
								where <left, unused1, use1> ← 
									FormExpCode[ModId.left, context, usage])
					else if EqualIntervalForm[IntervalForm.form, IntervalForm.leftOpen] then
							(<code, use>
								where code ← RopeCode4["%g.position + %g.length - %g.position - %g.length",
									CodeFill[right],
									CodeFill[right],
									CodeFill[left],
									CodeFill[left]]
								where <right, unused, use> ←
									FormExpCode[ModId.right, context, use1]
								where <left, unused1, use1> ← 
									FormExpCode[ModId.left, context, usage])
					else if EqualIntervalForm[IntervalForm.form, IntervalForm.rightOpen] then
							(<code, use>
								where code ← RopeCode2["%g.position - %g.length",
									CodeFill[right],
									CodeFill[left]]
								where <right, unused, use> ←
									FormExpCode[ModId.right, context, use1]
								where <left, unused1, use1> ← 
									FormExpCode[ModId.left, context, usage])
					else 
							(<code, use>
								where code ← RopeCode3["%g.position - %g.position - %g.length",
									CodeFill[right],
									CodeFill[left],
									CodeFill[left]]
								where <right, unused, use> ←
									FormExpCode[ModId.right, context, use1]
								where <left, unused1, use1> ← 
									FormExpCode[ModId.left, context, usage]))
									
			else <RopeCode["length"], FakeUsageCopy[usage]>
					
				



End.