UTI NodeBinaryOpCompare::checkAndLabelType()
  {
    assert(m_nodeLeft && m_nodeRight);
    UTI leftType = m_nodeLeft->checkAndLabelType();
    UTI rightType = m_nodeRight->checkAndLabelType();

    UlamType * lut = m_state.getUlamTypeByIndex(leftType);
    if((lut->getUlamTypeEnum() == Class))
      {
	Node * newnode = buildOperatorOverloadFuncCallNode();
	if(newnode)
	  {
	    AssertBool swapOk = Node::exchangeNodeWithParent(newnode);
	    assert(swapOk);

	    m_nodeLeft = NULL; //recycle as memberselect
	    m_nodeRight = NULL; //recycle as func call arg

	    delete this; //suicide is painless..

	    return newnode->checkAndLabelType(); //t41109
	  }
	//else should fail again as non-primitive;
      } //done

    UTI newType = calcNodeType(leftType, rightType); //for casting
    if(m_state.isComplete(newType))
      {
	u32 errCnt = 0;
	if(UlamType::compareForMakingCastingNode(rightType, newType, m_state) != UTIC_SAME)
	  {
	    if(!Node::makeCastingNode(m_nodeRight, newType, m_nodeRight))
	      errCnt++;
	  }

	if(UlamType::compareForMakingCastingNode(leftType, newType, m_state) != UTIC_SAME)
	  {
	    if(!Node::makeCastingNode(m_nodeLeft, newType, m_nodeLeft))
	      errCnt++;
	  }

	if(errCnt)
	  newType = Nav;
	else
	  newType = Bool; //always Bool (default size) for node; after castings!
      }
    setNodeType(newType);
    if(newType == Hzy) m_state.setGoAgain(); //nolonger needed in calcnodetypes
    Node::setStoreIntoAble(TBOOL_FALSE);

    //still may need casting (e.g. unary compared to an int) before constantfolding
    if((newType != Nav) && isAConstant() && m_nodeLeft->isReadyConstant() && m_nodeRight->isReadyConstant())
      return NodeBinaryOp::constantFold();

    return newType;
  } //checkAndLabelType
  UTI NodeBinaryOpCompare::checkAndLabelType()
  {
    assert(m_nodeLeft && m_nodeRight);
    UTI leftType = m_nodeLeft->checkAndLabelType();
    UTI rightType = m_nodeRight->checkAndLabelType();

    UTI newType = calcNodeType(leftType, rightType); //for casting
    if(newType != Nav && m_state.isComplete(newType))
      {
	u32 errCnt = 0;
	if(UlamType::compare(rightType, newType, m_state) != UTIC_SAME)
	  {
	    if(!makeCastingNode(m_nodeRight, newType, m_nodeRight))
	      errCnt++;
	  }

	if(UlamType::compare(leftType, newType, m_state) != UTIC_SAME)
	  {
	    if(!makeCastingNode(m_nodeLeft, newType, m_nodeLeft))
	      errCnt++;
	  }

	if(errCnt)
	  newType = Nav;
	else
	  newType = Bool; //always Bool (default size) for node; after castings!
      }
    setNodeType(newType);
    setStoreIntoAble(false);

    //still may need casting (e.g. unary compared to an int) before constantfolding
    if(newType != Nav && isAConstant() && m_nodeLeft->isReadyConstant() && m_nodeRight->isReadyConstant())
      return NodeBinaryOp::constantFold();

    return newType;
  } //checkAndLabelType
Exemple #3
0
  UTI NodeUnaryOp::checkAndLabelType()
  {
    assert(m_node);
    UTI uti = m_node->checkAndLabelType();

    if(m_state.isComplete(uti) && !m_state.isScalar(uti)) //array unsupported at this time
      {
	std::ostringstream msg;
	msg << "Incompatible (nonscalar) type: ";
	msg << m_state.getUlamTypeNameBriefByIndex(uti).c_str();
	msg << ", for unary " << getName();
	MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR);
	setNodeType(Nav);
	return Nav;
      }

    //replace node with func call to matching function overload operator for class
    // of left, with no arguments for unary (t41???);
    // quark toInt must be used on rhs of operators (t3191, t3200, t3513, t3648,9)
    UlamType * ut = m_state.getUlamTypeByIndex(uti);
    if((ut->getUlamTypeEnum() == Class))
      {
	Node * newnode = buildOperatorOverloadFuncCallNode();
	if(newnode)
	  {
	    AssertBool swapOk = Node::exchangeNodeWithParent(newnode);
	    assert(swapOk);

	    m_node = NULL; //recycle as memberselect

	    delete this; //suicide is painless..

	    return newnode->checkAndLabelType();
	  }
	//else should fail again as non-primitive;
      } //done

    UTI newType = Nav;
    if(uti != Nav)
      newType = calcNodeType(uti); //does safety check

    if(m_state.isComplete(newType))
      {
	if(UlamType::compareForMakingCastingNode(newType, uti, m_state) != UTIC_SAME) //not same|dontknow
	  {
	    if(!Node::makeCastingNode(m_node, newType, m_node))
	      newType = Nav;
	  }
      }
    else
      newType = Hzy;

    setNodeType(newType);
    if(newType == Hzy) m_state.setGoAgain(); //since not error
    Node::setStoreIntoAble(TBOOL_FALSE);

    if((newType != Nav) && isAConstant() && m_node->isReadyConstant())
      return constantFold();

    return newType;
  } //checkAndLabelType
  UTI NodeBinaryOpEqualShift::checkAndLabelType()
  {
    //UTI nodeType = NodeBinaryOp::checkAndLabelType(); //dup Shift calcNodeType

    assert(m_nodeLeft && m_nodeRight);

    UTI leftType = m_nodeLeft->checkAndLabelType();
    UTI rightType = m_nodeRight->checkAndLabelType();

    if(!m_state.okUTItoContinue(leftType))
      {
	//left type possibly a class w overload operator; no need to check right type here;
	setNodeType(leftType);
	return getNodeType();
      }

    // efficiency bites! no sooner, need left and right side-effects
    // (e.g. NodeControl condition is Bool at start; stubs need Symbol ptrs)
    if(m_state.isComplete(getNodeType()))
      return getNodeType();

    //replace node with func call to matching function overload operator for class
    // of left, with argument of right;
    UlamType * lut = m_state.getUlamTypeByIndex(leftType);
    if((lut->getUlamTypeEnum() == Class))
      {
	Node * newnode = buildOperatorOverloadFuncCallNode(); //virtual
	if(newnode)
	  {
	    AssertBool swapOk = Node::exchangeNodeWithParent(newnode);
	    assert(swapOk);

	    m_nodeLeft = NULL; //recycle as memberselect
	    m_nodeRight = NULL; //recycle as func call arg

	    delete this; //suicide is painless..

	    return newnode->checkAndLabelType();
	  }
	//else should fail again as non-primitive;
      } //done

    UTI newType = calcNodeType(leftType, rightType); //does safety check

    setNodeType(newType);

    if(m_state.okUTItoContinue(newType))
      {
	TBOOL stor = NodeBinaryOpEqual::checkStoreIntoAble();
	if(stor == TBOOL_FALSE)
	  {
	    setNodeType(Nav);
	    return Nav; //newType
	  }
	else if(stor == TBOOL_HAZY)
	  {
	    setNodeType(Hzy);
	    m_state.setGoAgain();
	  }

	if(!NodeBinaryOpEqual::checkNotUnpackedArray())
	  {
	    setNodeType(Nav);
	    return Nav;
	  }
      }

    if(m_state.isComplete(newType))
      {
	//lhs must be Bits; can't cast lhs of equal.

	//shift by unsigned type; cast if need be. safety checked by calcNodeType.
	if(m_state.getUlamTypeByIndex(rightType)->getUlamTypeEnum() != Unsigned)
	  {
	    if(!Node::makeCastingNode(m_nodeRight, Unsigned, m_nodeRight))
	      {
		newType = Nav;
		setNodeType(Nav);
	      }
	  }
      } //complete

    return getNodeType();
  } //checkandlabeltype