// work.code

#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(var 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();
		for(;sys->inputs.size()>n;sys->inputs.pop()){
			}
		for(;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(var s){
	if(typeof(s)!="string")return # ;
	P=PROGRAM(s);
	if(typeof(P)!="program")return # ;
	return P;
}



void PodgotovkaProgresDetails(var 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){
			i=0;
			for(;i<sys->namesinput.size();++i){
				nabor={};
				t=0;
				for(;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(var sys){
	PodgotovkaProgresDetails(sys);
	sys->DetailsCompleate=1;
	FList={};
	i=0;
	for(;i<sys->detali.size();++i)if({"function","program"}.find(typeof((sys->detali)[i]))>=0)FList.push(i);
	i=0;
	for(;i<FList.size();++i){
		F=(sys->detali)[FList[i]];
		if(typeof(F)!="function");else {
			names=F.getNamesStart();
			if(names.size()==1){
				sizedet=sys->detali.size();
				t=0;
				for(;t<sizedet;++t){
					X=F.run((sys->detali)[t]);
					if(!isset(X));else {if(sys->detali.find(X)<0){
						sys->detali.push(X);
						sys->DetailsCompleate=0;
						}}
					}
				}
			}
		}
	i=0;
	for(;i<FList.size();++i){
		P=(sys->detali)[FList[i]];
		if(typeof(P)!="program");else {
			names=P.getNames();
			if(names.size()==2)production2(sys,P);
			}
		}
}



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



void production2(var sys,var 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");
	i=0;
	for(;i<sumsize;++i){
		j=0;
		for(;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);
				}else {
				R={};
				if(okONEA){
					A=(sys->detali)[i];
					if(typeof(A)=="function")continue;
					}
				if(okONEB){
					B=(sys->detali)[j];
					if(typeof(B)=="function")continue;
					}
				t=0;
				for(;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);
					}
				}
			};
		}
}



void Work(var sys){
	ControlCorrectSys(sys);
	ProgresDetailsFull(sys);
	NumberLevel(sys);
	if(BoolLevel(sys))return;
	if(GroupLevel(sys))return;
	if(sys->functions.empty())ZeroLevel(sys);
}


// work.code	:-|