Ejemplo n.º 1
0
  Node * NodeBinaryOpCompare::buildOperatorOverloadFuncCallNode()
  {
    Token identTok;
    TokenType opTokType = Token::getTokenTypeFromString(getName());
    assert(opTokType != TOK_LAST_ONE);
    Token opTok(opTokType, getNodeLocation(), 0);
    u32 opolId = Token::getOperatorOverloadFullNameId(opTok, &m_state);
    if(opolId == 0)
      {
	std::ostringstream msg;
	msg << "Overload for operator <" << getName();
	msg << "> is not supported as operand for class: ";
	msg << m_state.getUlamTypeNameBriefByIndex(m_nodeLeft->getNodeType()).c_str();
	MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR);
	return NULL;
      }

    identTok.init(TOK_IDENTIFIER, getNodeLocation(), opolId);

    //may need to negate the opposite comparison, if this one isn't defined (t41109)
    UTI luti = m_nodeLeft->getNodeType();
    SymbolClass * csym = NULL;
    AssertBool isDefined = m_state.alreadyDefinedSymbolClass(luti, csym);
    assert(isDefined);

    NodeBlockClass * memberClassNode = csym->getClassBlockNode();
    assert(memberClassNode);  //e.g. forgot the closing brace on quark definition

    assert(m_state.okUTItoContinue(memberClassNode->getNodeType()));

   //set up compiler state to use the member class block for symbol searches
    m_state.pushClassContextUsingMemberClassBlock(memberClassNode);

    Symbol * fnsymptr = NULL;
    bool hazyKin = false; //unused
    bool useInverseOp = false;
    if(!m_state.isFuncIdInClassScope(opolId, fnsymptr, hazyKin))
      {
	//try inverse!
	const char * invopname = getInverseOpName();
	if(!invopname)
	  return NULL; //built-in error msg
	opTokType = Token::getTokenTypeFromString(invopname);
	assert(opTokType != TOK_LAST_ONE);
	opTok.init(opTokType, getNodeLocation(), 0);
	opolId = Token::getOperatorOverloadFullNameId(opTok, &m_state);
	assert(opolId != 0);
	if(!m_state.isFuncIdInClassScope(opolId, fnsymptr, hazyKin))
	  {
	    std::ostringstream msg;
	    msg << "Overload for operator <" << getName();
	    msg << "> and its inverse <" << invopname;
	    msg << "> are not supported as operand for class: ";
	    msg << m_state.getUlamTypeNameBriefByIndex(luti).c_str();
	    MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR);
	    return NULL;
	  }
	else //continue with a bang
	  {
	    std::ostringstream msg;
	    msg << "Using overload operator <" << getName();
	    msg << ">'s negated inverse <" << invopname;
	    msg << "> operator for class: ";
	    msg << m_state.getUlamTypeNameBriefByIndex(luti).c_str();
	    MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG);
	    useInverseOp = true;
	  }
      }
    //else continue without a bang

    //clear up compiler state to no longer use the member class block for symbol searches
    m_state.popClassContext();

    identTok.init(TOK_IDENTIFIER, getNodeLocation(), opolId);

    //fill in func symbol during type labeling;
    NodeFunctionCall * fcallNode = new NodeFunctionCall(identTok, NULL, m_state);
    assert(fcallNode);
    fcallNode->setNodeLocation(identTok.m_locator);

    fcallNode->addArgument(m_nodeRight);

    Node * rnode = fcallNode;
    if(useInverseOp)
      {
	rnode = new NodeUnaryOpBang(fcallNode, m_state);
	rnode->setNodeLocation(identTok.m_locator);
      }

    NodeMemberSelect * mselectNode = new NodeMemberSelect(m_nodeLeft, rnode, m_state);
    assert(mselectNode);
    mselectNode->setNodeLocation(identTok.m_locator);

    //redo check and type labeling done by caller!!
    return mselectNode; //replace right node with new branch
  } //buildOperatorOverloadFuncCallNode
Ejemplo n.º 2
0
  UTI NodeMemberSelect::checkAndLabelType()
  {
    assert(m_nodeLeft && m_nodeRight);

    UTI luti = m_nodeLeft->checkAndLabelType(); //side-effect
    TBOOL lstor = m_nodeLeft->getStoreIntoAble();
    if(lstor != TBOOL_TRUE)
      {
	//e.g. funcCall is not storeintoable even if its return value is.
	std::ostringstream msg;
	msg << "Member selected must be a valid lefthand side: '";
	msg << m_nodeLeft->getName();
	msg << "' requires a variable; may be a casted function call";
	if(lstor == TBOOL_HAZY)
	  {
	    MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT);
	    setNodeType(Hzy);
	    m_state.setGoAgain();
	    return Hzy;
	  }
	else
	  {
	    MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR);
	    setNodeType(Nav);
	    return Nav;
	  }
      } //done

    if(!m_state.isComplete(luti))
      {
	std::ostringstream msg;
	msg << "Member selected is incomplete class: ";
	msg << m_state.getUlamTypeNameBriefByIndex(luti).c_str();
	msg << ", check and label fails this time around";
	if(luti == Nav)
	  {
	    MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR);
	    setNodeType(Nav);
	  }
	else
	  {
	    MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT);
	    setNodeType(Hzy);
	    m_state.setGoAgain(); //since no error msg
	  }
	return getNodeType();
      } //done

    UlamType * lut = m_state.getUlamTypeByIndex(luti);
    ULAMCLASSTYPE classtype = lut->getUlamClassType();
    if(((classtype == UC_NOTACLASS) && (lut->getUlamTypeEnum() != Holder)) || !lut->isScalar())
      {
	// must be a scalar 'Class' type, (e.g. error/t3815)
	// doesn't complete checkandlabel for rhs (e.g. funccall is NULL, no eval)
	std::ostringstream msg;
	msg << "Member selected must be a Class, not type: ";
	msg << m_state.getUlamTypeNameBriefByIndex(luti).c_str();
	if(classtype != UC_NOTACLASS)
	  msg << "[" << lut->getArraySize() << "]";
	if(m_state.isAtom(luti))
	  msg << "; suggest using a Conditional-As";
	MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR);
	setNodeType(Nav);
	return Nav;
      } //done

    std::string className = m_state.getUlamTypeNameBriefByIndex(luti); //help me debug

    SymbolClass * csym = NULL;
    AssertBool isDefined = m_state.alreadyDefinedSymbolClass(luti, csym);
    assert(isDefined);

    NodeBlockClass * memberClassNode = csym->getClassBlockNode();
    assert(memberClassNode);  //e.g. forgot the closing brace on quark definition

    assert(m_state.okUTItoContinue(memberClassNode->getNodeType())); //t41010

   //set up compiler state to use the member class block for symbol searches
    m_state.pushClassContextUsingMemberClassBlock(memberClassNode);

    UTI rightType = m_nodeRight->checkAndLabelType();

    //clear up compiler state to no longer use the member class block for symbol searches
    m_state.popClassContext();

    setNodeType(rightType); //set Nav if error (t3513)

    if(m_state.okUTItoContinue(rightType))
      {
	//based on righthand side
	Node::setStoreIntoAble(m_nodeRight->getStoreIntoAble());

	//base reference-ability on righthand side (t41085)
	Node::setReferenceAble(m_nodeRight->getReferenceAble());
      }
    return getNodeType();
  } //checkAndLabelType