Logo Search packages:      
Sourcecode: ktechlab version File versions  Download package

void Expression::traverseTree ( BTreeNode root,
bool  conditionalRoot = false 
) [private]

Turns the operations encoded in the given tree into assembly code

TODO reimplement assignments as two branched trees?

Definition at line 44 of file expression.cpp.

References PIC14::assignNum(), PIC14::assignVar(), BTreeNode::childOp(), Traverser::current(), Microbe::decDest(), Microbe::dest(), BTreeNode::hasChildren(), Microbe::incDest(), BTreeNode::left(), BTreeNode::needsEvaluating(), BTreeNode::right(), PIC14::saveToReg(), PIC14::setConditionalCode(), Traverser::setCurrent(), BTreeNode::setReg(), BTreeNode::setType(), Traverser::start(), BTreeNode::type(), and BTreeNode::value().

Referenced by compileExpression().

{
      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() );

}


Generated by  Doxygen 1.6.0   Back to index