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
// used to select an array element; not for declaration UTI NodeSquareBracket::checkAndLabelType() { assert(m_nodeLeft && m_nodeRight); u32 errorCount = 0; UTI newType = Nav; //init UTI idxuti = Nav; UTI leftType = m_nodeLeft->checkAndLabelType(); bool isCustomArray = false; //for example, f.chance[i] where i is local, same as f.func(i); NodeBlock * currBlock = m_state.getCurrentBlock(); m_state.pushCurrentBlockAndDontUseMemberBlock(currBlock); //currblock doesn't change UTI rightType = m_nodeRight->checkAndLabelType(); m_state.popClassContext(); if(leftType != Nav) { UlamType * lut = m_state.getUlamTypeByIndex(leftType); isCustomArray = lut->isCustomArray(); if(lut->isScalar()) { if(lut->isHolder()) { std::ostringstream msg; msg << "Incomplete Type: " << m_state.getUlamTypeNameBriefByIndex(leftType).c_str(); msg << " used with " << getName(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); errorCount++; } else if(!isCustomArray) { std::ostringstream msg; msg << "Invalid Type: " << m_state.getUlamTypeNameBriefByIndex(leftType).c_str(); msg << " used with " << getName(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); errorCount++; } else { //must be a custom array; t.f. lhs is a quark! assert(lut->getUlamClass() != UC_NOTACLASS); // can't substitute a function call node for square brackets to leverage // all the overload matching in func call node's c&l, because // we ([]) can't tell which side of = we are on, and whether we should // be a aref or aset. UTI caType = ((UlamTypeClass *) lut)->getCustomArrayType(); if(!m_state.isComplete(caType)) { std::ostringstream msg; msg << "Incomplete Custom Array Type: "; msg << m_state.getUlamTypeNameBriefByIndex(caType).c_str(); msg << " used with class: "; msg << m_state.getUlamTypeNameBriefByIndex(leftType).c_str(); msg << getName(); if(lut->isComplete()) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); newType = Nav; //error! errorCount++; } } //set up idxuti..RHS //cant proceed with custom array subscript if lhs is incomplete if(errorCount == 0) { if(isCustomArray) { bool hasHazyArgs = false; u32 camatches = ((UlamTypeClass *) lut)->getCustomArrayIndexTypeFor(m_nodeRight, idxuti, hasHazyArgs); if(camatches == 0) { std::ostringstream msg; msg << "No defined custom array get function with"; msg << " matching argument type "; msg << m_state.getUlamTypeNameBriefByIndex(rightType).c_str(); msg << "; and cannot be called"; if(hasHazyArgs) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); idxuti = Nav; //error! errorCount++; } else if(camatches > 1) { std::ostringstream msg; msg << "Ambiguous matches (" << camatches; msg << ") of custom array get function for argument type "; msg << m_state.getUlamTypeNameBriefByIndex(rightType).c_str(); msg << "; Explicit casting required"; if(hasHazyArgs) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); idxuti = Nav; //error! errorCount++; } } else { //not custom array //must be some kind of numeric type: Int, Unsigned, or Unary..of any bit size if(rightType != Nav && !m_state.getUlamTypeByIndex(rightType)->isNumericType()) { std::ostringstream msg; msg << "Array item specifier requires numeric type: "; msg << m_state.getUlamTypeNameBriefByIndex(rightType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); idxuti = Nav; //error! errorCount++; } else idxuti = rightType; //default unless caarray } } //errorcount is zero } //lut is scalar if(idxuti != Nav && UlamType::compare(idxuti, rightType, m_state) == UTIC_NOTSAME) { if(m_nodeRight->safeToCastTo(idxuti) == CAST_CLEAR) { if(!makeCastingNode(m_nodeRight, idxuti, m_nodeRight)) { newType = Nav; //error! errorCount++; } } else { newType = Nav; //error! errorCount++; } } } //lt not nav if(errorCount == 0) { // sq bracket purpose in life is to account for array elements; if(isCustomArray) newType = ((UlamTypeClass *) m_state.getUlamTypeByIndex(leftType))->getCustomArrayType(); else newType = m_state.getUlamTypeAsScalar(leftType); // multi-dimensional possible; MP not ok lhs. setStoreIntoAble(m_nodeLeft->isStoreIntoAble()); } setNodeType(newType); return newType; } //checkAndLabelType
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