bool SymbolWithValue::getArrayValueAsString(std::string& vstr) { BV8K dval; bool oktoprint = getValueReadyToPrint(dval); if(!oktoprint) return false; UTI tuti = getUlamTypeIdx(); UlamType * tut = m_state.getUlamTypeByIndex(tuti); if(tut->getTotalBitSize() == 0) { vstr = "10"; //empty array return true; } //get the number of bits for this type into u64 // convert to a lex-number as a string, applying type specifics // return the completed string of all the array values in arg vstr. std::ostringstream tovstr; s32 bs = tut->getBitSize(); s32 arraysize = tut->getArraySize(); for(s32 i=0; i < arraysize; i++) { u64 thisval = dval.ReadLong(i * bs, bs); //pos and len std::string str; convertValueToALexString(thisval, tuti, str, m_state); tovstr << str; } vstr = tovstr.str(); return true; } //getArrayValueAsString
void NodeUnaryOp::genCode(File * fp, UVPass& uvpass) { assert(m_node); m_node->genCode(fp, uvpass); UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); m_state.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(methodNameForCodeGen().c_str()); fp->write("("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(nut->getBitSize()); fp->write(");"); GCNL; uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, 0); //POS 0 rightjustified. } //genCode
bool SymbolWithValue::convertValueToANonPrettyString(u64 varg, UTI tuti, std::string& vstr, CompilerState & state) { std::ostringstream ostr; UlamType * tut = state.getUlamTypeByIndex(tuti); s32 bs = tut->getBitSize(); ULAMTYPE etyp = tut->getUlamTypeEnum(); switch(etyp) { case Int: { if(bs <= MAXBITSPERINT) { s32 sval = _Int32ToInt32((u32) varg, bs, MAXBITSPERINT); ostr << sval; } else if(bs <= MAXBITSPERLONG) { s64 sval = _Int64ToInt64(varg, bs, MAXBITSPERLONG); ostr << sval; } else state.abortGreaterThanMaxBitsPerLong(); } break; case Unsigned: { if( bs <= MAXBITSPERINT) ostr << (u32) varg << "u"; else if( bs <= MAXBITSPERLONG) ostr << varg << "u"; else state.abortGreaterThanMaxBitsPerLong(); } break; case Unary: case Bool: case Bits: case Class: { ostr << "0x" << std::hex << varg; } break; case String: { std::string fstr = state.getDataAsUnFormattedUserString((u32) varg); u32 flen = fstr.length() - 1; //exclude null terminator for(u32 i = 0; i < flen; i++) ostr << std::hex << std::setfill('0') << std::setw(2) << (u32) fstr[i]; } break; default: state.abortUndefinedUlamType(); }; vstr = ostr.str(); return true; } //convertValueToANonPrettyString (static helper)
void NodeBinaryOpEqualShift::genCode(File * fp, UVPass& uvpass) { assert(m_nodeLeft && m_nodeRight); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); // generate rhs first; may update current object globals (e.g. function call) UVPass ruvpass; m_nodeRight->genCode(fp, ruvpass); // restore current object globals assert(m_state.m_currentObjSymbolsForCodeGen.empty()); // lhs should be the new current object: node member select updates them, // but a plain NodeIdent does not!!! because genCodeToStoreInto has been repurposed // to mean "don't read into a TmpVar" (e.g. by NodeCast). UVPass luvpass; m_nodeLeft->genCodeToStoreInto(fp, luvpass); //may update m_currentObjSymbol //wiped out by left read; need to write back into left std::vector<Symbol *> saveCOSVector = m_state.m_currentObjSymbolsForCodeGen; uvpass = luvpass; //keep luvpass slot untouched Node::genCodeReadIntoATmpVar(fp, uvpass); m_state.m_currentObjSymbolsForCodeGen = saveCOSVector; //restore vector after lhs read************* UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); m_state.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(methodNameForCodeGen().c_str()); fp->write("("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write(ruvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(nut->getBitSize()); fp->write(");"); GCNL; uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, uvpass.getPassPos(), uvpass.getPassNameId()); //P // current object globals should pertain to lhs for the write genCodeWriteFromATmpVar(fp, luvpass, uvpass); //uses rhs' tmpvar; orig lhs assert(m_state.m_currentObjSymbolsForCodeGen.empty()); } //genCode
bool SymbolWithValue::getArrayItemValue(u32 item, u64& rtnitem) { if(isReady()) { UTI suti = getUlamTypeIdx(); UlamType * sut = m_state.getUlamTypeByIndex(suti); u32 bs = sut->getBitSize(); s32 arrsize = sut->getArraySize(); assert(bs <= MAXBITSPERLONG); assert((arrsize >= 0) && (item < (u32) arrsize)); //no casting! rtnitem = m_constantValue.ReadLong(item * bs, bs); return true; } return false; }
bool SymbolWithValue::getArrayItemInitValue(u32 item, u32& rtnitem) { assert(hasInitValue()); if(isInitValueReady()) { UTI suti = getUlamTypeIdx(); UlamType * sut = m_state.getUlamTypeByIndex(suti); u32 bs = sut->getBitSize(); s32 arrsize = sut->getArraySize(); assert(bs <= MAXBITSPERINT); assert((arrsize >= 0) && (item < (u32) arrsize)); //no casting! rtnitem = m_initialValue.Read(item * bs, bs); return true; } return false; }
FORECAST UlamTypePrimitiveUnary::safeCast(UTI typidx) { FORECAST scr = UlamType::safeCast(typidx); if(scr != CAST_CLEAR) return scr; bool brtn = true; UlamType * vut = m_state.getUlamTypeByIndex(typidx); s32 valbitsize = vut->getBitSize(); s32 bitsize = getBitSize(); ULAMTYPE valtypEnum = vut->getUlamTypeEnum(); switch(valtypEnum) { case Unsigned: { u32 vwordsize = vut->getTotalWordSize(); if(vwordsize <= MAXBITSPERINT) brtn = ((u32) bitsize >= (u32) vut->getMax()); else brtn = ((u64) bitsize >= vut->getMax()); } break; case Unary: brtn = (bitsize >= valbitsize); break; case Int: case Bool: case Bits: case Void: case UAtom: case Class: brtn = false; break; default: m_state.abortUndefinedUlamType(); //std::cerr << "UlamTypePrimitiveUnary (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; return brtn ? CAST_CLEAR : CAST_BAD; } //safeCast
//short-circuit when lhs is true void NodeBinaryOpLogicalOr::genCode(File * fp, UVPass& uvpass) { assert(m_nodeLeft && m_nodeRight); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* //initialize node result to false UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); m_state.indentUlamCode(fp); //fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = false;"); GCNL; //process lhs first UVPass luvpass; m_nodeLeft->genCode(fp, luvpass); //updates m_currentObjSymbol UTI luti = luvpass.getPassTargetType(); UlamType * lut = m_state.getUlamTypeByIndex(luti); assert(lut->getUlamTypeEnum() == Bool); //fp->write("\n"); m_state.indentUlamCode(fp); fp->write("if(!"); //lhs is false fp->write(((UlamTypePrimitiveBool *) lut)->getConvertToCboolMethod().c_str()); fp->write("("); fp->write(luvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(lut->getBitSize()); fp->write(")"); fp->write(")"); GCNL; m_state.indentUlamCode(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; UVPass ruvpass; m_nodeRight->genCode(fp, ruvpass); //set node's tmp var to whatever rhs value m_state.indentUlamCode(fp); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(ruvpass.getTmpVarAsString(m_state).c_str()); fp->write(";"); GCNL; m_state.m_currentIndentLevel--; m_state.indentUlamCode(fp); fp->write("}\n"); m_state.indentUlamCode(fp); fp->write("else\n"); m_state.indentUlamCode(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; //set node's tmp var to lhs value (true) m_state.indentUlamCode(fp); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(luvpass.getTmpVarAsString(m_state).c_str()); fp->write(";"); GCNL; m_state.m_currentIndentLevel--; m_state.indentUlamCode(fp); fp->write("}\n"); uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, 0); //P assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* } //genCode
bool SymbolWithValue::convertValueToALexString(u64 varg, UTI tuti, std::string& vstr, CompilerState & state) { //UTI tuti = getUlamTypeIdx(); UlamType * tut = state.getUlamTypeByIndex(tuti); s32 bs = tut->getBitSize(); ULAMTYPE etyp = tut->getUlamTypeEnum(); switch(etyp) { case Int: { if(bs <= MAXBITSPERINT) { s32 sval = _Int32ToInt32((u32) varg, bs, MAXBITSPERINT); vstr = ToLeximitedNumber(sval); } else if(bs <= MAXBITSPERLONG) { s64 sval = _Int64ToInt64(varg, bs, MAXBITSPERLONG); vstr = ToLeximitedNumber64(sval); } else state.abortGreaterThanMaxBitsPerLong(); } break; case Bool: { bool bval = _Bool64ToCbool(varg, bs); if(bval) vstr = ToLeximitedNumber(1); //true else vstr = ToLeximitedNumber(0); //false } break; case Unary: { s32 pval = _Unary64ToInt64(varg, bs, MAXBITSPERINT); vstr = ToLeximitedNumber(pval); } break; case Unsigned: case Bits: { if( bs <= MAXBITSPERINT) vstr = ToLeximitedNumber((u32) varg); else if( bs <= MAXBITSPERLONG) vstr = ToLeximitedNumber64(varg); else state.abortGreaterThanMaxBitsPerLong(); } break; case String: { std::ostringstream fhex; std::string fstr = state.getDataAsUnFormattedUserString((u32) varg); u32 flen = fstr.length() - 1; //exclude null terminator for(u32 i = 0; i < flen; i++) fhex << std::hex << std::setfill('0') << std::setw(2) << (u32) fstr[i]; vstr = fhex.str(); } break; default: state.abortUndefinedUlamPrimitiveType(); }; return true; } //convertValueToLexString (static helper)
void SymbolWithValue::printPostfixValueScalar(File * fp) { u64 val = 0; bool oktoprint = getValueReadyToPrint(val); if(oktoprint) { UTI tuti = getUlamTypeIdx(); UlamType * tut = m_state.getUlamTypeByIndex(tuti); u32 twordsize = tut->getTotalWordSize(); //must be commplete s32 tbs = tut->getBitSize(); ULAMTYPE etyp = tut->getUlamTypeEnum(); switch(etyp) { case Int: { if(twordsize <= MAXBITSPERINT) { s32 sval = _Int32ToCs32((u32) val, tbs); fp->write_decimal(sval); } else if(twordsize <= MAXBITSPERLONG) { s64 sval = _Int64ToCs64(val, tbs); fp->write_decimal_long(sval); } else m_state.abortGreaterThanMaxBitsPerLong(); } break; case Bool: { bool bval = _Bool64ToCbool(val, tbs); if(bval) fp->write("true"); else fp->write("false"); } break; case Unary: case Unsigned: case Bits: { // NO CASTING NEEDED, assume saved in its ulam-native format if( tbs <= MAXBITSPERINT) fp->write_decimal_unsigned(val); else if( tbs <= MAXBITSPERLONG) fp->write_decimal_unsignedlong(val); else m_state.abortGreaterThanMaxBitsPerLong(); //TBD > 64 fp->write("u"); } break; case String: // scalar strings generate comments (output value rather than index) e.g. t3951,2 fp->write(m_state.getDataAsFormattedUserString(val).c_str()); break; default: m_state.abortUndefinedUlamPrimitiveType(); }; } else fp->write("NONREADYCONST"); } //printPostfixValueScalar
// replaces NodeVarDecl:printPostfix to learn the values of Class' storage in center site void SymbolVariableDataMember::printPostfixValuesOfVariableDeclarations(File * fp, s32 slot, u32 startpos, ULAMCLASSTYPE classtype) { UTI vuti = getUlamTypeIdx(); UlamKeyTypeSignature vkey = m_state.getUlamKeyTypeSignatureByIndex(vuti); UlamType * vut = m_state.getUlamTypeByIndex(vuti); ULAMCLASSTYPE vclasstype = vut->getUlamClassType(); ULAMTYPE vetyp = vut->getUlamTypeEnum(); fp->write(" "); if(vclasstype == UC_NOTACLASS) fp->write(vkey.getUlamKeyTypeSignatureNameAndBitSize(&m_state).c_str()); else fp->write(vut->getUlamTypeNameBrief().c_str()); fp->write(" "); fp->write(m_state.m_pool.getDataAsString(getId()).c_str()); s32 arraysize = m_state.getArraySize(vuti); //scalar has 'size=1'; empty array [0] is still '0'. s32 size = (arraysize > NONARRAYSIZE ? arraysize : 1); //output the arraysize (optional), and open paren if(arraysize > NONARRAYSIZE) { fp->write("["); fp->write_decimal(arraysize); fp->write("]"); } else if(arraysize == UNKNOWNSIZE) { fp->write("[UNKNOWN]"); } fp->write("("); if(vclasstype == UC_QUARK) { //outputs the data members, not just the lump value (e.g. SWV::printPostfixValue()) UTI scalarquark = m_state.getUlamTypeAsScalar(vuti); //printPostfixValuesForClass: SymbolClass * csym = NULL; AssertBool isDefined = m_state.alreadyDefinedSymbolClass(scalarquark, csym); assert(isDefined); NodeBlockClass * classNode = csym->getClassBlockNode(); assert(classNode); u32 newstartpos = startpos + getPosOffset(); s32 len = vut->getBitSize(); for(s32 i = 0; i < size; i++) classNode->printPostfixDataMembersSymbols(fp, slot, newstartpos + len * i, vclasstype); } else { PACKFIT packFit = m_state.determinePackable(vuti); assert(WritePacked(packFit)); //has to be to fit in an atom/site; char * valstr = new char[size * 8 + MAXBITSPERLONG]; //was 32 if(size > 0) { //build the string of values (for both scalar and packed array) UlamValue arrayPtr = UlamValue::makePtr(slot, EVENTWINDOW, vuti, packFit, m_state, startpos + getPosOffset(), getId()); UlamValue nextPtr = UlamValue::makeScalarPtr(arrayPtr, m_state); UlamValue atval = m_state.getPtrTarget(nextPtr); s32 len = m_state.getBitSize(vuti); if(len == UNKNOWNSIZE) { sprintf(valstr,"unknown"); for(s32 i = 1; i < size; i++) { strcat(valstr,", unknown"); } } else if(len <= MAXBITSPERINT) { u32 data = atval.getDataFromAtom(nextPtr, m_state); vut->getDataAsString(data, valstr, 'z'); //'z' -> no preceeding ',' if(vetyp == Unsigned || vetyp == Unary) strcat(valstr, "u"); for(s32 i = 1; i < size; i++) { char tmpstr[8]; AssertBool isNext = nextPtr.incrementPtr(m_state); assert(isNext); atval = m_state.getPtrTarget(nextPtr); data = atval.getDataFromAtom(nextPtr, m_state); vut->getDataAsString(data, tmpstr, ','); if(vetyp == Unsigned || vetyp == Unary) strcat(tmpstr, "u"); strcat(valstr,tmpstr); } } else if(len <= MAXBITSPERLONG) { u64 data = atval.getDataLongFromAtom(nextPtr, m_state); vut->getDataLongAsString(data, valstr, 'z'); //'z' -> no preceeding ',' if(vetyp == Unsigned || vetyp == Unary) strcat(valstr, "u"); for(s32 i = 1; i < size; i++) { char tmpstr[8]; AssertBool isNext = nextPtr.incrementPtr(m_state); assert(isNext); atval = m_state.getPtrTarget(nextPtr); data = atval.getDataLongFromAtom(nextPtr, m_state); vut->getDataLongAsString(data, tmpstr, ','); if(vetyp == Unsigned || vetyp == Unary) strcat(tmpstr, "u"); strcat(valstr,tmpstr); } } else assert(0); } //end arrays > 0, and scalar else { sprintf(valstr," "); } fp->write(valstr); //results out here! delete [] valstr; } //not a quark fp->write("); "); } //printPostfixValuesOfVariableDeclarations
// replaces NodeVarDecl:printPostfix to learn the values of Class' storage in center site void SymbolVariableDataMember::printPostfixValuesOfVariableDeclarations(File * fp, s32 slot, u32 startpos, ULAMCLASSTYPE classtype) { UTI vuti = getUlamTypeIdx(); UlamKeyTypeSignature vkey = m_state.getUlamKeyTypeSignatureByIndex(vuti); UlamType * vut = m_state.getUlamTypeByIndex(vuti); ULAMCLASSTYPE vclasstype = vut->getUlamClass(); fp->write(" "); if(vclasstype == UC_NOTACLASS) fp->write(vkey.getUlamKeyTypeSignatureNameAndBitSize(&m_state).c_str()); else fp->write(vut->getUlamTypeNameBrief().c_str()); fp->write(" "); fp->write(m_state.m_pool.getDataAsString(getId()).c_str()); s32 arraysize = m_state.getArraySize(vuti); //scalar has 'size=1'; empty array [0] is still '0'. s32 size = (arraysize > NONARRAYSIZE ? arraysize : 1); //output the arraysize (optional), and open paren if(arraysize > NONARRAYSIZE) { fp->write("["); fp->write_decimal(arraysize); fp->write("]"); } else if(arraysize == UNKNOWNSIZE) { fp->write("[UNKNOWN]"); } fp->write("("); if(vclasstype == UC_QUARK) { //printPostfixValuesForClass: SymbolClass * csym = NULL; if(m_state.alreadyDefinedSymbolClass(vuti, csym)) { NodeBlockClass * classNode = csym->getClassBlockNode(); assert(classNode); SymbolTable * stptr = classNode->getSymbolTablePtr(); //ST of data members u32 newstartpos = startpos + getPosOffset(); s32 len = vut->getBitSize(); for(s32 i = 0; i < size; i++) stptr->printPostfixValuesForTableOfVariableDataMembers(fp, slot, newstartpos + len * i, vclasstype); } else { assert(0); //error! } } else { PACKFIT packFit = m_state.determinePackable(vuti); assert(WritePacked(packFit)); //has to be to fit in an atom/site; char * valstr = new char[size * 8 + MAXBITSPERLONG]; //was 32 if(size > 0) { //simplifying assumption for testing purposes: center site //Coord c0(0,0); //u32 slot = c0.convertCoordToIndex(); //build the string of values (for both scalar and packed array) UlamValue arrayPtr = UlamValue::makePtr(slot, EVENTWINDOW, vuti, packFit, m_state, startpos + getPosOffset(), getId()); UlamValue nextPtr = UlamValue::makeScalarPtr(arrayPtr, m_state); UlamValue atval = m_state.getPtrTarget(nextPtr); s32 len = nextPtr.getPtrLen(); assert(len != UNKNOWNSIZE); if(len <= MAXBITSPERINT) { u32 data = atval.getDataFromAtom(nextPtr, m_state); vut->getDataAsString(data, valstr, 'z'); //'z' -> no preceeding ',' for(s32 i = 1; i < size; i++) { char tmpstr[8]; assert(nextPtr.incrementPtr(m_state)); atval = m_state.getPtrTarget(nextPtr); data = atval.getDataFromAtom(nextPtr, m_state); vut->getDataAsString(data, tmpstr, ','); strcat(valstr,tmpstr); } } else if(len <= MAXBITSPERLONG) { u64 data = atval.getDataLongFromAtom(nextPtr, m_state); vut->getDataLongAsString(data, valstr, 'z'); //'z' -> no preceeding ',' for(s32 i = 1; i < size; i++) { char tmpstr[8]; assert(nextPtr.incrementPtr(m_state)); atval = m_state.getPtrTarget(nextPtr); data = atval.getDataLongFromAtom(nextPtr, m_state); vut->getDataLongAsString(data, tmpstr, ','); strcat(valstr,tmpstr); } } else assert(0); } //end arrays > 0, and scalar else { sprintf(valstr," "); } fp->write(valstr); //results out here! delete [] valstr; } //not a quark fp->write("); "); } //printPostfixValuesOfVariableDeclarations
void NodeControl::genCode(File * fp, UVPass& uvpass) { assert(m_nodeCondition && m_nodeBody); //bracket for overall tmpvars (e.g. condition and body) is // generated by the specific control; e.g. final bracket depends // on presence of 'else'. m_nodeCondition->genCode(fp, uvpass); bool isTerminal = (uvpass.getPassStorage() == TERMINAL); UTI cuti = uvpass.getPassTargetType(); UlamType * cut = m_state.getUlamTypeByIndex(cuti); m_state.indentUlamCode(fp); fp->write(getName()); //if, while fp->write("("); if(isTerminal) { fp->write(m_state.m_pool.getDataAsString(uvpass.getPassNameId()).c_str()); } else { if(m_state.m_genCodingConditionalHas) { assert(cut->getUlamTypeEnum() == Bool); fp->write(((UlamTypePrimitiveBool *) cut)->getConvertToCboolMethod().c_str()); fp->write("(("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(" >= 0 ? 1 : 0), "); //test for 'has' pos fp->write_decimal(cut->getBitSize()); fp->write(")"); } else { //regular condition assert(cut->getUlamTypeEnum() == Bool); fp->write(((UlamTypePrimitiveBool *) cut)->getConvertToCboolMethod().c_str()); fp->write("("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(cut->getBitSize()); fp->write(")"); } } fp->write(")"); GCNL; m_state.indentUlamCode(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; //note: in case of has-conditional, uvpass still has the tmpvariable containing the pos! m_nodeBody->genCode(fp, uvpass); //probably should have been done within the body, to avoid any //subsequent if/whiles from misinterpretting it as theirs; if so, again, moot. assert(!m_state.m_genCodingConditionalHas); m_state.m_currentIndentLevel--; m_state.indentUlamCode(fp); fp->write("} // end "); fp->write(getName()); //end fp->write("\n"); } //genCode
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