Esempio n. 1
0
void BTreeBase::pruneTree(BTreeNode *root, bool /*conditionalRoot*/)
{
	Traverser t(root);
	
	t.descendLeftwardToTerminal();
	bool done = false;
	while(!done)
	{
	//t.descendLeftwardToTerminal();
	if( t.current()->parent() )
	{
		if( t.oppositeNode()->hasChildren() ) pruneTree(t.oppositeNode());
	}
	
	t.moveToParent();
	if( !t.current()->hasChildren() )
	{
		//if(t.current() == t.root()) done = true;
		if(!t.current()->parent()) done = true;
		continue;
	}

	BTreeNode *l = t.current()->left();
	BTreeNode *r = t.current()->right();
	BTreeNode *n = 0;
	BTreeNode *z = 0;
	

	// Deal with situations where there are two constants so we want
	// to evaluate at compile time
	if( (l->type() == number && r->type() == number) ) // && !(t.current()==root&&conditionalRoot) )
	{
		if(t.current()->childOp() == Expression::division && r->value() == "0" ) 
		{
			t.current()->setChildOp(Expression::divbyzero);
			return;
		}
		QString value = QString::number(Parser::doArithmetic(l->value().toInt(),r->value().toInt(),t.current()->childOp()));
		t.current()->deleteChildren();
		t.current()->setChildOp(Expression::noop);
		t.current()->setType(number);
		t.current()->setValue(value);
	}
	
	// Addition and subtraction
	else if(t.current()->childOp() == Expression::addition || t.current()->childOp() == Expression::subtraction)
	{
	// See if one of the nodes is 0, and set n to the node that actually has data,
	// z to the one containing zero.
	bool zero = false;
	if( l->value() == "0" )
	{
		zero = true;
		n = r;
		z = l;
	}
	else if( r->value() == "0" )
	{
		zero = true;
		n = l;
		z = r;
	}
	// Now get rid of the useless nodes
	if(zero)
	{
		BTreeNode *p = t.current(); // save in order to delete after

		replaceNode(p,n);
		t.setCurrent(n);
		// Delete the old nodes
		delete p;
		delete z;
	}
	}
	
	// Multiplication and division
	else if(t.current()->childOp() == Expression::multiplication || t.current()->childOp() == Expression::division)
	{
	// See if one of the nodes is 0, and set n to the node that actually has data,
	// z to the one containing zero.
	bool zero = false;
	bool one = false;
	if( l->value() == "1" )
	{
		one = true;
		n = r;
		z = l;
	}
	else if( r->value() == "1" )
	{
		one = true;
		n = l;
		z = r;
	}
	if( l->value() == "0" )
	{
		zero = true;
		n = r;
		z = l;
	}
	else if( r->value() == "0" )
	{
		
		// since we can't call compileError from in this class, we have a special way of handling it:
		// Leave the children as they are, and set childOp to divbyzero
		if( t.current()->childOp() == Expression::division )
		{
			t.current()->setChildOp(Expression::divbyzero);
			return; // no point doing any more since we are going to raise a compileError later anyway.
		}
		zero = true;
		n = l;
		z = r;
	}
	// Now get rid of the useless nodes
	if(one)
	{
		BTreeNode *p = t.current(); // save in order to delete after
		replaceNode(p,n);
		t.setCurrent(n);
		// Delete the old nodes
		delete p;
		delete z;
	}
	if(zero)
	{
		BTreeNode *p = t.current();
		p->deleteChildren();
		p->setChildOp(Expression::noop);
		p->setType(number);
		p->setValue("0");
		
	}
	}
	else if( t.current()->childOp() == Expression::bwand || t.current()->childOp() == Expression::bwor || t.current()->childOp() == Expression::bwxor )
	{
	bool zero = false;
	if( l->value() == "0" )
	{
		zero = true;
		n = r;
		z = l;
	}
	else if( r->value() == "0" )
	{
		zero = true;
		n = l;
		z = r;
	}
	// Now get rid of the useless nodes
	if(zero)
	{
		BTreeNode *p = t.current();
		QString value;
		if( p->childOp() == Expression::bwand )
		{
			value = "0";
			p->deleteChildren();
			p->setChildOp(Expression::noop);
			p->setType(number);
		}
		if( p->childOp() == Expression::bwor || p->childOp() == Expression::bwxor )
		{
			value = n->value();
			BTreeNode *p = t.current(); // save in order to delete after
			replaceNode(p,n);
			t.setCurrent(n);
			// Delete the old nodes
			delete p;
			delete z;
		}
		p->setValue(value);
	}
	}
	
	if(!t.current()->parent() || t.current() == root) done = true;
	else
	{

	}
	}
}
Esempio n. 2
0
void Expression::traverseTree( BTreeNode *root, bool conditionalRoot )
{
	Traverser t(root);
	t.start();
	
	// special case: if we are starting at the root node then
	// we are dealing with something of the form variable = 6
	// or variable = portb
	///TODO reimplement assignments as two branched trees?
	if ( t.current() == root &&
			!root->hasChildren() &&
			t.current()->childOp() != pin &&
			t.current()->childOp() != notpin &&
			t.current()->childOp() != function &&
			t.current()->childOp() != read_keypad )
	{
		switch(root->type())
		{
			case number: m_pic->assignNum(root->value()); break;
			case variable: m_pic->assignVar(root->value()); break;
			default: break; // Should never get here
		}
		// no need to traverse the tree as there is none.
		return;
	}
	
	t.setCurrent(root);
	
	if(t.current()->hasChildren())
	{
		// Here we work out what needs evaulating, and in which order.
		// To minimize register usage, if only one branch needs traversing,
		// then that branch should be done first.
		bool evaluateLeft = t.current()->left()->needsEvaluating();
	
		BTreeNode *evaluateFirst;
		BTreeNode *evaluateSecond;
	
		// If both need doing, then it really doesn't matter which we do
		// first (unless we are looking to do really complex optimizations...
	
		// Cases: 
		// - Both need evaluating,
		// - or left needs doing first,
		// in both cases we evaluate left, then right.
		if( evaluateLeft )
		{
			evaluateFirst = t.current()->left();
			evaluateSecond = t.current()->right();
		}
		// Otherwise it is best to evaluate right first for reasons given above.
		else
		{
			evaluateFirst = t.current()->right();
			evaluateSecond = t.current()->left();
		}
		
		QString dest1 = mb->dest();
		mb->incDest();
		QString dest2 = mb->dest();
		mb->decDest();
	
		bool evaluated = false;
		if( evaluateFirst->hasChildren() )
		{	
			traverseTree(evaluateFirst);
			evaluated = true;
		}
		else if( isUnaryOp(evaluateFirst->childOp()) )
		{
			doUnaryOp( evaluateFirst->childOp(), evaluateFirst );
			evaluated = true;
		}
		if ( evaluated )
		{
			// We need to save the result if we are going tro traverse the other
			// branch, or if we are performing a subtraction in which case the
			// value wanted in working is not the current value.
			// But as the optimizer will deal with unnecessary variables anyway,
			// always save to a register
			
			evaluateFirst->setReg( dest1 );
			evaluateFirst->setType( variable );
			m_pic->saveToReg( dest1 );
		}
	
		evaluated = false;
		if( evaluateSecond->hasChildren() )
		{
			mb->incDest();
			mb->incDest();
			traverseTree(evaluateSecond);
			evaluated = true;
			mb->decDest();
			mb->decDest();
		}
		else if( isUnaryOp(evaluateSecond->childOp()) )
		{
			doUnaryOp( evaluateSecond->childOp(), evaluateSecond );
			evaluated = true;
		}
		if ( evaluated )
		{
			evaluateSecond->setReg( dest2 );
			evaluateSecond->setType( variable );
			m_pic->saveToReg( dest2 );
		}
	}
	
	if(t.current()->childOp()==divbyzero)
	{
		mistake( Microbe::DivisionByZero );
	}
	
	// If we are at the top level of something like 'if a == 3 then', then we are ready to put
	// in the if code, else the expression just evaluates to 0 or 1
	if(conditionalRoot && t.current() == root)
		m_pic->setConditionalCode(m_ifCode, m_elseCode);

	// Handle operations
	// (functions are not actually supported)
	if(isUnaryOp(t.current()->childOp()))
		doUnaryOp( t.current()->childOp(), t.current() );
	else
		doOp( t.current()->childOp(), t.current()->left(), t.current()->right() );

}
Esempio n. 3
0
void Expression::compileConditional( const QString & expression, Code * ifCode, Code * elseCode )
{
	if( expression.contains(QRegExp("=>|=<|=!")) )
	{
		mistake( Microbe::InvalidComparison, expression );
		return;
	}
	if( expression.contains(QRegExp("[^=><!][=][^=]")))
	{
		mistake( Microbe::InvalidEquals );
		return;
	}
	// Make a tree to put the expression in.
	BTreeBase *tree = new BTreeBase();
	BTreeNode *root = new BTreeNode();

	// parse the expression into the tree
	buildTree(expression,tree,root,0);
	
	// Modify the tree so it is always at the top level of the form (kwoerpkwoep) == (qwopekqpowekp)
	if ( root->childOp() != equals &&
			root->childOp() != notequals &&
			root->childOp() != gt &&
			root->childOp() != lt &&
			root->childOp() != ge &&
			root->childOp() != le &&
			root->childOp() != pin &&
			root->childOp() != notpin &&
			root->childOp() != read_keypad )
	{
		BTreeNode *newRoot = new BTreeNode();
		
		BTreeNode *oneNode = new BTreeNode();
		oneNode->setChildOp(noop);
		oneNode->setType(number);
		oneNode->setValue("1");
		
		newRoot->setLeft(root);
		newRoot->setRight(oneNode);
		newRoot->setType(unset);
		newRoot->setChildOp(ge);
		
		tree->setRoot(newRoot);
		root = newRoot;
	}
	// compile the tree into assembly code
	tree->setRoot(root);
	tree->pruneTree(tree->root(),true);
	
	// We might have just a constant expression, in which case we can just always do if or else depending
	// on whether it is true or false.
	if( root->childOp() == noop )
	{
		if( root->value().toInt() == 0 )
			m_pic->mergeCode( elseCode );
		else
			m_pic->mergeCode( ifCode );
		return;
	}
	
	// traverse tree with argument conditionalRoot true
	// so that 3 == x gets integrated with code for if, repeat until etc...
	m_ifCode = ifCode;
	m_elseCode = elseCode;
	traverseTree(tree->root(),true);
	
	// Note deleting the tree deletes all nodes, so the root
	// doesn't need deleting separately.
	delete tree;
}
Esempio n. 4
0
void Expression::buildTree( const QString & unstrippedExpression, BTreeBase *tree, BTreeNode *node, int level )
{
	int firstEnd = 0;
	int secondStart = 0;
	bool unary = false;
	Operation op = noop;
	QString expression = stripBrackets( unstrippedExpression );
	switch(level)
	{
		// ==, !=
		case 0:
		{
		int equpos = findSkipBrackets(expression, "==");
		int neqpos = findSkipBrackets(expression, "!=");
		if( equpos != -1 )
		{
			op = equals;
			firstEnd = equpos;
			secondStart = equpos + 2;
		}
		else if( neqpos != -1 )
		{
			op = notequals;
			firstEnd = neqpos;
			secondStart = neqpos + 2;
		}
		else op = noop;
		break;
		}

		// <, <=, >=, >
		case 1:
		{
		int ltpos = findSkipBrackets(expression, "<");
		int lepos = findSkipBrackets(expression, "<=");
		int gepos = findSkipBrackets(expression, ">=");
		int gtpos = findSkipBrackets(expression, ">");
		// Note: if (for example) "<=" is present, "<" will also be present. This
		// means that we have to check for "<=" before "<", etc.
		if( lepos != -1 )
		{
			op = le;
			firstEnd = lepos;
			secondStart = lepos + 2;
		}
		else if( gepos != -1 )
		{
			op = ge;
			firstEnd = gepos;
			secondStart = gepos + 2;
		}
		else if( ltpos != -1 )
		{
			op = lt;
			firstEnd = ltpos;
			secondStart = ltpos + 1;
		}
		else if( gtpos != -1 )
		{
			op = gt;
			firstEnd = gtpos;
			secondStart = gtpos + 1;
		}
		else op = noop;
		break;
		}

		// +,-
		case 2:
		{
		int addpos = findSkipBrackets(expression, '+');
		int subpos = findSkipBrackets(expression, '-');
		if( subpos != -1 )
		{
			op = subtraction;
			firstEnd = subpos;
			secondStart = subpos + 1;
		}
		else if( addpos != -1 )
		{
			op = addition;
			firstEnd = addpos;
			secondStart = addpos + 1;
		}
		else op = noop;
		break;
		}
		
		// *,/
		case 3:
		{
		int mulpos = findSkipBrackets(expression, '*');
		int divpos = findSkipBrackets(expression, '/');
		if( divpos != -1 )
		{
			op = division;
			firstEnd = divpos;
			secondStart = divpos + 1;
		}
		else if( mulpos != -1 )
		{
			op = multiplication;
			firstEnd = mulpos;
			secondStart = mulpos + 1;
		}
		else op = noop;
		break;
		}
		
		// ^
		case 4:
		{
		int exppos = findSkipBrackets(expression, '^');
		if( exppos != -1 )
		{
			op = exponent;
			firstEnd = exppos;
			secondStart = exppos + 1;
		}
		else op = noop;
		break;
		}
		
		// AND, OR, XOR
		case 5:
		{
		int bwAndPos = findSkipBrackets(expression, " AND ");
		int bwOrPos = findSkipBrackets(expression, " OR ");
		int bwXorPos = findSkipBrackets(expression, " XOR ");
		if( bwAndPos != -1 )
		{
			op = bwand;
			firstEnd = bwAndPos;
			secondStart = bwAndPos + 5;
		}
		else if( bwOrPos != -1 )
		{
			op = bwor;
			firstEnd = bwOrPos;
			secondStart = bwOrPos + 4;
		}
		else if( bwXorPos != -1 )
		{
			op = bwxor;
			firstEnd = bwXorPos;
			secondStart = bwXorPos + 5;
		}
		else op = noop;
		break;
		}
		
		// NOT
		case 6:
		{
		int bwNotPos = findSkipBrackets(expression, " NOT ");
		if( bwNotPos != -1 )
		{
			op = bwnot;
			unary = true;
			firstEnd = bwNotPos; // this line is not needed for unary things/
			secondStart = bwNotPos + 5;
		}
		else op = noop;
		break;
		}
	}
	
	node->setChildOp(op);
	
	QString tokens[2];
	tokens[0] = expression.left(firstEnd).trimmed();
	tokens[1] = expression.mid(secondStart).trimmed();
	
	if( op != noop )
	{	
		for( int j = 0; j < 2; j++ )
		{
			
			BTreeNode *newNode = new BTreeNode();
			tree->addNode( node, newNode, (j == 0) );
			// we need to strip any brackets from the sub-expression
			
			// try each token again at the same level, if they 
			// don't have any of this level's operators, then the function
			// will go to the next level as below.
			
			// For unary opertaions, e.g NOT, we have no special 
			// code for nodes with only one child, so we leave the left
			// hand child blank and put the rest in the right hand node.
			if( unary && j == 0 )
			{
				newNode->setValue("");
				newNode->setType(number);
			}
			else buildTree(tokens[j], tree, newNode, 0 );
		}
	}
	else
	{
		// if there was no relevant operation i.e. " 3*4 / 6" as opposed to " 3*4 + 6"
		// then just pass the node onto the next parsing level.
		// unless we are at the lowest level, in which case we have reached a final value.
		if( level == 6 ) expressionValue(expression,tree,node);
		else 
		{
			buildTree(expression,tree,node,level + 1);
		}
	}
}