Пример #1
0
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;
}
Пример #2
0
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;
    }
}
Пример #5
0
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"));
}
Пример #6
0
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);
    }
Пример #7
0
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);
    }
}
Пример #9
0
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);
}
Пример #10
0
  //---------------------------------------------------------------------------
  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();
  }
Пример #11
0
bool convertBool(IValue &value)
{
    return value.getBool();
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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));
    }
Пример #15
0
  //---------------------------------------------------------------------------
  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];
}
Пример #17
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;
    }