// replaced by NodeVarDecl:genCode to leverage the declaration order preserved by the parse tree. void SymbolVariableDataMember::generateCodedVariableDeclarations(File * fp, ULAMCLASSTYPE classtype) { UTI vuti = getUlamTypeIdx(); UlamType * vut = m_state.getUlamTypeByIndex(vuti); ULAMCLASSTYPE vclasstype = vut->getUlamClass(); m_state.indent(fp); fp->write(vut->getUlamTypeMangledName().c_str()); //for C++ if(vclasstype == UC_QUARK) // called on classtype elements only { fp->write("<"); fp->write_decimal(getPosOffset()); fp->write(">"); } fp->write(" "); fp->write(getMangledName().c_str()); #if 0 s32 arraysize = vut->getArraySize(); if(arraysize > NONARRAYSIZE) { fp->write("["); fp->write_decimal(arraysize); fp->write("]"); } else if(arraysize == UNKNOWNSIZE) { fp->write("[UNKNOWN]"); } #endif fp->write(";\n"); } //generateCodedVariableDeclarations
//atomic parameter type, not model parameter. const std::string Symbol::getMangledNameForParameterType() { assert(!isModelParameter()); UlamType * sut = m_state.getUlamTypeByIndex(getUlamTypeIdx()); ULAMCLASSTYPE classtype = sut->getUlamClass(); //another way, like this? if(isModelParameter()) { std::ostringstream epmangled; epmangled << sut->getImmediateModelParameterStorageTypeAsString(); //if(classtype == UC_QUARK) // epmangled << "::Us"; assert(classtype == UC_NOTACLASS); return epmangled.str(); } // to distinguish btn an atomic parameter typedef and quark typedef; // use atomic parameter with array of classes bool isaclass = (( classtype == UC_QUARK || classtype == UC_ELEMENT || classtype == UC_UNSEEN) && sut->isScalar()); std::ostringstream pmangled; pmangled << Symbol::getParameterTypePrefix(isaclass).c_str() << getMangledName(); return pmangled.str(); } //getMangledNameForParameterType
UTI NodeCast::checkAndLabelType() { // unlike the other nodes, nodecast knows its type at construction time; // this is for checking for errors, before eval happens. u32 errorsFound = 0; UTI tobeType = getNodeType(); UTI nodeType = isExplicitCast() ? m_node->checkAndLabelType() : m_node->getNodeType(); //user cast if explicit if(m_nodeTypeDesc) { //might be a mapped uti for instantiated template class tobeType = m_nodeTypeDesc->checkAndLabelType(); setNodeType(tobeType); //overrides type set at parse time if(!m_nodeTypeDesc->isReadyType()) { std::ostringstream msg; msg << "Cannot cast to nonready type: " ; msg << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); msg << " (UTI" << tobeType << ")"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); errorsFound++; } } UlamType * tobe = m_state.getUlamTypeByIndex(tobeType); if(!m_state.isComplete(tobeType)) { std::ostringstream msg; msg << "Cannot cast to incomplete type: " ; msg << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); msg << " (UTI" << tobeType << ")"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); errorsFound++; } else if(tobeType == Nav) { std::ostringstream msg; msg << "Cannot cast " << m_state.getUlamTypeNameBriefByIndex(nodeType).c_str(); msg << " to not-a-valid type"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); errorsFound++; } else if(tobe->getUlamClass() != UC_NOTACLASS && m_state.getUlamTypeByIndex(nodeType)->getUlamClass() == UC_NOTACLASS) { if(nodeType != UAtom) { std::ostringstream msg; msg << "Cannot cast "; msg << m_state.getUlamTypeNameBriefByIndex(nodeType).c_str(); msg << " to " << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); errorsFound++; } } else if(isExplicitCast()) { FORECAST scr = tobe->explicitlyCastable(nodeType); if(scr != CAST_CLEAR) { std::ostringstream msg; msg << "Cannot explicitly cast "; msg << m_state.getUlamTypeNameBriefByIndex(nodeType).c_str(); msg << " to type: " << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); if(tobe->getUlamTypeEnum() == Bool) msg << "; Consider using a comparison operator"; if(scr == CAST_HAZY) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); errorsFound++; } } if(errorsFound == 0) //else { if(!m_state.isScalar(tobeType)) { MSG(getNodeLocationAsString().c_str(), "Array casts currently not supported", ERR); errorsFound++; if(m_state.isScalar(nodeType)) { MSG(getNodeLocationAsString().c_str(), "Consider implementing array casts: Cannot cast scalar into array", ERR); errorsFound++; } else if(m_state.getArraySize(tobeType) != m_state.getArraySize(nodeType)) { MSG(getNodeLocationAsString().c_str(), "Consider implementing array casts: Array sizes differ", ERR); errorsFound++; } } else { //to be scalar type if(!m_state.isScalar(nodeType)) { MSG(getNodeLocationAsString().c_str(), "Consider implementing array casts: Cannot cast array into scalar", ERR); errorsFound++; } } // end not scalar errors // needs commandline arg..lots of non-explicit warning. // reserve for user requested casts; ////if(isExplicitCast()) //Node::warnOfNarrowingCast(nodeType, tobeType); } // special case: user casting a quark to an Int; if(errorsFound == 0) { ULAMCLASSTYPE nodeClass = m_state.getUlamTypeByIndex(nodeType)->getUlamClass(); if(nodeClass == UC_QUARK) { if(!makeCastingNode(m_node, tobeType, m_node, isExplicitCast())) errorsFound++; } else { //classes are not surprisingly unknown bit sizes at this point if(nodeClass == UC_UNSEEN) { std::ostringstream msg; msg << "Cannot cast unseen class "; msg << m_state.getUlamTypeNameBriefByIndex(nodeType).c_str(); msg << " to " << m_state.getUlamTypeNameByIndex(tobeType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); errorsFound++; } } } if(errorsFound) return Nav; //inconsistent! but keeps cast type..makeCastingNode returns error return getNodeType(); } //checkAndLabelType
void NodeCast::genCodeCastAtomAndQuark(File * fp, UlamValue & uvpass) { UTI nuti = getNodeType(); //quark tobe UlamType * nut = m_state.getUlamTypeByIndex(nuti); UTI vuti = uvpass.getUlamValueTypeIdx(); if(vuti == Ptr) vuti = uvpass.getPtrTargetType(); //replace m_node->genCodeToStoreInto(fp, uvpass); //No need to load lhs into tmp (T); symbol's in COS vector assert(!m_state.m_currentObjSymbolsForCodeGen.empty()); Symbol * stgcos = NULL; stgcos = m_state.m_currentObjSymbolsForCodeGen[0]; s32 tmpVarPos = m_state.getNextTmpVarNumber(); // "downcast" might not be true; compare to be sure the atom has a quark "Foo" // get signed pos if(vuti == UAtom) { m_state.indent(fp); fp->write("const s32 "); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str());; fp->write(" = "); //internal method, takes uc, u32 and const char*, returns s32 position fp->write(m_state.getHasMangledFunctionName(vuti)); fp->write("("); fp->write("uc, "); Node::genLocalMemberNameOfMethod(fp); //assume atom is a local var (neither dm nor ep) if(stgcos->isSelf()) fp->write("GetType(), "); //no read for self else fp->write("read().GetType(), "); fp->write("\""); fp->write(nut->getUlamTypeMangledName().c_str()); fp->write("\");\n"); //keeping pos in tmp } else { UlamType* vut = m_state.getUlamTypeByIndex(vuti); if(vut->getUlamClass() == UC_ELEMENT) { m_state.indent(fp); fp->write("const s32 "); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str());; fp->write(" = "); //internal method, takes uc, u32 and const char*, returns s32 position fp->write(vut->getUlamTypeMangledName().c_str()); fp->write("<EC>::"); fp->write(m_state.getHasMangledFunctionName(vuti)); fp->write("(\""); fp->write(nut->getUlamTypeMangledName().c_str()); fp->write("\");\n"); //keeping pos in tmp } else { //e.g. a quark here would be wrong std::ostringstream msg; msg << "Casting 'incomplete' types "; msg << m_state.getUlamTypeNameBriefByIndex(nuti).c_str(); msg << " to be "; msg << m_state.getUlamTypeNameBriefByIndex(vuti).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); assert(0);//return; } } m_state.indent(fp); fp->write("if("); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str()); fp->write(" < 0)\n"); m_state.m_currentIndentLevel++; m_state.indent(fp); fp->write("FAIL(BAD_CAST);\n\n"); m_state.m_currentIndentLevel--; //informed by genCodedAutoLocal() in NodeVarDecl used for conditional-as // uses stgcos since there's no m_varSymbol in this situation. s32 tmpVarStg = m_state.getNextTmpVarNumber(); UTI stguti = stgcos->getUlamTypeIdx(); UlamType * stgut = m_state.getUlamTypeByIndex(stguti); assert(stguti == UAtom || stgut->getUlamClass() == UC_ELEMENT); // can't let Node::genCodeReadIntoTmpVar do this for us (we need a ref!): assert(m_state.m_currentObjSymbolsForCodeGen.size() == 1); m_state.indent(fp); // no const here fp->write(stgut->getTmpStorageTypeAsString().c_str()); fp->write("& "); fp->write(m_state.getTmpVarAsString(stguti, tmpVarStg, TMPBITVAL).c_str()); fp->write(" = "); fp->write(stgcos->getMangledName().c_str()); if(!stgcos->isSelf()) fp->write(".getRef()"); fp->write("; //ref needed\n"); // now we have our pos in tmpVarPos, and our T in tmpVarStg // time to (like a) "shadow 'self'" with auto local variable: m_state.indent(fp); fp->write(nut->getUlamTypeImmediateAutoMangledName().c_str()); //for C++ local vars, ie non-data members fp->write("<EC> "); s32 tmpIQ = m_state.getNextTmpVarNumber(); //tmp since no variable name fp->write(m_state.getTmpVarAsString(nuti, tmpIQ).c_str()); fp->write("("); fp->write(m_state.getTmpVarAsString(stguti, tmpVarStg, TMPBITVAL).c_str()); //for known quark: fp->write(", "); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str()); fp->write(");\n"); //like, shadow lhs of as //update the uvpass to have the casted immediate quark uvpass = UlamValue::makePtr(tmpIQ, uvpass.getPtrStorage(), nuti, m_state.determinePackable(nuti), m_state, 0); //POS 0 rightjustified; m_state.m_currentObjSymbolsForCodeGen.clear(); //clear remnant of lhs } //genCodeCastAtomAndQuark
void NodeCast::genCodeReadIntoATmpVar(File * fp, UlamValue& uvpass) { // e.g. called by NodeFunctionCall on a NodeTerminal.. if(!needsACast()) { return m_node->genCodeReadIntoATmpVar(fp, uvpass); } UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); UTI vuti = uvpass.getUlamValueTypeIdx(); bool isTerminal = false; s32 tmpVarNum = 0; if(vuti == Ptr) { tmpVarNum = uvpass.getPtrSlotIndex(); vuti = uvpass.getPtrTargetType(); //replace } else { // an immediate terminal value isTerminal = true; } if(nuti == vuti) return; //nothing to do! UlamType * vut = m_state.getUlamTypeByIndex(vuti); //after vuti replacement ULAMCLASSTYPE nclasstype = nut->getUlamClass(); ULAMCLASSTYPE vclasstype = vut->getUlamClass(); //handle element-atom and atom-element casting differently: // handle element->quark, atom->quark, not quark->element or quark->atom if(nuti == UAtom || vuti == UAtom || vclasstype == UC_ELEMENT || vclasstype == UC_QUARK) { //only to be nclasstype quark makes sense!!! check first, one might be element if(nclasstype == UC_QUARK || vclasstype == UC_QUARK) return genCodeCastAtomAndQuark(fp, uvpass); if(nclasstype == UC_ELEMENT || vclasstype == UC_ELEMENT) return genCodeCastAtomAndElement(fp, uvpass); { std::ostringstream msg; msg << "Casting 'incomplete' types: "; msg << m_state.getUlamTypeNameByIndex(nuti).c_str(); msg << "(UTI" << nuti << ") to be " << m_state.getUlamTypeNameByIndex(vuti).c_str(); msg << "(UTI" << vuti << ")"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); return; } } s32 tmpVarCastNum = m_state.getNextTmpVarNumber(); m_state.indent(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64, etc. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarCastNum).c_str()); fp->write(" = "); // write the cast method (e.g. _Unsigned32ToInt32, _Int32ToUnary32, etc..) fp->write(nut->castMethodForCodeGen(vuti).c_str()); fp->write("("); if(isTerminal) { s32 len = m_state.getBitSize(vuti); assert(len != UNKNOWNSIZE); if(len <= MAXBITSPERINT) { u32 data = uvpass.getImmediateData(m_state); char dstr[40]; vut->getDataAsString(data, dstr, 'z'); fp->write(dstr); } else if(len <= MAXBITSPERLONG) { u64 data = uvpass.getImmediateDataLong(m_state); char dstr[70]; vut->getDataLongAsString(data, dstr, 'z'); fp->write(dstr); } else assert(0); } else { fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum).c_str()); } fp->write(", "); assert(!(nuti == UAtom || vuti == UAtom)); //LENGTH of node being casted (Uh_AP_mi::LENGTH ?) //fp->write(m_state.getBitVectorLengthAsStringForCodeGen(nodetype).c_str()); fp->write_decimal(m_state.getTotalBitSize(vuti)); //src length fp->write(", "); fp->write_decimal(m_state.getTotalBitSize(nuti)); //tobe length fp->write(")"); fp->write(";\n"); //PROBLEM is that funccall checks for 0 nameid to use the tmp var! // but then if we don't pass it along Node::genMemberNameForMethod fails.. if(isTerminal) uvpass = UlamValue::makePtr(tmpVarCastNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0); //POS 0 rightjustified. else uvpass = UlamValue::makePtr(tmpVarCastNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, uvpass.getPtrNameId()); //POS 0 rightjustified; pass along name id } //genCodeReadIntoTmp
// 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
// 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