Cn Analitza::calc(Object* root)
{
	Q_ASSERT(root && root->type()!=Object::none);
	Cn ret=Cn(0.);
	Ci *a;
	
	switch(root->type()) {
		case Object::container:
			ret = operate((Container*) root);
			break;
		case Object::value:
			ret=(Cn*) root;
			break;
		case Object::variable:
			a=(Ci*) root;
			
			if(m_vars->contains(a->name()))
				ret = calc(m_vars->value(a->name()));
			else if(a->isFunction())
				m_err << i18n("The function <em>%1</em> doesn't exist").arg(a->name());
			else
				m_err << i18n("The variable <em>%1</em> doesn't exist").arg(a->name());
			
			break;
		case Object::oper:
		default:
			break;
	}
	return ret;
}
void objectWalker(const Object* root, int ind)
{
	Container *c; Cn *num; Operator *op; Ci *var;
	QString s;
	if(!root) {
		qDebug() << "This is an null object";
		return;
	}
	if(ind>100) return;
	
	for(int i=0; i<ind; i++)
		s += " |_____";
	
	switch(root->type()) { //TODO: include the function into a module and use toString
		case Object::container:
			c= (Container*) root;
			qDebug() << qPrintable(s) << "| cont: " << c->toMathML();
			for(int i=0; i<c->m_params.count(); i++)
				objectWalker(c->m_params[i], ind+1);
			
			break;
		case Object::value:
			num= (Cn*) root;
			qDebug() << qPrintable(s) << "| num: " << num->value();
			break;
		case Object::oper:
			op= (Operator*) root;
			qDebug() << qPrintable(s) << "| operator: " << op->toString();
			break;
		case Object::variable:
			var = (Ci*) root;
			qDebug() << qPrintable(s) << "| variable: " << var->name() << "Func:" << var->isFunction();
			break;
		default:			qDebug() << qPrintable(s) << "| dunno: " << (int) root->type();
			break;
	}
}
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;
}