Esempio n. 1
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() );

}