QString Container::toString() const
{
	QStringList ret;
	bool func=false;
	
	Operator *op=0;
	for(int i=0; i<m_params.count(); i++) {
		if(m_params[i]==0) {
			qDebug() << "kkk";
			return "<<kk>>";
		}
		
		if(m_params[i]->type() == Object::oper)
			op = (Operator*) m_params[i];
		else if(m_params[i]->type() == Object::variable) {
			Ci *b = (Ci*) m_params[i];
			if(b->isFunction())
				func=true;
			ret << b->toString();
		} else if(m_params[i]->type() == Object::container) {
			Container *c = (Container*) m_params[i];
			QString s = c->toString();
			Operator child_op = c->firstOperator();
			if(op!=0 && op->weight()>child_op.weight() && child_op.nparams()!=1)
				s=QString("(%1)").arg(s);
			
			if(c->containerType() == Object::bvar) {
				Container *ul = ulimit(), *dl = dlimit();
				if(ul!=0 || dl!=0) {
					if(dl!=0)
						s += dl->toString();
					s += "..";
					if(ul!=0)
						s += ul->toString();
				}
			}
			
			if(c->containerType()!=Object::uplimit && c->containerType()!=Object::downlimit)
				ret << s;
		} else 
			ret << m_params[i]->toString();
	}
	
	QString toret;
	switch(containerType()) {
		case Object::declare:
			toret += ret.join(":=");
			break;
		case Object::lambda:
			toret += ret.join("");
			break;
		case Object::math:
			toret += ret.join("; ");
			break;
		case Object::apply:
			if(func){
				QString n = ret.takeFirst();
				toret += QString("%1(%2)").arg(n).arg(ret.join(", "));
			} else if(op==0)
				toret += ret.join(" ");
			else switch(op->operatorType()) {
				case Object::plus:
					toret += ret.join("+");
					break;
				case Object::times:
					toret += ret.join("*");
					break;
				case Object::divide:
					toret += ret.join("/");
					break;
				case Object::minus:
					if(ret.count()==1)
						toret += "-"+ret[0];
					else
						toret += ret.join("-");
					break;
				case Object::power:
					toret += ret.join("^");
					break;
				default:
					toret += QString("%1(%2)").arg(op->toString()).arg(ret.join(", "));
					break;
			}
			break;
		case Object::uplimit: //x->(n1..n2) is put at the same time
		case Object::downlimit:
			break;
		case Object::bvar:
			toret += ret.join("->")+"->";
			break;
		default:
			toret += ret.join(" ?? ");
			break;
	}
	return toret;
}