// work.txt

#include <code\programmer\ZeroLevel.txt>
#include <code\programmer\NumberLevel.txt>
#include <code\programmer\BoolLevel.txt>
#include <code\programmer\GroupLevel.txt>
#include <code\programmer\instruments.txt>



void ControlCorrectSys(sys){
	if(!isset(sys->functions))sys->functions={};
	if(!isset((*sys)["имя программы"]))(*sys)["имя программы"]="main";
	n={sys->inputs.size(),sys->outputs.size()};
	if(n[0]!=n[1]){
		trace("Несоответствует количество входных данных с количеством выходных.");
		n=n.min();
		while(sys->inputs.size()>n)sys->inputs.pop();
		while(sys->outputs.size()>n)sys->outputs.pop();
		}
	if(!isset(sys->namesinput))sys->namesinput={"input"};
	if(!isset(sys->namesoutput))sys->namesoutput={"output"};
	if(!sys->isset("DetailsCompleate"))sys->DetailsCompleate=0;
}




program stringToProgram(s){
	if(typeof(s)!="string")return #;
	P=PROGRAM(s);
	if(typeof(P)!="program")return #;
	return P;
}



void PodgotovkaProgresDetails(sys){
	if(!sys->isset("newParams")){
		sys->newParams={};
		sys->newParamsF={};
		if(sys->namesinput.size()==1){
			sys->newParams.push(sys->inputs);
			sys->newParamsF.push(PROGRAM(sys->namesinput[0]));
			}
		if(sys->namesinput.size()>1)for(i=0;i<sys->namesinput.size();++i){
			nabor={};
			for(t=0;t<sys->inputs.size();++t){
				Args=sys->inputs[t];
				Arg=#;
				if(typeof(Args)=="vector")if(Args.size()>i)Arg=Args[i];
				nabor.push(Arg);
				}
			sys->newParams.push(nabor);
			sys->newParamsF.push(PROGRAM(sys->namesinput[i]));
			}
		}
	if(!sys->isset("detali"))sys->detali={};
	StoPF=getFunction("stringToProgram");
	if(sys->detali.find(StoPF)<0)sys->detali.push(StoPF);
	if(!sys->isset("DetailsCompleate"))sys->DetailsCompleate=0;
}



void ProgresDetails(sys){
	PodgotovkaProgresDetails(sys);
	sys->DetailsCompleate=1;
	FList={};
	for(i=0;i<sys->detali.size();++i)
		if({"function","program"}.find(typeof(sys->detali[i]))>=0)FList.push(i);
	for(i=0;i<FList.size();++i){
		F=sys->detali[FList[i]];
		if(typeof(F)!="function")continue;
		names=F.getNamesStart();
		if(names.size()==1){
			sizedet=sys->detali.size();
			for(t=0;t<sizedet;++t){
				X=F.run(sys->detali[t]);
				if(!isset(X))continue;
				if(sys->detali.find(X)<0){
					sys->detali.push(X);
					sys->DetailsCompleate=0;
					}
				}
			}

		}
	for(i=0;i<FList.size();++i){
		P=sys->detali[FList[i]];
		if(typeof(P)!="program")continue;
		names=P.getNames();
		if(names.size()==2)production2(sys,P);
		}

}




void ProgresDetailsFull(sys){
	while(!sys->DetailsCompleate)ProgresDetails(sys);
}




void production2(sys,P){
	sizedet=sys->detali.size();
	sizeParams=sys->newParams.size();
	sumsize=sizedet+sizeParams;
	sizeOneRow=0;
	if(sizeParams)sizeOneRow=sys->newParams[0].size();
	if(sumsize<2)return;
	names=P.getNames();
	P.replace(names[0],"A");
	P.replace(names[1],"B");
	//trace(P);
	//trace(sys->newParams.export());
	//trace("pow=="+sumsize*(sumsize-1));
	for(i=0;i<sumsize;++i)
	for(j=0;j<sumsize;++j)if(i!=j){
		okONEA=i<sizedet;
		okONEB=j<sizedet;
		if(okONEA && okONEB){
			A=sys->detali[i];
			B=sys->detali[j];
			R=eval(P);
			if(sys->detali.find(R)<0)sys->detali.push(R);
			continue;
			}
		R={};
		if(okONEA){
			A=sys->detali[i];
			if(typeof(A)=="function")continue;
			}
		if(okONEB){
			B=sys->detali[j];
			if(typeof(B)=="function")continue;
			}
		for(t=0;t<sizeOneRow;++t){
			if(!okONEA)A=sys->newParams[i-sizedet][t];
			if(!okONEB)B=sys->newParams[j-sizedet][t];
			R.push(eval(P));
			}
		if(sys->newParams.find(R)<0){
			sys->DetailsCompleate=0;
			sys->newParams.push(R);
			P2=P;
			if(okONEA){
				X=(typeof(A)=="program")?A:(string)A;
				if(typeof(A)=="bool")X="(bool)"+A?1:0;
				if({"string","vector","set"}.find(typeof(A))>=0)X=A.export();
				X=PROGRAM(X);
				}else{
				X=sys->newParamsF[i-sizedet];
				if(typeof(X)=="vector")X=X[#];
				}
			ReplaceVars(&P2,"A",X);
			if(okONEB){
				X=(typeof(B)=="program")?B:(string)B;
				if(typeof(B)=="bool")X="(bool)"+B?1:0;
				if({"string","vector","set"}.find(typeof(B))>=0)X=B.export();
				X=PROGRAM(X);
				}else{
				X=sys->newParamsF[j-sizedet];
				if(typeof(X)=="vector")X=X[#];
				}
			ReplaceVars(&P2,"B",X);
			sys->newParamsF.push(P2);
			//trace(R.export());
			}
		}
}




void Work(sys){
	ControlCorrectSys(sys);
	ProgresDetailsFull(sys);
	NumberLevel(sys);
	if(BoolLevel(sys))return;
	if(GroupLevel(sys))return;


	if(sys->functions.empty())ZeroLevel(sys);
}









