TCHAR * EVAL::EvalFunction(TCHAR * pExpr, double * pValue, INT * pError) { EVAL_EAT_WHITE( pExpr ); TCHAR * pEnd = pExpr; while( isalnum(* pEnd) ) pEnd++; TCHAR szFun[2048]; INT nLen = pEnd - pExpr; if( nLen > 0 ) { strncpy( szFun, pExpr, nLen ); szFun[nLen] = '\0'; strlwr(szFun); } else { * pError = EVAL_ERROR_WRONG_SYNTAX; return pExpr; } INT nFunction; if( hashFunctions.Lookup( szFun, nFunction ) ) { pExpr = pEnd; } else { * pError = EVAL_ERROR_FUNCTION_NOT_DEFINED; return pExpr; } INT argc = 0; double argv[EVAL_MAX_ARGUMENT_COUNT]; EVAL_EAT_WHITE( pExpr ); if( * pExpr == '(' ) pExpr++; // skip '(' else { * pError = EVAL_ERROR_WRONG_SYNTAX; return pExpr; } EVAL_EAT_WHITE( pExpr ); if( * pExpr != ')' ) { // not a void parameter function pExpr = EvalExpression( pExpr, & (argv[argc++]), pError ); if( * pError ) return pExpr; } EVAL_EAT_WHITE( pExpr ); TCHAR op = * pExpr; while( op == ',' ) { pExpr++; // skip commma operator EVAL_EAT_WHITE( pExpr ); pExpr = EvalExpression( pExpr, & (argv[argc++]), pError ); if( * pError ) return pExpr; EVAL_EAT_WHITE( pExpr ); op = * pExpr; } EVAL_EAT_WHITE( pExpr ); if( * pExpr == ')' ) pExpr++; // skip ')' else { * pError = EVAL_ERROR_WRONG_SYNTAX; return pExpr; } if( EvalFunction( nFunction, argc, argv, pValue ) ) { } else { * pError = EVAL_ERROR_FUNCTION_ARGUMENT_COUNT; return pExpr; } return pExpr; }
bool IsDefinedClass(const EvalContext *ctx, const char *context, const char *ns) { ParseResult res; if (!context) { return true; } res = ParseExpression(context, 0, strlen(context)); if (!res.result) { char *errexpr = HighlightExpressionError(context, res.position); CfOut(OUTPUT_LEVEL_ERROR, "", "Unable to parse class expression: %s", errexpr); free(errexpr); return false; } else { ExpressionValue r = EvalExpression(ctx, res.result, &EvalTokenAsClass, &EvalVarRef, (void *)ns); FreeExpression(res.result); CfDebug("Evaluate(%s) -> %d\n", context, r); /* r is EvalResult which could be ERROR */ return r == true; } }
static bool EvalWithTokenFromList(EvalContext *ctx, const char *expr, StringSet *token_set) { ParseResult res = ParseExpression(expr, 0, strlen(expr)); if (!res.result) { char *errexpr = HighlightExpressionError(expr, res.position); CfOut(OUTPUT_LEVEL_ERROR, "", "Syntax error in expression: %s", errexpr); free(errexpr); return false; /* FIXME: return error */ } else { ExpressionValue r = EvalExpression(ctx, res.result, &EvalTokenFromList, &EvalVarRef, token_set); FreeExpression(res.result); /* r is EvalResult which could be ERROR */ return r == true; } }
bool IsDefinedClass(const EvalContext *ctx, const char *context, const char *ns) { ParseResult res; if (!context) { return true; } res = ParseExpression(context, 0, strlen(context)); if (!res.result) { Log(LOG_LEVEL_ERR, "Unable to parse class expression '%s'", context); return false; } else { EvalTokenAsClassContext etacc = { .ctx = ctx, .ns = ns }; ExpressionValue r = EvalExpression(res.result, &EvalTokenAsClass, &EvalVarRef, &etacc); FreeExpression(res.result); /* r is EvalResult which could be ERROR */ return r == true; } }
TCHAR * EVAL::EvalParentheses(TCHAR * pExpr, double * pValue, INT * pError) { EVAL_EAT_WHITE( pExpr ); if( * pExpr == '(' ) pExpr++; // skip '(' else { * pError = EVAL_ERROR_INTERNAL; return pExpr; } EVAL_EAT_WHITE( pExpr ); pExpr = EvalExpression( pExpr, pValue, pError ); if( * pError ) return pExpr; EVAL_EAT_WHITE( pExpr ); if( * pExpr == ')' ) pExpr++; // skip ')' else { * pError = EVAL_ERROR_WRONG_SYNTAX; return pExpr; } return pExpr; }
TCHAR * EVAL::Evaluate(TCHAR * pExpr, double * pValue, INT * pError) { if( ! bInitialized ) Initialize(); * pValue = 0.0; * pError = EVAL_ERROR_SUCCESSFUL; EVAL_EAT_WHITE( pExpr ); pExpr = EvalExpression( pExpr, pValue, pError ); if( * pError == EVAL_ERROR_SUCCESSFUL && * pExpr != '\0' ) * pError = EVAL_ERROR_WRONG_SYNTAX; if( * pError == EVAL_ERROR_SUCCESSFUL ) hashVariables.SetAt("ans", * pValue); return pExpr; }
static bool EvalWithTokenFromList(const char *expr, StringSet *token_set) { ParseResult res = ParseExpression(expr, 0, strlen(expr)); if (!res.result) { Log(LOG_LEVEL_ERR, "Syntax error in expression '%s'", expr); return false; /* FIXME: return error */ } else { ExpressionValue r = EvalExpression(res.result, &EvalTokenFromList, &EvalVarRef, token_set); FreeExpression(res.result); /* r is EvalResult which could be ERROR */ return r == true; } }
/* VarDest := ArithmExpr */ void MakeCalc(char * CalcString,int VerifyMode) { char StrCopy[ARITHM_EXPR_SIZE+1]; /* used for putting null char after first expr */ int TargetVarType,TargetVarOffset; int Found = FALSE; /* null expression ? */ if (*CalcString=='\0' || *CalcString=='#') return; strcpy(StrCopy,CalcString); Expr = StrCopy; if (IdentifyFinalVar(Expr,&TargetVarType,&TargetVarOffset)) { /* flush var found */ Expr++; do { Expr++; } while( (*Expr!='@') && (*Expr!='\0') ); Expr++; /* verify if there is the '=' or ':=' */ do { if (*Expr==':') Expr++; if (*Expr=='=') { Found = TRUE; Expr++; } if (*Expr==' ') Expr++; } while( !Found && *Expr!='\0' ); while( *Expr==' ') Expr++; if (Found) { arithmtype EvalExpr; //printf("Calc - Eval String=%s\n",Expr); EvalExpr = EvalExpression(Expr); //printf("Calc - Result=%d\n",EvalExpr); if (!VerifyMode) { WriteVar(TargetVarType,TargetVarOffset,(int)EvalExpr); } #ifdef GTK_INTERFACE else { if ( !TestVarIsReadWrite( TargetVarType, TargetVarOffset ) ) { ErrorDesc = "Target variable must be read/write !"; SyntaxError(); } } #endif } else { ErrorDesc = "Missing := to make operate"; SyntaxError(); } } }
ExpressionValue EvalExpression(const Expression *expr, NameEvaluator nameevalfn, VarRefEvaluator varrefevalfn, void *param) { switch (expr->op) { case OR: case AND: { ExpressionValue lhs = EXP_ERROR, rhs = EXP_ERROR; lhs = EvalExpression(expr->val.andor.lhs, nameevalfn, varrefevalfn, param); if (lhs == EXP_ERROR) { return EXP_ERROR; } rhs = EvalExpression(expr->val.andor.rhs, nameevalfn, varrefevalfn, param); if (rhs == EXP_ERROR) { return EXP_ERROR; } if (expr->op == OR) { return lhs || rhs; } else { return lhs && rhs; } } case NOT: { ExpressionValue arg = EvalExpression(expr->val.not.arg, nameevalfn, varrefevalfn, param); if (arg == EXP_ERROR) { return EXP_ERROR; } else { return !arg; } } case EVAL: { ExpressionValue ret = EXP_ERROR; char *name = EvalStringExpression(expr->val.eval.name, varrefevalfn, param); if (name == NULL) { return EXP_ERROR; } ret = (*nameevalfn) (name, param); free(name); return ret; } default: FatalError("Unexpected class expression type is found: %d", expr->op); } }
/* Expr1 ... Expr2 where ... can be : < , > , = , <= , >= , <> */ int EvalCompare(char * CompareString) { char * FirstExpr,* SecondExpr = NULL; char StrCopy[ARITHM_EXPR_SIZE+1]; /* used for putting null char after first expr */ char * SearchSep; char * CutFirst; int Found = FALSE; int BoolRes = 0; /* null expression ? */ if (*CompareString=='\0' || *CompareString=='#') return BoolRes; strcpy(StrCopy,CompareString); /* search for '>' or '<' or '=' or '>=' or '<=' */ CutFirst = FirstExpr = StrCopy; SearchSep = CompareString; do { if ( (*SearchSep=='>') || (*SearchSep=='<') || (*SearchSep=='=') ) { Found = TRUE; *CutFirst = '\0'; CutFirst++; SecondExpr = CutFirst; /* 2 chars if '>=' or '<=' or '<>' */ if ( *CutFirst=='=' || *CutFirst=='>') { CutFirst++; SecondExpr = CutFirst; } } else { SearchSep++; CutFirst++; } } while (*SearchSep!='\0' && !Found); if (Found) { arithmtype EvalFirst,EvalSecond; //printf("EvalCompare FirstString=%s , SecondString=%s\n",FirstExpr,SecondExpr); EvalFirst = EvalExpression(FirstExpr); EvalSecond = EvalExpression(SecondExpr); //printf("EvalCompare ResultFirst=%d , ResultSecond=%d\n",EvalFirst,EvalSecond); /* verify if compare is true */ if ( *SearchSep=='>' && EvalFirst>EvalSecond ) BoolRes = 1; if ( *SearchSep=='<' && *(SearchSep+1)!='>' && EvalFirst<EvalSecond ) BoolRes = 1; if ( *SearchSep=='<' && *(SearchSep+1)=='>' && EvalFirst!=EvalSecond ) BoolRes = 1; if ( (*SearchSep=='=' || *(SearchSep+1)=='=') && EvalFirst==EvalSecond ) BoolRes = 1; } else { ErrorDesc = "Missing < or > or = or ... to make compare"; SyntaxError(); } //printf("Eval FinalBoolResult = %d\n",BoolRes); return BoolRes; }
ExpressionValue EvalExpression(const Expression *expr, NameEvaluator nameevalfn, VarRefEvaluator varrefevalfn, void *param) { switch (expr->op) { case LOGICAL_OP_OR: case LOGICAL_OP_AND: { ExpressionValue lhs = EXPRESSION_VALUE_ERROR, rhs = EXPRESSION_VALUE_ERROR; lhs = EvalExpression(expr->val.andor.lhs, nameevalfn, varrefevalfn, param); if (lhs == EXPRESSION_VALUE_ERROR) { return EXPRESSION_VALUE_ERROR; } rhs = EvalExpression(expr->val.andor.rhs, nameevalfn, varrefevalfn, param); if (rhs == EXPRESSION_VALUE_ERROR) { return EXPRESSION_VALUE_ERROR; } if (expr->op == LOGICAL_OP_OR) { return lhs || rhs; } else { return lhs && rhs; } } case LOGICAL_OP_NOT: { ExpressionValue arg = EvalExpression(expr->val.not.arg, nameevalfn, varrefevalfn, param); if (arg == EXPRESSION_VALUE_ERROR) { return EXPRESSION_VALUE_ERROR; } else { return !arg; } } case LOGICAL_OP_EVAL: { ExpressionValue ret = EXPRESSION_VALUE_ERROR; char *name = EvalStringExpression(expr->val.eval.name, varrefevalfn, param); if (name == NULL) { return EXPRESSION_VALUE_ERROR; } else if (0 == strcmp("true", name)) { ret = EXPRESSION_VALUE_TRUE; } else if (0 == strcmp("false", name)) { ret = EXPRESSION_VALUE_FALSE; } else { ret = (*nameevalfn) (name, param); } free(name); return ret; } default: ProgrammingError("Unexpected class expression type is found: %d", expr->op); } }
bool Attribute::SetMember (std::string expr, const vector<Attribute*>& obs_attribs, bool verbose){ //set my own symbol m_symbol_name = m_prototype->GetName()+"x"+m_name; //attribute represents a std::string //if (GetTypeID()==typeid(std::string*).name()) { WriteMember(expr); return true; } //attribute represents a PulseAxis if (GetTypeID()==typeid(PulseAxis*).name()) { if (expr=="RF") { WriteMember(AXIS_RF); return true; } if (expr=="GX") { WriteMember(AXIS_GX); return true; } if (expr=="GY") { WriteMember(AXIS_GY); return true; } if (expr=="GZ") { WriteMember(AXIS_GZ); return true; } else { WriteMember(AXIS_VOID); return true; } } //GiNaC expressions Prototype::ReplaceString(expr,"step","csgn"); if (expr.find("I", 0)!=std::string::npos) m_complex = true; m_subjects.clear(); m_symlist.remove_all(); //GiNaC::symbol d(m_sym_diff); //loop over all possibly observed subjects for (unsigned int i=0; i<obs_attribs.size() ; i++) { //convert string "a1","a2", ... to the matching symbol name Attribute* subject_attrib = obs_attribs.at(i); std::string SymbolName = subject_attrib->GetPrototype()->GetName() + "x" + subject_attrib->GetName(); stringstream key; key << "a" << i+1; if (!Prototype::ReplaceString(expr,key.str(),SymbolName)) continue; //still here? the attribute was in the expression, so it is an observed subject AttachSubject( subject_attrib ); m_symlist.append( get_symbol(SymbolName) ); } //cout << "!!! " << GetPrototype()->GetName() << " : " << expr << " , " << m_symlist << endl; m_formula = expr; //stop for strings if (GetTypeID()==typeid(std::string*).name()) { EvalExpression (); return true; } //build GiNaC expression (maybe not successful at first call, if subjects still missing) try { m_expression = GiNaC::ex(m_formula,m_symlist); //differentiation of expression? if (m_diff>0) { m_expression = m_expression.diff(get_symbol(m_sym_diff),m_diff); stringstream se; se << m_expression; m_formula = se.str(); } //test the expression evaluation once EvalExpression (); } catch (exception &p) { if ( verbose ) { cout << "Warning in " << m_prototype->GetName() << ": attribute " << GetName() << " can not evaluate its GiNaC expression E = " << expr << ". Reason: " << p.what() << endl; } return false; } return true; }
double Attribute::EvalCompiledNLGExpression (double const x, double const y ,double const z, double const g ) { //cout << GetPrototype()->GetName() << " ?? at pointer num " << m_cur_fp << " -> compiled = " << m_compiled.at(m_cur_fp) << endl; if (m_nlgfp == NULL && m_ginac_excomp) { //substitute all attributes with numbers in GiNaC expression, except the attribute //which serves as the free parameter for runtime compilation GiNaC::lst symlist; GiNaC::lst numlist; for (unsigned int i=0; i<m_subjects.size() ; i++) { Attribute* a = m_subjects.at(i); if (a->GetName() == "NLG_posX") continue; if (a->GetName() == "NLG_posY") continue; if (a->GetName() == "NLG_posZ") continue; if (a->GetName() == "NLG_value") continue; symlist.append( get_symbol(a->GetSymbol()) ); if (a->GetTypeID()==typeid( double*).name()) { numlist.append(a->GetMember <double>() ); continue; } if (a->GetTypeID()==typeid( int*).name()) { numlist.append(a->GetMember <int>() ); continue; } if (a->GetTypeID()==typeid( long*).name()) { numlist.append(a->GetMember <long>() ); continue; } if (a->GetTypeID()==typeid(unsigned*).name()) { numlist.append(a->GetMember<unsigned>() ); continue; } if (a->GetTypeID()==typeid( bool*).name()) { numlist.append(a->GetMember <bool>() ); continue; } } GiNaC::ex e = GiNaC::evalf((symlist.nops()==0)?m_expression:m_expression.subs(symlist,numlist)); try { compile_ex (e, get_symbol(GetPrototype()->GetAttribute("NLG_posX")->GetSymbol()), get_symbol(GetPrototype()->GetAttribute("NLG_posY")->GetSymbol()), get_symbol(GetPrototype()->GetAttribute("NLG_posZ")->GetSymbol()), get_symbol(GetPrototype()->GetAttribute("NLG_value")->GetSymbol()), m_nlgfp); //cout << " compiling attribute " << GetName() << " of module " << GetPrototype()->GetName() << endl; } catch (exception &p) { cout << " Warning: attribute " << GetName() << " of module " << GetPrototype()->GetName() << endl << endl << " function Attribute::EvalCompiledNLGExpression" << endl << " No external runtime compiler available: " << p.what() << endl << " Falling back to (slow) analytic evaluation!" << endl << endl << " Hint: if you have a shell and gcc on your system, create the one-liner " << endl << endl << " #!/bin/sh" << endl << " gcc -x c -fPIC -shared -o $1.so $1" << endl << endl << " name it \"ginac-excompiler\", and put it somewhere in your search path." << endl << endl; m_ginac_excomp = false; } } //if compilation failed, invoke slow analytic evaluation if (!m_ginac_excomp ) { *((double*) GetPrototype()->GetAttribute("NLG_posX")-> GetAddress()) = x; *((double*) GetPrototype()->GetAttribute("NLG_posY")-> GetAddress()) = y; *((double*) GetPrototype()->GetAttribute("NLG_posZ")-> GetAddress()) = z; *((double*) GetPrototype()->GetAttribute("NLG_value")-> GetAddress()) = g; EvalExpression(); return *((double*) GetAddress()); } //invoke fast runtime compiled routines if ( m_nlgfp != NULL ) return m_nlgfp(x,y,z,g); return 0.0; }
double Attribute::EvalCompiledExpression (double const val, std::string const attrib ) { //cout << GetPrototype()->GetName() << " ?? at pointer num " << m_cur_fp << " -> compiled = " << m_compiled.at(m_cur_fp) << endl; if (!m_compiled.at(m_cur_fp)) { //substitute all attributes with numbers in GiNaC expression, except the attribute //which serves as the free parameter for runtime compilation GiNaC::lst symlist; GiNaC::lst numlist; for (unsigned int i=0; i<m_subjects.size() ; i++) { Attribute* a = m_subjects.at(i); if (a->GetName() == attrib) continue; symlist.append( get_symbol(a->GetSymbol()) ); if (a->GetTypeID()==typeid( double*).name()) { numlist.append(a->GetMember <double>() ); continue; } if (a->GetTypeID()==typeid( int*).name()) { numlist.append(a->GetMember <int>() ); continue; } if (a->GetTypeID()==typeid( long*).name()) { numlist.append(a->GetMember <long>() ); continue; } if (a->GetTypeID()==typeid(unsigned*).name()) { numlist.append(a->GetMember<unsigned>() ); continue; } if (a->GetTypeID()==typeid( bool*).name()) { numlist.append(a->GetMember <bool>() ); continue; } } GiNaC::ex e = GiNaC::evalf((symlist.nops()==0)?m_expression:m_expression.subs(symlist,numlist)); //add function pointers m_fp.push_back(NULL); m_fpi.push_back(NULL); //compile the GiNaC expression try { //fairly easy for real valued expressions if (!m_complex) { compile_ex(e, get_symbol(GetPrototype()->GetAttribute(attrib)->GetSymbol()), m_fp.at(m_num_fp)); } //more work to do, since GiNaC::realsymbol does not behave as expected (and it is therefore not used at all) else { stringstream se; se << e; std::string formula = se.str(); std::string sym = GetPrototype()->GetAttribute(attrib)->GetSymbol(); std::string asym = "abs(VarForEvalCompiledExpression)"; Prototype::ReplaceString(formula,sym,asym); GiNaC::lst symlist; symlist.append( get_symbol("VarForEvalCompiledExpression") ); GiNaC::ex ea = GiNaC::ex(formula,symlist); symlist.remove_all(); symlist.append( get_symbol(sym) ); GiNaC::ex ear = ea.real_part(); stringstream ser; ser << ear; formula = ser.str(); if ( Prototype::ReplaceString(formula,asym,sym) ) { ear = GiNaC::ex(formula,symlist); compile_ex(ear, get_symbol(GetPrototype()->GetAttribute(attrib)->GetSymbol()), m_fp.at(m_num_fp)); } GiNaC::ex eai = ea.imag_part(); stringstream sei; sei << eai; formula = sei.str(); if ( Prototype::ReplaceString(formula,asym,sym) ) { eai = GiNaC::ex(formula,symlist); compile_ex(eai, get_symbol(GetPrototype()->GetAttribute(attrib)->GetSymbol()), m_fpi.at(m_num_fp)); } } //cout << " compiling expression " << e << " of attribute " << GetName() << " in module " << GetPrototype()->GetName() << endl; m_num_fp++; } catch (exception &p) { cout << " Warning: attribute " << GetName() << " of module " << GetPrototype()->GetName() << endl << endl << " function Attribute::EvalCompiledExpression" << endl << " No external runtime compiler available: " << p.what() << endl << " Falling back to (slow) analytic evaluation!" << endl << endl << " Hint: if you have a shell and gcc on your system, create the one-liner " << endl << endl << " #!/bin/sh" << endl << " gcc -x c -fPIC -shared -o $1.so $1" << endl << endl << " name it \"ginac-excompiler\", and put it somewhere in your search path." << endl << endl; m_ginac_excomp = false; } m_compiled.at(m_cur_fp) = true; //even if compilation failed, as we don't have to try a second time! } //if compilation failed, invoke slow analytic evaluation if (!m_ginac_excomp ) { *((double*) GetPrototype()->GetAttribute(attrib)-> GetAddress()) = val; EvalExpression(); return *((double*) GetAddress()); } //invoke fast runtime compiled routines if (m_fpi.at(m_cur_fp) != NULL ) m_imaginary = m_fpi.at(m_cur_fp)(val); if ( m_fp.at(m_cur_fp) != NULL ) return m_fp.at(m_cur_fp)(val); return 0.0; }