

string GeneratorUniqueName(AllNames){
	size=(int)'Z'-(int)'A'+1;
	n=1;
	while(1){
		newName="";
		for(i=0;i<n;++i)newName+=(char)((rand()%size)+(int)'A');
		if(isset(AllNames))if(AllNames->indexOf(newName)<0)break;
		++n;
		}
	if(isset(AllNames))AllNames->push(newName);
	return newName;
}


var question(vopros,formula,nameVar){
	namedll="what.dll";
	if(DLLS.indexOf(namedll)<0){
		LoadDLL(namedll);
		SendDLL(namedll,"WAY:"+WAY);
		}
	if(vopros=="equality")what="?: get equality for ("+formula+") unknown {"+nameVar+"}";
	if(vopros=="optimize")what="?: optimize ("+formula+")";
	if(vopros=="compare"){
		if(typeof(formula)=="program")if(formula.typeof()=="="){
			formula2=PROGRAM("#==#");
			formula2.setSub({0},formula.getSub({0}));
			formula2.setSub({1},formula.getSub({1}));
			formula=formula2;
			}
		what="?: compare ("+formula+")";
		}
	SendDLL(namedll,what);
	R=RecvDLL(namedll);
	//trace(what);trace(R.export());
	return R;
}


// Вернёт все имена переменных в указанной функции
vector getAllNamesIzFunction(func){
	f=&func;
	if(typeof(func)=="string")f=func;
	AllNamesFunction=f->getNamesStart();
	S=f->getIDs();
	while(S.size()){
		n=S.pop();
		command=f->getCommand(n);
		if(typeof(command)=="program")AllNamesFunction+=getListAllVar(command);
		}
	return (vector)(set)AllNamesFunction;
}



//Взять список всех переменных
vector getListAllVar(comand){
	S=(set){};
	acces={};
	accesf={};
	isf=0;
	while(1){
		p=comand.getRowSize(acces);
		x=comand.getSub(acces);
		if(typeof(x)=="program"){
			if(p==1)if(x.typeof()=="CreateVar")S.insert(x.typeof({},"name"));
			if(!p)if(x.typeof()=="var")S.insert((string)x);
			}
		acces.push(p);
		isf=(x.typeof()=="function");
		accesf.push(isf);
		n=acces.size()-1;
		p=acces[n];
		isf=accesf[n];
		if(isf)if(p==1)--p;
		while(!p){
			acces.pop_back();
			accesf.pop_back();
			--n;
			if(n<0)break;
			p=acces[n];
			isf=accesf[n];
			if(isf)if(p==1)--p;
			}
		if(!p)break;
		--p;
		acces[n]=p;
		}
	return (vector)S;
}



// заменит в программе все переменные ho на выражение na
var ReplaceVars(var*proga,string ho,var na){
	if(typeof(na)!="program")na=PROGRAM((string)na);
	acces={};
	ok=0;
	while(1){
		p=proga->getRowSize(acces);
		if(proga->typeof(acces,"name")==ho)proga->typeof(acces,"name",na);
		if(!p){
			x=proga->getSub(acces);
			if(ho==x){
				proga->setSub(acces,na);
				ok=1;
				}
			}
		acces.push(p);
		n=acces.size()-1;
		p=acces[n];
		while(!p){
			acces.pop_back();
			--n;
			if(n<0)break;
			p=acces[n];
			}
		if(!p)break;
		--p;
		acces[n]=p;
		}
	return ok;
}



void InverseCondition(condition){
	type=condition->typeof();
	if(type=="!."){
		*condition=condition->getSub({0});
		return;
		}
	if((a=type[0]=='<') || type[0]=='>'){
		b=type.size()==1;
		type=(a?">":"<");
		if(b)type+="=";
		c=PROGRAM("#"+type+"#");
		c.setSub({0},condition->getSub({0}));
		c.setSub({1},condition->getSub({1}));
		*condition=c;
		return;
		}
	if(type=="!=" || type=="=="){
		type=(type=="!="?"==":"!=");
		c=PROGRAM("#"+type+"#");
		c.setSub({0},condition->getSub({0}));
		c.setSub({1},condition->getSub({1}));
		*condition=c;
		return;
		}
	if(type=="&&" || type=="||"){
		type=(type=="&&"?"||":"&&");
		c=PROGRAM("#"+type+"#");
		x=condition->getSub({0});
		InverseCondition(&x);
		c.setSub({0},x);
		x=condition->getSub({1});
		InverseCondition(&x);
		c.setSub({1},x);
		*condition=c;
		return;
		}
	c=PROGRAM("!#");
	c.setSub({0},*condition);
	*condition=c;
}

