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
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