const std::string NodeBinaryOpEqualShift::methodNameForCodeGen() { std::ostringstream methodname; //methodname << "_Shift"; determined by each op UlamType * nut = m_state.getUlamTypeByIndex(getNodeType()); // common part of name ULAMTYPE etyp = nut->getUlamTypeEnum(); switch(etyp) { case Int: case Unsigned: case Bool: case Unary: case Bits: methodname << UlamType::getUlamTypeEnumAsString(etyp); break; default: m_state.abortUndefinedUlamPrimitiveType(); break; }; methodname << nut->getTotalWordSize(); return methodname.str(); } //methodNameForCodeGen
FORECAST UlamTypePrimitive::explicitlyCastable(UTI typidx) { FORECAST scr = UlamType::safeCast(typidx); //default if(scr == CAST_CLEAR) { // primitives must be the same sizes when casting to a reference type if(isReference() && !UlamType::checkReferenceCast(typidx)) scr = CAST_BAD; // strings cannot be cast explicitly to other primitive types, except Void (t3961) UlamType * vut = m_state.getUlamTypeByIndex(typidx); ULAMTYPE valtypEnum = vut->getUlamTypeEnum(); if((getUlamTypeEnum() != Void) && ((valtypEnum == String) ^ (getUlamTypeEnum() == String))) scr = CAST_BAD; //only quarks may be cast to Ints, explicitly or not; requires toInt method (t3996) if(valtypEnum == Class) { ULAMCLASSTYPE vclasstype = vut->getUlamClassType(); if(vclasstype != UC_QUARK) scr = CAST_BAD; } } return scr; } //explicitlyCastable
void NodeVarRef::printTypeAndName(File * fp) { UTI vuti = m_varSymbol->getUlamTypeIdx(); UlamKeyTypeSignature vkey = m_state.getUlamKeyTypeSignatureByIndex(vuti); UlamType * vut = m_state.getUlamTypeByIndex(vuti); if(m_state.isConstantRefType(vuti)) fp->write(" constant"); //t41242,3 fp->write(" "); if(vut->getUlamTypeEnum() != Class) { fp->write(vkey.getUlamKeyTypeSignatureNameAndBitSize(&m_state).c_str()); fp->write("&"); //<--the only difference!!! } else fp->write(vut->getUlamTypeClassNameBrief(vuti).c_str()); //includes any & fp->write(" "); fp->write(getName()); s32 arraysize = m_state.getArraySize(vuti); if(arraysize > NONARRAYSIZE) { fp->write("["); fp->write_decimal(arraysize); fp->write("]"); } else if(arraysize == UNKNOWNSIZE) { fp->write("[UNKNOWN]"); } } //printTypeAndName
UTI NodeBinaryOpEqualArith::checkAndLabelType() { UTI nodeType = NodeBinaryOpEqual::checkAndLabelType(); UlamType * nut = m_state.getUlamTypeByIndex(nodeType); // common part of name ULAMTYPE enodetyp = nut->getUlamTypeEnum(); if(enodetyp == Bits) { // can happen with op-equal operations when both sides are the same type MSG(getNodeLocationAsString().c_str(), "Arithmetic Operations are invalid on 'Bits' type", ERR); nodeType = Nav; } if(enodetyp == Bool) { // can happen with op-equal operations when both sides are the same type MSG(getNodeLocationAsString().c_str(), "Arithmetic Operations are invalid on 'Bool' type", ERR); nodeType = Nav; } if((nodeType != Nav) && !nut->isScalar()) { std::ostringstream msg; msg << "Non-scalars require a loop for operator" << getName(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); nodeType = Nav; } setNodeType(nodeType); return nodeType; } //checkAndLabelType
// replaces NodeTypedef:printPostfix to learn the values of Class' storage in center site void SymbolTypedef::printPostfixValuesOfVariableDeclarations(File * fp, s32 slot, u32 startpos, ULAMCLASSTYPE classtype) { UTI tuti = getUlamTypeIdx(); UlamKeyTypeSignature tkey = m_state.getUlamKeyTypeSignatureByIndex(tuti); UlamType * tut = m_state.getUlamTypeByIndex(tuti); fp->write(" typedef"); fp->write(" "); if(tut->getUlamTypeEnum() != Class) fp->write(tkey.getUlamKeyTypeSignatureNameAndBitSize(&m_state).c_str()); else fp->write(tut->getUlamTypeNameBrief().c_str()); fp->write(" "); fp->write(m_state.m_pool.getDataAsString(getId()).c_str()); s32 arraysize = m_state.getArraySize(tuti); if(arraysize > NONARRAYSIZE) { fp->write("["); fp->write_decimal(arraysize); fp->write("]"); } else if(arraysize == UNKNOWNSIZE) { fp->write("[UNKNOWN]"); } fp->write("; "); } //printPostfixValuesOfVariableDeclarations
const std::string NodeBinaryOpEqualArith::methodNameForCodeGen() { std::ostringstream methodname; //methodname << "_BitwiseOr"; determined by each op UlamType * nut = m_state.getUlamTypeByIndex(getNodeType()); // common part of name ULAMTYPE etyp = nut->getUlamTypeEnum(); switch(etyp) { case Int: case Unsigned: case Bool: case Unary: methodname << UlamType::getUlamTypeEnumAsString(etyp); break; case Bits: default: assert(0); methodname << "NAV"; break; }; methodname << nut->getTotalWordSize(); return methodname.str(); } //methodNameForCodeGen
const std::string NodeBinaryOpCompare::methodNameForCodeGen() { std::ostringstream methodname; //methodname << "_BitwiseOr"; determined by each op UlamType * lut = m_state.getUlamTypeByIndex(m_nodeLeft->getNodeType()); // common part of name ULAMTYPE etyp = lut->getUlamTypeEnum(); switch(etyp) { case Int: methodname << "Int"; break; case Unsigned: methodname << "Unsigned"; break; case Bits: methodname << "Bits"; break; case Bool: methodname << "Bool"; break; case String: methodname << "String"; break; default: m_state.abortUndefinedUlamPrimitiveType(); methodname << "NAV"; break; }; methodname << lut->getTotalWordSize(); return methodname.str(); } // methodNameForCodeGen
UTI NodeBinaryOpCompare::checkAndLabelType() { assert(m_nodeLeft && m_nodeRight); UTI leftType = m_nodeLeft->checkAndLabelType(); UTI rightType = m_nodeRight->checkAndLabelType(); UlamType * lut = m_state.getUlamTypeByIndex(leftType); if((lut->getUlamTypeEnum() == Class)) { Node * newnode = buildOperatorOverloadFuncCallNode(); if(newnode) { AssertBool swapOk = Node::exchangeNodeWithParent(newnode); assert(swapOk); m_nodeLeft = NULL; //recycle as memberselect m_nodeRight = NULL; //recycle as func call arg delete this; //suicide is painless.. return newnode->checkAndLabelType(); //t41109 } //else should fail again as non-primitive; } //done UTI newType = calcNodeType(leftType, rightType); //for casting if(m_state.isComplete(newType)) { u32 errCnt = 0; if(UlamType::compareForMakingCastingNode(rightType, newType, m_state) != UTIC_SAME) { if(!Node::makeCastingNode(m_nodeRight, newType, m_nodeRight)) errCnt++; } if(UlamType::compareForMakingCastingNode(leftType, newType, m_state) != UTIC_SAME) { if(!Node::makeCastingNode(m_nodeLeft, newType, m_nodeLeft)) errCnt++; } if(errCnt) newType = Nav; else newType = Bool; //always Bool (default size) for node; after castings! } setNodeType(newType); if(newType == Hzy) m_state.setGoAgain(); //nolonger needed in calcnodetypes Node::setStoreIntoAble(TBOOL_FALSE); //still may need casting (e.g. unary compared to an int) before constantfolding if((newType != Nav) && isAConstant() && m_nodeLeft->isReadyConstant() && m_nodeRight->isReadyConstant()) return NodeBinaryOp::constantFold(); return newType; } //checkAndLabelType
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)
UTI NodeControl::checkAndLabelType() { assert(m_nodeCondition && m_nodeBody); UTI newType = Bool; ULAMTYPE newEnumTyp = Bool; // condition should be a bool, safely cast UTI cuti = m_nodeCondition->checkAndLabelType(); if(m_state.okUTItoContinue(cuti) && m_state.isComplete(cuti)) { assert(m_state.isScalar(cuti)); UlamType * cut = m_state.getUlamTypeByIndex(cuti); ULAMTYPE ctypEnum = cut->getUlamTypeEnum(); if(ctypEnum != newEnumTyp) { if(checkSafeToCastTo(cuti, newType)) { if(!Node::makeCastingNode(m_nodeCondition, newType, m_nodeCondition)) newType = Nav; } //else not safe, newType changed } else { //caution: c&l called multiple times //always cast: Bools are maintained as unsigned in gen code, //until c-bool is needed if(cuti != newType) { if(checkSafeToCastTo(cuti, newType)) { if(!Node::makeCastingNode(m_nodeCondition, cuti, m_nodeCondition)) newType = Nav; else newType = cuti; } } } } else { newType = Hzy; //was = cuti; m_state.setGoAgain(); } m_nodeBody->checkAndLabelType(); //side-effect setNodeType(newType); //stays the same Node::setStoreIntoAble(TBOOL_FALSE); return getNodeType(); } //checkAndLabelType
FORECAST UlamTypeInt::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 = m_state.getBitSize(typidx); s32 bitsize = getBitSize(); ULAMTYPE valtypEnum = vut->getUlamTypeEnum(); switch(valtypEnum) { case Int: brtn = (bitsize >= valbitsize); break; case Unsigned: brtn = (bitsize > valbitsize); break; case Unary: brtn = (bitsize > (s32) _getLogBase2(valbitsize) + 1); break; case Bool: case Bits: case Void: case UAtom: brtn = false; break; case Class: { //must be Quark! treat as Int if it has a toInt method if(vut->isNumericType()) brtn = (bitsize >= MAXBITSPERINT); else { std::ostringstream msg; msg << "Class: "; msg << m_state.getUlamTypeNameBriefByIndex(typidx).c_str(); msg << " is not a numeric type and cannot be safely cast to an Int"; MSG(m_state.getFullLocationAsString(m_state.m_locOfNextLineText).c_str(),msg.str().c_str(), ERR); brtn = false; } } break; default: assert(0); //std::cerr << "UlamTypeInt (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; return brtn ? CAST_CLEAR : CAST_BAD; } //safeCast
UTI NodeBinaryOpArithRemainder::castThyselfToResultType(UTI rt, UTI lt, UTI newType) { UTI nuti = newType; //because the result bitsize for mod should be the right bitsize // create a cast! combining newType's base type and right resultbitsize. // could be the same, or "unsafe". if(m_state.okUTItoContinue(newType) && m_state.isComplete(newType)) { UlamType * newut = m_state.getUlamTypeByIndex(newType); ULAMTYPE typEnum = newut->getUlamTypeEnum(); u32 convertSize = m_state.getUlamTypeByIndex(rt)->bitsizeToConvertTypeTo(typEnum); u32 enumStrIdx = m_state.m_pool.getIndexForDataString(UlamType::getUlamTypeEnumAsString(typEnum)); UlamKeyTypeSignature tokey(enumStrIdx, convertSize, NONARRAYSIZE); ULAMCLASSTYPE newclasstype = newut->getUlamClassType(); nuti = m_state.makeUlamType(tokey, typEnum, newclasstype); if(UlamType::compareForMakingCastingNode(nuti, newType, m_state) != UTIC_SAME) //not same, or dontknow { NNO pno = Node::getYourParentNo(); //save assert(pno); //not using use makeCastingNode since don't want recursive c&l call Node * castNode = Node::newCastingNode(this, nuti); Node * parentNode = m_state.findNodeNoInThisClass(pno); if(!parentNode) { std::ostringstream msg; msg << "Remainder cast cannot be exchanged at this time while compiling class: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); msg << " Parent required"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); assert(0); //parent required } AssertBool swapOk = parentNode->exchangeKids(this, castNode); assert(swapOk); std::ostringstream msg; msg << "Exchanged kids! of parent of binary operator" << getName(); msg << ", with a cast to type: "; msg << m_state.getUlamTypeNameBriefByIndex(nuti).c_str(); msg << " while compiling class: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); castNode->setYourParentNo(pno); //inverts normal update lineage setYourParentNo(castNode->getNodeNo()); } } return nuti; } //castThyselfToResultType
FORECAST UlamTypePrimitiveInt::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 = m_state.getBitSize(typidx); s32 bitsize = getBitSize(); ULAMTYPE valtypEnum = vut->getUlamTypeEnum(); switch(valtypEnum) { case Int: brtn = (bitsize >= valbitsize); break; case Unsigned: brtn = (bitsize > valbitsize); break; case Unary: brtn = (bitsize > (s32) _getLogBase2(valbitsize) + 1); break; case Bool: case Bits: case Void: case UAtom: brtn = false; break; case Class: { //must be Quark! treat as Int if it has a toInt method if(vut->isNumericType()) brtn = (bitsize >= MAXBITSPERINT); else brtn = false; //t41131 called by matching args (no error msg please) } break; default: m_state.abortUndefinedUlamType(); //std::cerr << "UlamTypePrimitiveInt (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; return brtn ? CAST_CLEAR : CAST_BAD; } //safeCast
void SymbolWithValue::printPostfixValueArrayStringAsComment(File * fp) { BV8K dval; bool oktoprint = getValueReadyToPrint(dval); UTI tuti = getUlamTypeIdx(); UlamType * tut = m_state.getUlamTypeByIndex(tuti); bool isString = (tut->getUlamTypeEnum() == String); //t3953 assert(isString); if(!oktoprint) { fp->write("// "); fp->write(getMangledName().c_str()); fp->write(": NONREADYCONSTARRAY OF STRINGS"); GCNL; return; } //like the code generated in CS::genCodeClassDefaultConstantArray u32 uvals[ARRAY_LEN8K]; dval.ToArray(uvals); u32 nwords = tut->getTotalNumberOfWords(); //indented comments of string value items (one per line); e.g. t3953,4 for(u32 w = 0; w < nwords; w++) { m_state.indent(fp); fp->write("// "); fp->write("["); fp->write_decimal_unsigned(w); fp->write("] = "); fp->write(m_state.getDataAsFormattedUserString(uvals[w]).c_str()); fp->write("\n"); } m_state.indent(fp); fp->write("// = "); fp->write(getMangledName().c_str()); fp->write("["); fp->write_decimal_unsigned(nwords); fp->write("]"); GCNL; } //printPostfixValueArrayStringAsComment
void NodeVarRef::checkAbstractInstanceErrors() { //unlike NodeVarDecl, an abstract class can be a reference! UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); if(nut->getUlamTypeEnum() == Class) { SymbolClass * csym = NULL; AssertBool isDefined = m_state.alreadyDefinedSymbolClass(nuti, csym); assert(isDefined); if(csym->isAbstract()) { std::ostringstream msg; msg << "Instance of Abstract Class "; msg << m_state.getUlamTypeNameBriefByIndex(nuti).c_str(); msg << " used with reference variable symbol name '"; msg << getName() << "'"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), INFO); } } } //checkAbstractInstanceErrors
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
void SymbolWithValue::printPostfixValueArray(File * fp) { BV8K dval; bool oktoprint = getValueReadyToPrint(dval); if(!oktoprint) { fp->write("NONREADYCONSTARRAY"); return; } UTI tuti = getUlamTypeIdx(); UlamType * tut = m_state.getUlamTypeByIndex(tuti); s32 tbs = tut->getTotalBitSize(); if(tbs == 0) { fp->write("{ }"); return; //nothing to do } //required as hex for String arrays too (needed for initialization) (t3974) //like the code generated in CS::genCodeClassDefaultConstantArray std::string dhex; bool nonZero = SymbolWithValue::getHexValueAsString(tbs, dval, dhex); //short-circuit if all zeros if(!nonZero) { if(tut->getUlamTypeEnum() == String) //t3953 m_state.abortShouldntGetHere(); fp->write("{ 0 }"); return; //nothing else to do } fp->write("{ "); fp->write(dhex.c_str()); fp->write(" }"); } //printPostfixValueArray
void NodeTypedef::printPostfix(File * fp) { assert(m_typedefSymbol); if(m_typedefSymbol->getId() == m_state.m_pool.getIndexForDataString("Self")) return; if(m_typedefSymbol->getId() == m_state.m_pool.getIndexForDataString("Super")) return; UTI tuti = m_typedefSymbol->getUlamTypeIdx(); UlamKeyTypeSignature tkey = m_state.getUlamKeyTypeSignatureByIndex(tuti); UlamType * tut = m_state.getUlamTypeByIndex(tuti); fp->write(" typedef"); fp->write(" "); if(tut->getUlamTypeEnum() != Class) { fp->write(tkey.getUlamKeyTypeSignatureNameAndBitSize(&m_state).c_str()); if(tut->isReference()) fp->write(" &"); //an array of refs as written, should be ref to an array. } else fp->write(tut->getUlamTypeNameBrief().c_str()); fp->write(" "); fp->write(getName()); s32 arraysize = m_state.getArraySize(tuti); if(arraysize > NONARRAYSIZE) { fp->write("["); fp->write_decimal(arraysize); fp->write("]"); } else if(arraysize == UNKNOWNSIZE) { fp->write("[UNKNOWN]"); } fp->write("; "); } //printPostfix
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 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
UTI NodeUnaryOp::checkAndLabelType() { assert(m_node); UTI uti = m_node->checkAndLabelType(); if(m_state.isComplete(uti) && !m_state.isScalar(uti)) //array unsupported at this time { std::ostringstream msg; msg << "Incompatible (nonscalar) type: "; msg << m_state.getUlamTypeNameBriefByIndex(uti).c_str(); msg << ", for unary " << getName(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); setNodeType(Nav); return Nav; } //replace node with func call to matching function overload operator for class // of left, with no arguments for unary (t41???); // quark toInt must be used on rhs of operators (t3191, t3200, t3513, t3648,9) UlamType * ut = m_state.getUlamTypeByIndex(uti); if((ut->getUlamTypeEnum() == Class)) { Node * newnode = buildOperatorOverloadFuncCallNode(); if(newnode) { AssertBool swapOk = Node::exchangeNodeWithParent(newnode); assert(swapOk); m_node = NULL; //recycle as memberselect delete this; //suicide is painless.. return newnode->checkAndLabelType(); } //else should fail again as non-primitive; } //done UTI newType = Nav; if(uti != Nav) newType = calcNodeType(uti); //does safety check if(m_state.isComplete(newType)) { if(UlamType::compareForMakingCastingNode(newType, uti, m_state) != UTIC_SAME) //not same|dontknow { if(!Node::makeCastingNode(m_node, newType, m_node)) newType = Nav; } } else newType = Hzy; setNodeType(newType); if(newType == Hzy) m_state.setGoAgain(); //since not error Node::setStoreIntoAble(TBOOL_FALSE); if((newType != Nav) && isAConstant() && m_node->isReadyConstant()) return constantFold(); return newType; } //checkAndLabelType
UTI NodeMemberSelect::checkAndLabelType() { assert(m_nodeLeft && m_nodeRight); UTI luti = m_nodeLeft->checkAndLabelType(); //side-effect TBOOL lstor = m_nodeLeft->getStoreIntoAble(); if(lstor != TBOOL_TRUE) { //e.g. funcCall is not storeintoable even if its return value is. std::ostringstream msg; msg << "Member selected must be a valid lefthand side: '"; msg << m_nodeLeft->getName(); msg << "' requires a variable; may be a casted function call"; if(lstor == TBOOL_HAZY) { MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT); setNodeType(Hzy); m_state.setGoAgain(); return Hzy; } else { MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); setNodeType(Nav); return Nav; } } //done if(!m_state.isComplete(luti)) { std::ostringstream msg; msg << "Member selected is incomplete class: "; msg << m_state.getUlamTypeNameBriefByIndex(luti).c_str(); msg << ", check and label fails this time around"; if(luti == Nav) { MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); setNodeType(Nav); } else { MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT); setNodeType(Hzy); m_state.setGoAgain(); //since no error msg } return getNodeType(); } //done UlamType * lut = m_state.getUlamTypeByIndex(luti); ULAMCLASSTYPE classtype = lut->getUlamClassType(); if(((classtype == UC_NOTACLASS) && (lut->getUlamTypeEnum() != Holder)) || !lut->isScalar()) { // must be a scalar 'Class' type, (e.g. error/t3815) // doesn't complete checkandlabel for rhs (e.g. funccall is NULL, no eval) std::ostringstream msg; msg << "Member selected must be a Class, not type: "; msg << m_state.getUlamTypeNameBriefByIndex(luti).c_str(); if(classtype != UC_NOTACLASS) msg << "[" << lut->getArraySize() << "]"; if(m_state.isAtom(luti)) msg << "; suggest using a Conditional-As"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); setNodeType(Nav); return Nav; } //done std::string className = m_state.getUlamTypeNameBriefByIndex(luti); //help me debug SymbolClass * csym = NULL; AssertBool isDefined = m_state.alreadyDefinedSymbolClass(luti, csym); assert(isDefined); NodeBlockClass * memberClassNode = csym->getClassBlockNode(); assert(memberClassNode); //e.g. forgot the closing brace on quark definition assert(m_state.okUTItoContinue(memberClassNode->getNodeType())); //t41010 //set up compiler state to use the member class block for symbol searches m_state.pushClassContextUsingMemberClassBlock(memberClassNode); UTI rightType = m_nodeRight->checkAndLabelType(); //clear up compiler state to no longer use the member class block for symbol searches m_state.popClassContext(); setNodeType(rightType); //set Nav if error (t3513) if(m_state.okUTItoContinue(rightType)) { //based on righthand side Node::setStoreIntoAble(m_nodeRight->getStoreIntoAble()); //base reference-ability on righthand side (t41085) Node::setReferenceAble(m_nodeRight->getReferenceAble()); } return getNodeType(); } //checkAndLabelType
FORECAST NodeVarRef::safeToCastTo(UTI newType) { assert(m_nodeInitExpr); UTI nuti = getNodeType(); //cast RHS if necessary and safe //insure lval is same bitsize/arraysize // if classes, safe to cast a subclass to any of its superclasses FORECAST rscr = CAST_CLEAR; if(UlamType::compare(nuti, newType, m_state) != UTIC_SAME) { UlamType * nut = m_state.getUlamTypeByIndex(nuti); UlamType * newt = m_state.getUlamTypeByIndex(newType); rscr = m_nodeInitExpr->safeToCastTo(nuti); if((nut->getUlamTypeEnum() == Class)) { if(rscr != CAST_CLEAR) { //e.g. error/t3792, error/t3616 std::ostringstream msg; msg << "Incompatible class types "; msg << nut->getUlamTypeClassNameBrief(nuti).c_str(); msg << " and "; msg << m_state.getUlamTypeNameBriefByIndex(newType).c_str(); msg << " used to initialize reference '" << getName() <<"'"; if(rscr == CAST_HAZY) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } } else if(m_state.isAtom(nuti)) { //atoms init from a quark ref could use .atomof // "clear" when complete, not the same as "bad". if(rscr != CAST_CLEAR) { std::ostringstream msg; msg << "Reference atom variable " << getName() << "'s type "; msg << nut->getUlamTypeNameBrief().c_str(); msg << ", and its initial value type "; msg << m_state.getUlamTypeNameBriefByIndex(newType).c_str(); msg << ", are incompatible"; if(newt->isAltRefType() && newt->getUlamClassType() == UC_QUARK) msg << "; .atomof may help"; if(rscr == CAST_HAZY) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } } else { //primitives must be EXACTLY the same size (for initialization); // "clear" when complete, not the same as "bad". (t3614, t3694) if(rscr != CAST_CLEAR) { std::ostringstream msg; msg << "Reference variable " << getName() << "'s type "; msg << m_state.getUlamTypeNameBriefByIndex(nuti).c_str(); msg << ", and its initial value type "; msg << m_state.getUlamTypeNameBriefByIndex(newType).c_str(); msg << ", are incompatible"; if(rscr == CAST_HAZY) MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } else if(m_nodeInitExpr->isAConstant() && !m_state.isConstantRefType(nuti)) { std::ostringstream msg; msg << "Initial value of non-constant reference variable: " << getName(); msg << " is constant"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); //error/t41255 rscr = CAST_BAD; } } } //okay to explicitly cast rhs to reference type, e.g. if(a is Foo) QW& qref = (Foo &) a; return rscr; } //safeToCastTo
UTI NodeBinaryOpEqualShift::checkAndLabelType() { //UTI nodeType = NodeBinaryOp::checkAndLabelType(); //dup Shift calcNodeType assert(m_nodeLeft && m_nodeRight); UTI leftType = m_nodeLeft->checkAndLabelType(); UTI rightType = m_nodeRight->checkAndLabelType(); if(!m_state.okUTItoContinue(leftType)) { //left type possibly a class w overload operator; no need to check right type here; setNodeType(leftType); return getNodeType(); } // efficiency bites! no sooner, need left and right side-effects // (e.g. NodeControl condition is Bool at start; stubs need Symbol ptrs) if(m_state.isComplete(getNodeType())) return getNodeType(); //replace node with func call to matching function overload operator for class // of left, with argument of right; UlamType * lut = m_state.getUlamTypeByIndex(leftType); if((lut->getUlamTypeEnum() == Class)) { Node * newnode = buildOperatorOverloadFuncCallNode(); //virtual if(newnode) { AssertBool swapOk = Node::exchangeNodeWithParent(newnode); assert(swapOk); m_nodeLeft = NULL; //recycle as memberselect m_nodeRight = NULL; //recycle as func call arg delete this; //suicide is painless.. return newnode->checkAndLabelType(); } //else should fail again as non-primitive; } //done UTI newType = calcNodeType(leftType, rightType); //does safety check setNodeType(newType); if(m_state.okUTItoContinue(newType)) { TBOOL stor = NodeBinaryOpEqual::checkStoreIntoAble(); if(stor == TBOOL_FALSE) { setNodeType(Nav); return Nav; //newType } else if(stor == TBOOL_HAZY) { setNodeType(Hzy); m_state.setGoAgain(); } if(!NodeBinaryOpEqual::checkNotUnpackedArray()) { setNodeType(Nav); return Nav; } } if(m_state.isComplete(newType)) { //lhs must be Bits; can't cast lhs of equal. //shift by unsigned type; cast if need be. safety checked by calcNodeType. if(m_state.getUlamTypeByIndex(rightType)->getUlamTypeEnum() != Unsigned) { if(!Node::makeCastingNode(m_nodeRight, Unsigned, m_nodeRight)) { newType = Nav; setNodeType(Nav); } } } //complete return getNodeType(); } //checkandlabeltype
// this is the auto local variable's node, created at parse time, // for Conditional-As case. void NodeVarRefAs::genCode(File * fp, UVPass & uvpass) { assert(!m_state.m_currentObjSymbolsForCodeGen.empty()); // the uvpass comes from NodeControl, and still has the POS obtained // during the condition statement for As..unorthodox, but necessary. // before shadowing the lhs of the h/as-conditional variable with its auto, // let's load its storage from the currentSelfSymbol: Symbol * stgcos = m_state.m_currentObjSymbolsForCodeGen[0]; UTI stgcosuti = stgcos->getUlamTypeIdx(); UlamType * stgcosut = m_state.getUlamTypeByIndex(stgcosuti); ULAMTYPE stgetyp = stgcosut->getUlamTypeEnum(); ULAMCLASSTYPE stgclasstype = stgcosut->getUlamClassType(); assert((stgetyp == UAtom) || (stgetyp == Class)); //lhs if(stgcos->isSelf()) return genCodeRefAsSelf(fp, uvpass); s32 tmpVarStg = m_state.getNextTmpVarNumber(); // can't let Node::genCodeReadIntoTmpVar do this for us: need a ref. assert(m_state.m_currentObjSymbolsForCodeGen.size() == 1); m_state.indentUlamCode(fp); fp->write(stgcosut->getUlamTypeImmediateMangledName().c_str()); fp->write("<EC> & "); //here it is!! brilliant fp->write(m_state.getTmpVarAsString(stgcosuti, tmpVarStg, TMPBITVAL).c_str()); fp->write(" = "); fp->write(stgcos->getMangledName().c_str()); fp->write("; //c++ reference to immediate"); GCNL; // now we have our pos in tmpVarPos, and our T in tmpVarStg // time to shadow 'self' with auto local variable: UTI vuti = m_varSymbol->getUlamTypeIdx(); UlamType * vut = m_state.getUlamTypeByIndex(vuti); ULAMCLASSTYPE vclasstype = vut->getUlamClassType(); m_state.indentUlamCode(fp); fp->write(vut->getLocalStorageTypeAsString().c_str()); //for C++ local vars, ie non-data members fp->write(" "); fp->write(m_varSymbol->getMangledName().c_str()); fp->write("("); fp->write(m_state.getTmpVarAsString(stgcosuti, tmpVarStg, TMPBITVAL).c_str()); if(stgetyp == UAtom) { fp->write(", 0u + T::ATOM_FIRST_STATE_BIT, "); //position as super quark (e.g. t3639, t3709, t3675, t3408, t3336); as element t3249, t3255, t3637; as atom ref t3908 //note: needs effective self of the atom, not simply the RHS type. fp->write(m_state.getHiddenContextArgName()); fp->write(".LookupUlamElementTypeFromContext("); fp->write(m_state.getTmpVarAsString(stgcosuti, tmpVarStg, TMPBITVAL).c_str()); //t3636 fp->write(".GetType())"); if(vclasstype == UC_QUARK) fp->write(", UlamRef<EC>::ELEMENTAL"); //becomes elemental, t3835 } else if((stgclasstype == UC_ELEMENT)) { if(stgcosut->isReference()) { fp->write(", 0u, "); //t3655 fp->write(stgcos->getMangledName().c_str()); //stg fp->write(".GetEffectiveSelf()"); //Sat Jun 18 17:30:20 2016 } else { fp->write(", 0u + T::ATOM_FIRST_STATE_BIT, &"); //t3586, t3589, t3637 //must be same as look up for elements only Sat Jun 18 17:30:17 2016 fp->write(m_state.getTheInstanceMangledNameByIndex(stgcosuti).c_str()); } if(vclasstype == UC_QUARK) fp->write(", UlamRef<EC>::ELEMENTAL"); //stays elemental } else if((stgclasstype == UC_TRANSIENT)) { // transient can be another transient or a quark, not an element fp->write(", 0u, "); if(stgcosut->isReference()) { fp->write(stgcos->getMangledName().c_str()); //stg fp->write(".GetEffectiveSelf()"); //t3824 } else { fp->write("&"); //t3822 fp->write(m_state.getTheInstanceMangledNameByIndex(stgcosuti).c_str()); } if(vclasstype == UC_QUARK) fp->write(", UlamRef<EC>::CLASSIC"); //stays classic } else if((stgclasstype == UC_QUARK)) { // quark can be another quark, not an element, nor transient fp->write(", 0u, "); if(stgcosut->isReference()) { fp->write(stgcos->getMangledName().c_str()); //stg fp->write(".GetEffectiveSelf()"); //tt3829 } else { fp->write("&"); //t3830 fp->write(m_state.getTheInstanceMangledNameByIndex(stgcosuti).c_str()); } assert(vclasstype == UC_QUARK); fp->write(", UlamRef<EC>::CLASSIC"); //stays classic } else m_state.abortUndefinedUlamClassType(); //WHAT THEN??? if(!stgcosut->isReference()) fp->write(", uc"); //t3249 fp->write("); //shadows lhs of 'as'"); GCNL; m_state.clearCurrentObjSymbolsForCodeGen(); //clear remnant of lhs ? } //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)
UTI NodeTypedef::checkAndLabelType() { UTI it = Nav; // instantiate, look up in current block if(m_typedefSymbol == NULL) checkForSymbol(); if(m_typedefSymbol) { //m_typedefSymbol is the (rhs) type alias it = m_typedefSymbol->getUlamTypeIdx(); //check for UNSEEN Class' ClassType (e.g. array of UC_QUARK) UlamType * tdut = m_state.getUlamTypeByIndex(it); if((tdut->getUlamTypeEnum() == Class) && (tdut->getUlamClassType() == UC_UNSEEN)) { if(!m_state.completeIncompleteClassSymbolForTypedef(it)) { std::ostringstream msg; msg << "Incomplete Typedef for class type: "; msg << m_state.getUlamTypeNameBriefByIndex(it).c_str(); msg << ", used with variable symbol name <" << getName() << ">"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT); } } else if(tdut->isHolder() && !m_state.isThisLocalsFileScope()) { m_state.statusUnknownTypeInThisClassResolver(it); } UTI cuti = m_state.getCompileThisIdx(); if(m_nodeTypeDesc) { UTI duti = m_nodeTypeDesc->checkAndLabelType(); //sets goagain if nav if(m_state.okUTItoContinue(duti) && (duti != it)) { std::ostringstream msg; msg << "REPLACING Symbol UTI" << it; msg << ", " << m_state.getUlamTypeNameBriefByIndex(it).c_str(); msg << " used with typedef symbol name '" << getName(); msg << "' with node type descriptor type: "; msg << m_state.getUlamTypeNameBriefByIndex(duti).c_str(); msg << " UTI" << duti << " while labeling class: "; msg << m_state.getUlamTypeNameBriefByIndex(cuti).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); m_state.mapTypesInCurrentClass(it, duti); m_state.updateUTIAliasForced(it, duti); //t3379 m_typedefSymbol->resetUlamType(duti); //consistent! (must be same ref type) it = duti; } } if(!m_state.okUTItoContinue(it) || !m_state.isComplete(it)) //reloads { std::ostringstream msg; msg << "Incomplete Typedef for type: "; msg << m_state.getUlamTypeNameBriefByIndex(it).c_str(); msg << ", used with typedef symbol name '" << getName() << "'"; if(m_state.okUTItoContinue(it) || (it == Hzy)) { MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WAIT); m_state.setGoAgain(); //since not error; unlike vardecl } else MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } } // got typedef symbol setNodeType(it); return getNodeType(); } //checkAndLabelType
// 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
//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 NodeTypeDescriptorSelect::resolveType(UTI& rtnuti) { bool rtnb = false; if(isReadyType()) { rtnuti = getNodeType(); return true; } // we are in a "chain" of type selects.. assert(m_nodeSelect); UTI seluti = m_nodeSelect->checkAndLabelType(); if(m_nodeSelect->isReadyType()) { UlamType * selut = m_state.getUlamTypeByIndex(seluti); ULAMTYPE seletype = selut->getUlamTypeEnum(); if(seletype == Class) { SymbolClass * csym = NULL; assert(m_state.alreadyDefinedSymbolClass(seluti, csym)); m_state.pushClassContext(seluti, csym->getClassBlockNode(), csym->getClassBlockNode(), false, NULL); // find our id in the "selected" class, must be a typedef at top level Symbol * asymptr = NULL; if(m_state.alreadyDefinedSymbol(m_typeTok.m_dataindex, asymptr)) { if(asymptr->isTypedef()) { UTI auti = asymptr->getUlamTypeIdx(); if(m_state.isComplete(auti)) { rtnuti = auti; //should be mapped already, if necessary rtnb = true; } else if(m_state.isHolder(auti)) { UTI mappedUTI; if(m_state.mappedIncompleteUTI(seluti, auti, mappedUTI)) { std::ostringstream msg; msg << "Substituting Mapped UTI" << mappedUTI << ", "; msg << m_state.getUlamTypeNameBriefByIndex(mappedUTI).c_str(); msg << " for incomplete descriptor type: "; msg << m_state.getUlamTypeNameBriefByIndex(auti).c_str(); msg << "' UTI" << auti << " while labeling class: "; msg << m_state.getUlamTypeNameBriefByIndex(seluti).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); auti = mappedUTI; } } } else { //error id is not a typedef std::ostringstream msg; msg << "Not a typedef <" << m_state.getTokenDataAsString(&m_typeTok).c_str(); msg << "> in another class, " ;; msg << m_state.getUlamTypeNameBriefByIndex(seluti).c_str(); msg <<" while compiling: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), WARN); } } else { //error! id not found std::ostringstream msg; msg << "Undefined Typedef <" << m_state.getTokenDataAsString(&m_typeTok).c_str(); msg << "> in another class, " ;; msg << m_state.getUlamTypeNameBriefByIndex(seluti).c_str(); msg <<" while compiling: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); } m_state.popClassContext(); } else { //error has to be a class std::ostringstream msg; msg << "Type selected by <" << m_state.getTokenDataAsString(&m_typeTok).c_str(); msg << "> is NOT another class, " ; msg << m_state.getUlamTypeNameBriefByIndex(seluti).c_str(); msg << ", rather a " << UlamType::getUlamTypeEnumAsString(seletype) << " type,"; msg <<" while compiling: "; msg << m_state.getUlamTypeNameBriefByIndex(m_state.getCompileThisIdx()).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } } //else select not ready, so neither are we!! return rtnb; } //resolveType