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