void* StdMap_remove( StdMap* self, const IKey* key ) { void* ret = 0; IPIterator* it = self->entries->positions( self->entries ); while ( it->hasNext( it ) ) { const IPosition* p = it->next( it ); const StdEntry* entry = (StdEntry*) p->getElement( p ); const IKey* e_key = (const IKey*) StdEntry_getKey( entry ); if ( e_key->contentEquals( e_key, key ) ) { StdEntry* removed_entry = (StdEntry*) self->entries->remove( self->entries, p ); IValue* v = (IValue*) StdEntry_replaceValue( removed_entry, NULL ); ret = v->replaceValue( v, NULL ); free_StdEntry( removed_entry ); v->free( v ); break; } } it->free( it ); return ret; }
Variant convertVariant(IValue &value) { if (value.isObject()) { return deserialize(value); } else if (value.isArray()) { return Variant::make<std::vector<Variant>>( convertArray<Variant>(value, convertVariant)); } else { // This covers all non-object values // i.e values without a _typename entry return value.getVariant(); } }
bool GenPrototype::restoreGene(FILE* f, RESTORE_GA_GENE* gene, std::vector<Gen*>& storage) { IValue* value = m_randomStrategy->getRandomValue(); Gen* gen; if(!value->restore(f)) return false; gen = new Gen(this,gene->ID); gen->setValue(value); //make sure that the genes are in the right order //SingletonGenEngine::getInstance()->addGen(gen); if(storage.size()<=(unsigned int)gene->ID) storage.resize(gene->ID+1); storage[gene->ID]=gen; return true; }
//--------------------------------------------------------------------------- bool IValue::operator!=(const IValue &a_Val) const { char_type type1 = GetType(), type2 = a_Val.GetType(); if (type1 == type2 || (IsScalar() && a_Val.IsScalar())) { switch (GetType()) { case 's': return GetString() != a_Val.GetString(); case 'i': case 'f': return GetFloat() != a_Val.GetFloat(); case 'c': return (GetFloat() != a_Val.GetFloat()) || (GetImag() != a_Val.GetImag()); case 'b': return GetBool() != a_Val.GetBool(); case 'v': return true; case 'm': if (GetRows() != a_Val.GetRows() || GetCols() != a_Val.GetCols()) { return true; } else { for (int i = 0; i < GetRows(); ++i) { if (const_cast<IValue*>(this)->At(i) != const_cast<IValue&>(a_Val).At(i)) return true; } return false; } default: ErrorContext err; err.Errc = ecINTERNAL_ERROR; err.Pos = -1; err.Type2 = GetType(); err.Type1 = a_Val.GetType(); throw ParserError(err); } // switch this type } else { return true; } }
void CDynaRow::Format(FILE * file, LPCTSTR format) { // output head for (JCSIZE ii = 0; ii < m_col_size; ++ii) { IValue * val = m_cols[ii]; stdext::auto_cif<IValueFormat> fmt; //IValueFormat * fmt = NULL; val->QueryInterface(IF_NAME_VALUE_FORMAT, fmt); //IValueFormat * fmt = dynamic_cast<IValueFormat*>(); if ( fmt.valid() ) { fmt->Format(file, format); //fmt->Release(); } stdext::jc_fprintf(file, _T(",")); } //stdext::jc_fprintf(file, _T("\n")); }
IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, IHqlExpression * test, unsigned lower, unsigned upper) { ITypeInfo * compareType = test->queryType()->queryPromotedType(); type_t compareTypeCode = compareType->getTypeCode(); HqlExprArray values; IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur unsigned num = (upper-lower+1); values.ensure(num); unsigned idx; for (idx = 0; idx < num; idx++) values.append(*LINK(dft)); ForEachItemIn(idx2, pairs) { IHqlExpression & cur = pairs.item(idx2); IValue * value = cur.queryChild(0)->queryValue(); unsigned replaceIndex; switch (compareTypeCode) { case type_int: replaceIndex = (int)value->getIntValue()-lower; break; case type_string: { StringBuffer temp; value->getStringValue(temp); replaceIndex = (int)(unsigned char)temp.charAt(0)-lower; break; } default: throwUnexpectedType(compareType); } IHqlExpression * mapTo = cur.queryChild(1); if (mapTo->getOperator() != no_constant) throwUnexpected(); if (replaceIndex >= num) translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex); else values.replace(*LINK(mapTo),replaceIndex); }
void* StdMap_put_IValue( StdMap* self, const IKey* key, StdValue* aValue ) { void* ret = 0; int inserted = 0; IPIterator* it = self->entries->positions( self->entries ); bool loop = TRUE; while ( loop && it->hasNext( it ) ) { const IPosition* p = it->next( it ); const IEntry* entry = p->getElement( p ); const IKey* e_key = entry->getKey( entry ); if ( e_key->contentEquals( e_key, key ) ) { IValue* value = (IValue*) StdEntry_replaceValue( (StdEntry*) entry, aValue ); ret = value->replaceValue( value, NULL ); value->free( value ); inserted = 1; break; } else if ( 0 < e_key->compareTo( e_key, key ) ) { IEntry* entry = (IEntry*) new_StdEntry( key, (IValue*) aValue ); self->entries->insertBefore( self->entries, p, entry ); inserted = 1; loop = FALSE; } //int x = e_key->compareTo( e_key, key ); //fprintf( stdout, "%i %s - %s\n", x, e_key->getChars( e_key ), key->getChars( key ) ); } it->free( it ); if ( ! inserted ) { IEntry* entry = (IEntry*) new_StdEntry( key, (IValue*) aValue ); self->entries->insertLast( self->entries, entry ); } return ret; }
//--------------------------------------------------------------------------- bool IValue::operator<=(const IValue &a_Val) const { char_type type1 = GetType(), type2 = a_Val.GetType(); if (type1 == type2 || (IsScalar() && a_Val.IsScalar())) { switch (GetType()) { case 's': return GetString() <= a_Val.GetString(); case 'i': case 'f': case 'c': return GetFloat() <= a_Val.GetFloat(); case 'b': return GetBool() <= a_Val.GetBool(); default: ErrorContext err; err.Errc = ecINTERNAL_ERROR; err.Pos = -1; err.Type1 = GetType(); err.Type2 = a_Val.GetType(); throw ParserError(err); } // switch this type } else { ErrorContext err; err.Errc = ecTYPE_CONFLICT_FUN; err.Arg = (type1 != 'f' && type1 != 'i') ? 1 : 2; err.Type1 = type2; err.Type2 = type1; throw ParserError(err); } }
void ViewFieldECLTransformer::transform(unsigned & lenTarget, char * & target, unsigned lenSource, const char * source, const HqlExprArray & extraArgs) { Owned<ITypeInfo> sourceType = makeUtf8Type(lenSource, 0); IValue * sourceValue = createUtf8Value(source, LINK(sourceType)); OwnedHqlExpr sourceExpr = createConstant(sourceValue); HqlExprArray actuals; actuals.append(*LINK(sourceExpr)); appendArray(actuals, extraArgs); Owned<IErrorReceiver> errorReporter = createThrowingErrorReceiver(); OwnedHqlExpr call = createBoundFunction(errorReporter, function, actuals, NULL, true); OwnedHqlExpr castValue = ensureExprType(call, utf8Type); OwnedHqlExpr folded = quickFoldExpression(castValue, NULL, 0); IValue * foldedValue = folded->queryValue(); assertex(foldedValue); unsigned len = foldedValue->queryType()->getStringLen(); const char * data = static_cast<const char *>(foldedValue->queryValue()); unsigned size = rtlUtf8Size(len, data); lenTarget = len; target = (char *)rtlMalloc(size); memcpy(target, data, size); }
//--------------------------------------------------------------------------- Value::Value(const IValue &a_Val) :IValue(cmVAL) ,m_psVal(nullptr) ,m_pvVal(nullptr) ,m_pCache(nullptr) { Reset(); switch(a_Val.GetType()) { case 'i': case 'f': case 'b': m_val = cmplx_type(a_Val.GetFloat(), 0); break; case 'c': m_val = cmplx_type(a_Val.GetFloat(), a_Val.GetImag()); break; case 's': if (!m_psVal) m_psVal = new string_type(a_Val.GetString()); else *m_psVal = a_Val.GetString(); break; case 'm': if (!m_pvVal) m_pvVal = new matrix_type(a_Val.GetArray()); else *m_pvVal = a_Val.GetArray(); break; case 'v': break; default: MUP_FAIL(INVALID_TYPE_CODE); } m_cType = a_Val.GetType(); }
bool convertBool(IValue &value) { return value.getBool(); }
VALUE IValue::readValue(int offset, KIND type) { int byte; VALUE value; DEBUG_STDOUT("\t" << " Reading from IValue object: " << toString()); DEBUG_STDOUT("\t" << " Reading for type: " << KIND_ToString(type)); byte = KIND_GetSize(type); if (offset == 0 && KIND_GetSize(getIPtrValue(index).getType()) == byte) { // // trivial reading case // DEBUG_STDOUT("\t" << "Trivial reading."); value = getIPtrValue(index).getValue(); } else { // // off the shelf reading case // DEBUG_STDOUT("\t" << "Off the shelf reading."); unsigned nextIndex; int totalByte, tocInx, trcInx; uint8_t* totalContent, *truncContent; nextIndex = index; totalByte = 0; // TODO: review the condition nextIndex < length while (totalByte < offset + byte && nextIndex < length) { IValue value; value = getIPtrValue(nextIndex); totalByte += KIND_GetSize(value.getType()); // TODO: can the value's type change while iterating? nextIndex++; } // // totalContent stores the accumulative content from IValue at index // to IValue at nextIndex-1 // totalContent = (uint8_t*)malloc(totalByte * sizeof(uint8_t)); tocInx = 0; for (unsigned i = index; i < nextIndex; i++) { IValue value; KIND type; int size; VALUE valValue; uint8_t* valueContent; value = getIPtrValue(i); type = value.getType(); size = KIND_GetSize(type); // TODO: can the value's type change while iterating? valValue = value.getValue(); valueContent = (uint8_t*)&valValue; for (int j = 0; j < size; j++) { totalContent[tocInx] = valueContent[j]; tocInx++; } } // // truncate content from total content // truncContent = (uint8_t*)calloc(8, sizeof(uint8_t)); // TODO: magic number 8 is 64/8 trcInx = 0; for (int i = offset; i < offset + byte; i++) { truncContent[trcInx] = totalContent[i]; trcInx++; } // // cast truncate content array to an actual value // switch (type) { case FLP32_KIND: { float* truncValue = (float*)truncContent; value.as_flp = *truncValue; break; } case FLP64_KIND: { double* truncValue = (double*)truncContent; value.as_flp = *truncValue; break; } default: { int64_t* truncValue = (int64_t*)truncContent; value.as_int = *truncValue; break; } } } return value; }
int FuncCallStack::push(ITypeInfo* argType, IHqlExpression* curParam) { unsigned len = 0; char* str; int incsize; int inclen; IValue * paramValue = curParam->queryValue(); Owned<IValue> castParam; if (paramValue) // Not all constants have a paramValue - null, all, constant records etc { castParam.setown(paramValue->castTo(argType)); if(!castParam) { PrintLog("Failed to cast paramValue to argType in FuncCallStack::push"); return -1; } } switch (argType->getTypeCode()) { case type_string: case type_data: getStringFromIValue(len, str, castParam); // For STRINGn, len doesn't need to be passed in. if(argType->getSize() == UNKNOWN_LENGTH) { push(sizeof(unsigned), &len); } push(sizeof(char *), &str); if(numToFree < MAXARGS) { toFree[numToFree++] = str; } break; case type_varstring: getStringFromIValue(len, str, castParam); push(sizeof(char *), &str); if(numToFree < MAXARGS) { toFree[numToFree++] = str; } break; case type_qstring: case type_unicode: case type_utf8: { unsigned argSize = castParam->getSize(); const void * text = castParam->queryValue(); str = (char *)malloc(argSize); memcpy(str, text, argSize); // For STRINGn, len doens't need to be passed in. if(argType->getSize() == UNKNOWN_LENGTH) { len = castParam->queryType()->getStringLen(); push(sizeof(unsigned), &len); } push(sizeof(char *), &str); if(numToFree < MAXARGS) { toFree[numToFree++] = str; } } break; case type_varunicode: UNIMPLEMENTED; case type_real: #ifdef MAXFPREGS if (numFpRegs==MAXFPREGS) { PrintLog("Too many floating point registers needed in FuncCallStack::push"); return -1; } char tempbuf[sizeof(double)]; castParam->toMem(tempbuf); #ifdef FPREG_FIXEDSIZE if (argType->getSize()<=4) fpRegs[numFpRegs++] = *(float *)&tempbuf; else fpRegs[numFpRegs++] = *(double *)&tempbuf; #else // Variable size FP registers as on arm/x64 if (argType->getSize()<=4) fpRegs[numFpRegs].f = *(float *)&tempbuf; else fpRegs[numFpRegs].d = *(double *)&tempbuf; fpSizes[numFpRegs++] = argType->getSize(); #endif break; #else // fall through if no hw regs used for params #endif case type_boolean: case type_int: case type_decimal: case type_date: case type_char: case type_enumerated: case type_swapint: case type_packedint: incsize = argType->getSize(); inclen = align(incsize); assure(inclen); castParam->toMem(stackbuf+sp); memset(stackbuf+sp+incsize, 0, inclen - incsize); sp += inclen; break; case type_row: { if (hasMeta) { try { pushMeta(curParam->queryRecordType()); } catch (IException *E) { ::Release(E); return -1; } } if (curParam->getOperator()==no_null) { // MORE - check type matches MemoryBuffer out; createConstantNullRow(out, curParam->queryRecord()); str = (char *) out.detach(); push(sizeof(char *), &str); if(numToFree < MAXARGS) toFree[numToFree++] = str; } else return -1; break; } case type_record: { try { pushMeta(curParam->queryRecordType()); } catch (IException *E) { ::Release(E); return -1; } break; } default: EclIR::dump_ir(curParam); //code isn't here to pass sets/datasets to external functions.... return -1; } return sp; }
IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, const CHqlBoundExpr & test) { ITypeInfo * compareType = test.queryType()->queryPromotedType(); type_t compareTypeCode = compareType->getTypeCode(); HqlExprArray values; IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur __int64 lower = getIntValue(lowerTableBound, 0); unsigned num = (getIntValue(upperTableBound, 0)-lower)+1; CHqlBoundExpr indexExpr; switch (compareTypeCode) { case type_int: indexExpr.set(test); break; case type_string: indexExpr.expr.setown(createValue(no_index, makeCharType(), LINK(test.expr), getZero())); indexExpr.expr.setown(createValue(no_cast, makeIntType(1, false), LINK(indexExpr.expr))); break; default: throwUnexpectedType(compareType); } if (useRangeIndex && (num != 1)) translator.ensureSimpleExpr(ctx, indexExpr); OwnedHqlExpr mapped; ITypeInfo * retType = resultType; //if num == pairs.ordinality() and all results are identical, avoid the table lookup. if (allResultsMatch && (num == pairs.ordinality())) { mapped.set(pairs.item(0).queryChild(1)); } else { values.ensure(num); unsigned idx; for (idx = 0; idx < num; idx++) values.append(*LINK(dft)); ForEachItemIn(idx2, pairs) { IHqlExpression & cur = pairs.item(idx2); IValue * value = cur.queryChild(0)->queryValue(); unsigned replaceIndex; switch (compareTypeCode) { case type_int: replaceIndex = (unsigned)(value->getIntValue()-lower); break; case type_string: { StringBuffer temp; value->getStringValue(temp); replaceIndex = (unsigned)((unsigned char)temp.charAt(0)-lower); break; } default: throwUnexpectedType(compareType); } IHqlExpression * mapTo = cur.queryChild(1); if (mapTo->getOperator() != no_constant) throwUnexpected(); if (replaceIndex >= num) translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex); else values.replace(*LINK(mapTo),replaceIndex); } //Now replace the placeholders with the default values. for (idx = 0; idx < num; idx++) { if (&values.item(idx) == dft) values.replace(*defaultValue.getLink(),idx); } // use a var string type to get better C++ generated... ITypeInfo * storeType = getArrayElementType(resultType); ITypeInfo * listType = makeArrayType(storeType, values.ordinality()); OwnedHqlExpr lvalues = createValue(no_list, listType, values); CHqlBoundExpr boundTable; translator.buildExpr(ctx, lvalues, boundTable); LinkedHqlExpr tableIndex = indexExpr.expr; if (getIntValue(lowerTableBound, 0)) tableIndex.setown(createValue(no_sub, tableIndex->getType(), LINK(tableIndex), LINK(lowerTableBound))); IHqlExpression * ret = createValue(no_index, LINK(retType), LINK(boundTable.expr), LINK(tableIndex)); mapped.setown(createTranslatedOwned(ret)); }
//--------------------------------------------------------------------------- void ParserXBase::CreateRPN() const { if (!m_pTokenReader->GetExpr().length()) Error(ecUNEXPECTED_EOF, 0); // The Stacks take the ownership over the tokens Stack<ptr_tok_type> stOpt; Stack<ptr_val_type> stVal; Stack<ICallback*> stFunc; Stack<int> stArgCount; Stack<int> stIdxCount; ptr_tok_type pTok, pTokPrev; Value val; ReInit(); // The outermost counter counts the number of seperated items // such as in "a=10,b=20,c=c+a" stArgCount.push(1); for(bool bLoop=true; bLoop;) { pTokPrev = pTok; pTok = m_pTokenReader->ReadNextToken(); #if defined(MUP_DUMP_TOKENS) cout << pTok->AsciiDump() << endl; #endif ECmdCode eCmd = pTok->GetCode(); switch (eCmd) { case cmVAR: case cmVAL: { IValue *pVal = pTok->AsIValue(); if (stFunc.empty() && pVal->GetType()=='n') { ErrorContext err; err.Errc = ecUNEXPECTED_PARENS; err.Ident = _T(")"); err.Pos = pTok->GetExprPos(); throw ParserError(err); } stVal.push( ptr_val_type(pVal) ); // Arrays can't be added directly to the reverse polish notation // since there may be an index operator following next... m_rpn.Add(pTok); // Apply infix operator if existant if (stOpt.size() && stOpt.top()->GetCode()==cmOPRT_INFIX) ApplyFunc(stOpt, stVal, 1); } break; case cmIC: { // The argument count for parameterless functions is zero // by default an opening bracket sets parameter count to 1 // in preparation of arguments to come. If the last token // was an opening bracket we know better... if (pTokPrev.Get()!=NULL && pTokPrev->GetCode()==cmIO) --stArgCount.top(); ApplyRemainingOprt(stOpt, stVal); // if opt is "]" and opta is "[" the bracket content has been evaluated. // Now its time to check if there is either a function or a sign pending. // - Neither the opening nor the closing bracket will be pushed back to // the operator stack // - Check if a function is standing in front of the opening bracket, // if so evaluate it afterwards to apply an infix operator. if ( stOpt.size() && stOpt.top()->GetCode()==cmIO ) { // // Find out how many dimensions were used in the index operator. // std::size_t iArgc = stArgCount.pop(); stOpt.pop(); // Take opening bracket from stack IOprtIndex *pOprtIndex = pTok->AsIOprtIndex(); MUP_ASSERT(pOprtIndex!=NULL); pOprtIndex->SetNumArgsPresent(iArgc); m_rpn.Add(pTok); // Pop the index values from the stack MUP_ASSERT(stVal.size()>=iArgc+1); for (std::size_t i=0; i<iArgc; ++i) stVal.pop(); // Now i would need to pop the topmost value from the stack, apply the index // opertor and push the result back to the stack. But here we are just creating the // RPN and are working with dummy values anyway so i just mark the topmost value as // volatile and leave it were it is. The real index logic is in the RPN evaluator... stVal.top()->AddFlags(IToken::flVOLATILE); } // if opening index bracket is on top of operator stack } break; case cmBC: { // The argument count for parameterless functions is zero // by default an opening bracket sets parameter count to 1 // in preparation of arguments to come. If the last token // was an opening bracket we know better... if (pTokPrev.Get()!=NULL && pTokPrev->GetCode()==cmBO) --stArgCount.top(); ApplyRemainingOprt(stOpt, stVal); // if opt is ")" and opta is "(" the bracket content has been evaluated. // Now its time to check if there is either a function or a sign pending. // - Neither the opening nor the closing bracket will be pushed back to // the operator stack // - Check if a function is standing in front of the opening bracket, // if so evaluate it afterwards to apply an infix operator. if ( stOpt.size() && stOpt.top()->GetCode()==cmBO ) { // // Here is the stuff to evaluate a function token // int iArgc = stArgCount.pop(); stOpt.pop(); // Take opening bracket from stack if ( stOpt.empty() ) break; if ( (stOpt.top()->GetCode()!=cmFUNC) && (stOpt.top()->GetCode()!=cmOPRT_INFIX) ) break; ICallback *pFun = stOpt.top()->AsICallback(); stFunc.pop(); if (pFun->GetArgc()!=-1 && iArgc > pFun->GetArgc()) Error(ecTOO_MANY_PARAMS, pTok->GetExprPos(), pFun); if (iArgc < pFun->GetArgc()) Error(ecTOO_FEW_PARAMS, pTok->GetExprPos(), pFun); // Evaluate the function ApplyFunc(stOpt, stVal, iArgc); // Apply an infix operator, if present if (stOpt.size() && stOpt.top()->GetCode()==cmOPRT_INFIX) ApplyFunc(stOpt, stVal, 1); } } break; case cmELSE: ApplyRemainingOprt(stOpt, stVal); m_rpn.Add(pTok); stOpt.push(pTok); break; case cmSCRIPT_NEWLINE: { ApplyRemainingOprt(stOpt, stVal); // Value stack plätten // Stack der RPN um die Anzahl im stack enthaltener Werte zurück setzen int n = stVal.size(); m_rpn.AddNewline(pTok, n); stVal.clear(); stOpt.clear(); } break; case cmARG_SEP: if (stArgCount.empty()) Error(ecUNEXPECTED_COMMA, m_pTokenReader->GetPos()); ++stArgCount.top(); //if (stVal.size()) // increase argument counter // stArgCount.top()++; ApplyRemainingOprt(stOpt, stVal); break; case cmEOE: ApplyRemainingOprt(stOpt, stVal); m_rpn.Finalize(); break; case cmIF: case cmOPRT_BIN: { while ( stOpt.size() && stOpt.top()->GetCode() != cmBO && stOpt.top()->GetCode() != cmIO && stOpt.top()->GetCode() != cmELSE && stOpt.top()->GetCode() != cmIF) { IToken *pOprt1 = stOpt.top().Get(); IToken *pOprt2 = pTok.Get(); MUP_ASSERT(pOprt1 && pOprt2); MUP_ASSERT(pOprt1->AsIPrecedence() && pOprt2->AsIPrecedence()); int nPrec1 = pOprt1->AsIPrecedence()->GetPri(), nPrec2 = pOprt2->AsIPrecedence()->GetPri(); if (pOprt1->GetCode()==pOprt2->GetCode()) { // Deal with operator associativity EOprtAsct eOprtAsct = pOprt1->AsIPrecedence()->GetAssociativity(); if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) ) { break; } } else if (nPrec1 < nPrec2) { break; } // apply the operator now // (binary operators are identic to functions with two arguments) ApplyFunc(stOpt, stVal, 2); } // while ( ... ) if (pTok->GetCode()==cmIF) m_rpn.Add(pTok); stOpt.push(pTok); } break; // // Postfix Operators // case cmOPRT_POSTFIX: { MUP_ASSERT(stVal.size()); ptr_val_type &pVal(stVal.top()); try { // place a dummy return value into the value stack, do not // evaluate pOprt (this is important for lazy evaluation!) // The only place where evaluation takes place is the RPN // engine! pVal = ptr_val_type(new Value()); m_rpn.Add(pTok); } catch(ParserError &) { if (!m_bIsQueryingExprVar) throw; } } break; case cmIO: case cmBO: stOpt.push(pTok); stArgCount.push(1); break; // // Functions // case cmOPRT_INFIX: case cmFUNC: { ICallback *pFunc = pTok->AsICallback(); MUP_ASSERT(pFunc); // Check if this function is a argument to another function // if so check if the the return type fits. if (!stFunc.empty() && stFunc.top()->GetCode()==cmFUNC) { MUP_ASSERT(stArgCount.size()); int iArgc = (int)stArgCount.top() /*+ 1*/; ICallback *pOuterFunc = stFunc.top(); if (pOuterFunc->GetArgc()!=-1 && iArgc>pOuterFunc->GetArgc()) Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()); MUP_ASSERT(pOuterFunc->GetArgc()==-1 || iArgc<=pOuterFunc->GetArgc()); } stOpt.push(pTok); stFunc.push(pFunc); // to collect runtime type information } break; default: Error(ecINTERNAL_ERROR); } // switch Code if (ParserXBase::s_bDumpStack) { StackDump( stVal, stOpt ); } if ( pTok->GetCode() == cmEOE ) bLoop = false; } // for (all tokens) if (ParserXBase::s_bDumpRPN) { m_rpn.AsciiDump(); } m_nFinalResultIdx = stArgCount.top()-1; MUP_ASSERT(stVal.size()); }
//--------------------------------------------------------------------------- const IValue& ParserXBase::ParseFromRPN() const { ptr_val_type *pStack = &m_vStackBuffer[0]; if (m_rpn.GetSize()==0) { // Passiert bei leeren strings oder solchen, die nur Leerzeichen enthalten ErrorContext err; err.Expr = m_pTokenReader->GetExpr(); err.Errc = ecUNEXPECTED_EOF; err.Pos = 0; throw ParserError(err); } const ptr_tok_type *pRPN = &(m_rpn.GetData()[0]); int sidx = -1; std::size_t lenRPN = m_rpn.GetSize(); for (std::size_t i=0; i<lenRPN; ++i) { IToken *pTok = pRPN[i].Get(); ECmdCode eCode = pTok->GetCode(); switch (eCode) { case cmSCRIPT_NEWLINE: sidx = -1; continue; case cmVAL: { IValue *pVal = static_cast<IValue*>(pTok); sidx++; assert(sidx<(int)m_vStackBuffer.size()); if (pVal->IsVariable()) { pStack[sidx].Reset(pVal); } else { ptr_val_type &val = pStack[sidx]; if (val->IsVariable()) val.Reset(m_cache.CreateFromCache()); *val = *(static_cast<IValue*>(pTok)); } } continue; case cmIC: { IOprtIndex *pIdxOprt = static_cast<IOprtIndex*>(pTok); int nArgs = pIdxOprt->GetArgsPresent(); sidx -= nArgs - 1; assert(sidx>=0); ptr_val_type &idx = pStack[sidx]; // Pointer to the first index ptr_val_type &val = pStack[--sidx]; // Pointer to the variable or value beeing indexed pIdxOprt->At(val, &idx, nArgs); } continue; case cmOPRT_POSTFIX: case cmFUNC: case cmOPRT_BIN: case cmOPRT_INFIX: { ICallback *pFun = static_cast<ICallback*>(pTok); int nArgs = pFun->GetArgsPresent(); sidx -= nArgs - 1; assert(sidx>=0); ptr_val_type &val = pStack[sidx]; try { if (val->IsVariable()) { ptr_val_type buf(m_cache.CreateFromCache()); pFun->Eval(buf, &val, nArgs); val = buf; } else pFun->Eval(val, &val, nArgs); } catch(ParserError &exc) { // <ibg 20130131> Not too happy about that: // Multiarg functions may throw specific error codes when evaluating. // These codes would be converted to ecEVAL here. I omit the conversion // for certain handpicked errors. (The reason this catch block exists is // that not all exceptions contain proper metadata when thrown out of // a function.) if (exc.GetCode()==ecTOO_FEW_PARAMS || exc.GetCode()==ecDOMAIN_ERROR || exc.GetCode()==ecOVERFLOW) throw; // </ibg> ErrorContext err; err.Expr = m_pTokenReader->GetExpr(); err.Ident = pFun->GetIdent(); err.Errc = ecEVAL; err.Pos = pFun->GetExprPos(); err.Hint = exc.GetMsg(); throw ParserError(err); } catch(MatrixError & /*exc*/) { ErrorContext err; err.Expr = m_pTokenReader->GetExpr(); err.Ident = pFun->GetIdent(); err.Errc = ecMATRIX_DIMENSION_MISMATCH; err.Pos = pFun->GetExprPos(); throw ParserError(err); } } continue; case cmIF: MUP_ASSERT(sidx>=0); if (pStack[sidx--]->GetBool()==false) i+=static_cast<TokenIfThenElse*>(pTok)->GetOffset(); continue; case cmELSE: case cmJMP: i += static_cast<TokenIfThenElse*>(pTok)->GetOffset(); continue; case cmENDIF: continue; default: Error(ecINTERNAL_ERROR); } // switch token } // for all RPN tokens return *pStack[0]; }
IValue* Decoder::_decode(std::string value, int &pos) { IValue* json; std::string str = value.substr(pos); if (str.length() > 0) { switch(str[0]) { case '{': { int startPos = 0; json = new Value::Object(); (dynamic_cast<Value::Object*>(json))->set(Decoder::_decodeObject(str, startPos)); pos += startPos; } break; case '"': json = new Value::String(); json->set(Decoder::_decodeString(str)); pos += (json->getString().length() + 2); break; case '[': { int startPos = 0; json = new Value::Array(); (dynamic_cast<Value::Array*>(json))->set(Decoder::_decodeArray(str, startPos)); pos += startPos; } break; case 't': case 'f': json = new Value::Boolean(); (dynamic_cast<Value::Boolean*>(json))->set(Decoder::_decodeBoolean(str)); if (value[pos] == 't') { pos += 4; } else { pos += 5; } break; case 'n': json = new Value::Null(); Decoder::_decodeNull(str); pos += 4; break; default: { int startPos = 0; json = new Value::Numeric(); (dynamic_cast<Value::Numeric*>(json))->set(Decoder::_decodeNumeric(str, startPos)); pos += startPos; } } } return json; }