EvalStatus NodeStatements::eval() { assert(m_node); evalNodeProlog(0); makeRoomForNodeType(m_node->getNodeType()); EvalStatus evs = m_node->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //not the last one, so thrown out results and continue if(m_nodeNext) { evalNodeEpilog(); evs = m_nodeNext->eval(); if(evs != NORMAL) { return evs; } } else evalNodeEpilog(); return NORMAL; } //eval
//overrides parent due to short-circuiting requirement EvalStatus NodeBinaryOpLogicalOr::eval() { assert(m_nodeLeft && m_nodeRight); UTI nuti = getNodeType(); u32 len = m_state.getTotalBitSize(nuti); evalNodeProlog(0); //new current frame pointer u32 slot = makeRoomForNodeType(nuti); EvalStatus evs = m_nodeLeft->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //short-circuit if lhs is true UlamValue luv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(slot); //immediate value u32 ldata = luv.getImmediateData(len, m_state); if(_Bool32ToCbool(ldata, len) == true) { //copies return UV to stack, -1 relative to current frame pointer m_state.m_nodeEvalStack.storeUlamValueInSlot(luv, -1); } else { u32 slot2 = makeRoomForNodeType(getNodeType()); evs = m_nodeRight->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue ruv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(slot+slot2); //immediate value //copies return UV to stack, -1 relative to current frame pointer m_state.m_nodeEvalStack.storeUlamValueInSlot(ruv, -1); } evalNodeEpilog(); return NORMAL; } //eval
// eval() no longer performed before check and label // returns false if error; UNKNOWNSIZE is not an error! bool NodeSquareBracket::getArraysizeInBracket(s32 & rtnArraySize) { bool noerr = true; // since square brackets determine the constant size for this type, else error s32 newarraysize = NONARRAYSIZE; UTI sizetype = m_nodeRight->checkAndLabelType(); if(sizetype == Nav) { rtnArraySize = UNKNOWNSIZE; return true; } UlamType * sizeut = m_state.getUlamTypeByIndex(sizetype); // expects a constant, numeric type within [] if(sizeut->isNumericType() && m_nodeRight->isAConstant()) { evalNodeProlog(0); //new current frame pointer makeRoomForNodeType(sizetype); //offset a constant expression if(m_nodeRight->eval() == NORMAL) { UlamValue arrayUV = m_state.m_nodeEvalStack.popArg(); u32 arraysizedata = arrayUV.getImmediateData(m_state); newarraysize = sizeut->getDataAsCs32(arraysizedata); if(newarraysize < 0 && newarraysize != UNKNOWNSIZE) //NONARRAY or UNKNOWN { MSG(getNodeLocationAsString().c_str(), "Array size specifier in [] is not a positive number", ERR); noerr = false; } //else unknown is not an error } else //newarraysize = UNKNOWNSIZE; //still true noerr = false; evalNodeEpilog(); } else { MSG(getNodeLocationAsString().c_str(), "Array size specifier in [] is not a constant number", ERR); noerr = false; } rtnArraySize = newarraysize; return noerr; } //getArraysizeInBracket
EvalStatus NodeUnaryOp::eval() { assert(m_node); UTI nuti = getNodeType(); if(nuti == Nav) return evalErrorReturn(); if(nuti == Hzy) return evalStatusReturnNoEpilog(NOTREADY); evalNodeProlog(0); //new current frame pointer u32 slots = makeRoomForNodeType(nuti); EvalStatus evs = m_node->eval(); if(evs != NORMAL) return evalStatusReturn(evs); if(!doUnaryOperation(1,slots)) return evalStatusReturn(ERROR); evalNodeEpilog(); return NORMAL; } //eval
UTI NodeUnaryOp::constantFold() { u64 val = U64_MAX; UTI nuti = getNodeType(); if(nuti == Nav) return Nav; //nothing to do yet //if(nuti == Hzy) return Hzy; //nothing to do yet TRY? // if here, must be a constant.. assert(isAConstant()); NNO pno = Node::getYourParentNo(); assert(pno); Node * parentNode = m_state.findNodeNoInThisClassForParent(pno); //t3767 assert(parentNode); evalNodeProlog(0); //new current frame pointer makeRoomForNodeType(nuti); //offset a constant expression EvalStatus evs = eval(); if( evs == NORMAL) { UlamValue cnstUV = m_state.m_nodeEvalStack.popArg(); u32 wordsize = m_state.getTotalWordSize(nuti); if(wordsize <= MAXBITSPERINT) val = cnstUV.getImmediateData(m_state); else if(wordsize <= MAXBITSPERLONG) val = cnstUV.getImmediateDataLong(m_state); else m_state.abortGreaterThanMaxBitsPerLong(); } evalNodeEpilog(); if(evs == ERROR) { std::ostringstream msg; msg << "Constant value expression for unary op" << getName(); msg << " is erroneous while compiling class: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); setNodeType(Nav); return Nav; } if(evs == NOTREADY) { std::ostringstream msg; msg << "Constant value expression for unary op" << getName(); msg << " is not yet ready while compiling class: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT); setNodeType(Hzy); m_state.setGoAgain(); //for compiler counts return Hzy; } //replace ourselves (and kids) with a node terminal; new NNO unlike template's NodeTerminal * newnode = new NodeTerminal(val, nuti, m_state); assert(newnode); newnode->setNodeLocation(getNodeLocation()); AssertBool swapOk = parentNode->exchangeKids(this, newnode); assert(swapOk); std::ostringstream msg; msg << "Exchanged kids! for unary " << getName(); msg << ", with a constant == " << newnode->getName(); msg << " while compiling class: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); newnode->setYourParentNo(pno); newnode->resetNodeNo(getNodeNo()); delete this; //suicide is painless.. return newnode->checkAndLabelType(); } //constantFold
EvalStatus NodeMemberSelect::eval() { assert(m_nodeLeft && m_nodeRight); UTI nuti = getNodeType(); if(nuti == Nav) return ERROR; if(nuti == Hzy) return NOTREADY; evalNodeProlog(0); //new current frame pointer on node eval stack UlamValue saveCurrentObjectPtr = m_state.m_currentObjPtr; //************* UlamValue saveCurrentSelfPtr = m_state.m_currentSelfPtr; //************* makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeLeft->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //UPDATE selected member (i.e. element or quark) before eval of rhs //(i.e. data member or func call); e.g. Ptr to atom UlamValue newCurrentObjectPtr = m_state.m_nodeEvalStack.loadUlamValuePtrFromSlot(1); UTI newobjtype = newCurrentObjectPtr.getUlamValueTypeIdx(); if(!m_state.isPtr(newobjtype)) { assert(m_nodeLeft->isFunctionCall()); //must be the result of a function call // copy anonymous class to "uc" hidden slot in STACK, then replace with a pointer to it. assert(m_state.isAClass(newobjtype)); newCurrentObjectPtr = assignAnonymousClassReturnValueToStack(newCurrentObjectPtr); //t3912 } u32 superid = m_state.m_pool.getIndexForDataString("super"); if(newCurrentObjectPtr.getPtrNameId() == superid) { if(!m_nodeRight->isFunctionCall()) newCurrentObjectPtr = m_state.m_currentSelfPtr; //(t3749) else m_state.m_currentSelfPtr = newCurrentObjectPtr; //changes self ********* (t3743, t3745) } m_state.m_currentObjPtr = newCurrentObjectPtr; //UTI ruti = m_nodeRight->getNodeType(); //u32 slot = makeRoomForNodeType(ruti); u32 slot = makeRoomForNodeType(nuti); evs = m_nodeRight->eval(); //a Node Function Call here, or data member eval if(evs != NORMAL) { evalNodeEpilog(); return evs; } //assigns rhs to lhs UV pointer (handles arrays); //also copy result UV to stack, -1 relative to current frame pointer if(slot) //avoid Void's if(!doBinaryOperation(1, 1+slot, slot)) evs = ERROR; m_state.m_currentObjPtr = saveCurrentObjectPtr; //restore current object ptr m_state.m_currentSelfPtr = saveCurrentSelfPtr; //restore current self ptr evalNodeEpilog(); return evs; } //eval
EvalStatus NodeCast::eval() { assert(m_node); //has to be UTI tobeType = getNodeType(); UTI nodeType = m_node->getNodeType(); //uv.getUlamValueType() if(tobeType == Nav) return ERROR; evalNodeProlog(0); //new current frame pointer makeRoomForNodeType(nodeType); EvalStatus evs = m_node->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //do we believe these to be scalars, only? //possibly an array that needs to be casted, per elenemt if(m_state.isScalar(tobeType)) { if(!m_state.isScalar(nodeType)) { std::ostringstream msg; msg << "Cannot cast an array "; msg << m_state.getUlamTypeNameBriefByIndex(nodeType).c_str(); msg << " to a scalar type " ; msg << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } } else { //both arrays the same dimensions if(m_state.getArraySize(tobeType) != m_state.getArraySize(nodeType)) { MSG(getNodeLocationAsString().c_str(), "Considering implementing array casts!!!", ERR); } } UlamValue uv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(1); if(nodeType != tobeType) { if(!(m_state.getUlamTypeByIndex(tobeType)->cast(uv, tobeType))) { std::ostringstream msg; msg << "Cast problem during eval! Value type "; msg << m_state.getUlamTypeNameBriefByIndex(uv.getUlamValueTypeIdx()).c_str(); msg << " failed to be cast as "; msg << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evalNodeEpilog(); return ERROR; } } //also copy result UV to stack, -1 relative to current frame pointer assignReturnValueToStack(uv); evalNodeEpilog(); return NORMAL; } //eval
EvalStatus NodeSquareBracket::evalToStoreInto() { assert(m_nodeLeft && m_nodeRight); UTI nuti = getNodeType(); if(nuti == Nav) return ERROR; evalNodeProlog(0); //new current frame pointer makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeLeft->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue pluv = m_state.m_nodeEvalStack.popArg(); makeRoomForNodeType(m_nodeRight->getNodeType()); //offset a constant expression evs = m_nodeRight->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue offset = m_state.m_nodeEvalStack.popArg(); // constant expression only required for array declaration u32 offsetdata = offset.getImmediateData(m_state); s32 offsetInt = m_state.getUlamTypeByIndex(offset.getUlamValueTypeIdx())->getDataAsCs32(offsetdata); UTI auti = pluv.getPtrTargetType(); UlamType * aut = m_state.getUlamTypeByIndex(auti); if(aut->isCustomArray()) { UTI caType = ((UlamTypeClass *) aut)->getCustomArrayType(); UlamType * caut = m_state.getUlamTypeByIndex(caType); u32 pos = pluv.getPtrPos(); if(caut->getBitSize() > MAXBITSPERINT) pos = 0; // itemUV = UlamValue::makeAtom(caType); //else // itemUV = UlamValue::makeImmediate(caType, 0, m_state); //quietly skip for now XXX //use CA type, not the left ident's type UlamValue scalarPtr = UlamValue::makePtr(pluv.getPtrSlotIndex(), pluv.getPtrStorage(), caType, m_state.determinePackable(caType), //PACKEDLOADABLE m_state, pos /* base pos of array */ ); //copy result UV to stack, -1 relative to current frame pointer assignReturnValuePtrToStack(scalarPtr); } else { //adjust pos by offset * len, according to its scalar type UlamValue scalarPtr = UlamValue::makeScalarPtr(pluv, m_state); if(scalarPtr.incrementPtr(m_state, offsetInt)) //copy result UV to stack, -1 relative to current frame pointer assignReturnValuePtrToStack(scalarPtr); else { s32 arraysize = m_state.getArraySize(pluv.getPtrTargetType()); Symbol * lsymptr; u32 lid = 0; if(getSymbolPtr(lsymptr)) lid = lsymptr->getId(); std::ostringstream msg; msg << "Array subscript [" << offsetInt << "] exceeds the size (" << arraysize; msg << ") of array '" << m_state.m_pool.getDataAsString(lid).c_str() << "'"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evs = ERROR; } } evalNodeEpilog(); return evs; } //evalToStoreInto
EvalStatus NodeSquareBracket::eval() { assert(m_nodeLeft && m_nodeRight); UTI nuti = getNodeType(); if(nuti == Nav) return ERROR; evalNodeProlog(0); //new current frame pointer makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeLeft->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue pluv = m_state.m_nodeEvalStack.popArg(); UTI ltype = pluv.getPtrTargetType(); //could be a custom array which is a scalar quark. already checked. UlamType * lut = m_state.getUlamTypeByIndex(ltype); bool isCustomArray = lut->isCustomArray(); assert(!m_state.isScalar(ltype) || isCustomArray); //already checked, must be array makeRoomForNodeType(m_nodeRight->getNodeType()); //offset a constant expression evs = m_nodeRight->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue offset = m_state.m_nodeEvalStack.popArg(); UlamType * offut = m_state.getUlamTypeByIndex(offset.getUlamValueTypeIdx()); s32 offsetInt = 0; if(offut->isNumericType()) { // constant expression only required for array declaration s32 arraysize = m_state.getArraySize(ltype); u32 offsetdata = offset.getImmediateData(m_state); offsetInt = offut->getDataAsCs32(offsetdata); if((offsetInt >= arraysize) && !isCustomArray) { Symbol * lsymptr; u32 lid = 0; if(getSymbolPtr(lsymptr)) lid = lsymptr->getId(); std::ostringstream msg; msg << "Array subscript [" << offsetInt << "] exceeds the size (" << arraysize; msg << ") of array '" << m_state.m_pool.getDataAsString(lid).c_str() << "'"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evalNodeEpilog(); return ERROR; } } else if(!isCustomArray) { Symbol * lsymptr; u32 lid = 0; if(getSymbolPtr(lsymptr)) lid = lsymptr->getId(); std::ostringstream msg; msg << "Array subscript of array '"; msg << m_state.m_pool.getDataAsString(lid).c_str(); msg << "' requires a numeric type"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evalNodeEpilog(); return ERROR; } assignReturnValueToStack(pluv.getValAt(offsetInt, m_state)); evalNodeEpilog(); return NORMAL; } //eval