コード例 #1
0
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;
}
コード例 #2
0
ファイル: env_context.c プロジェクト: shaunamarie/core
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;
    }
}
コード例 #3
0
ファイル: env_context.c プロジェクト: shaunamarie/core
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;
    }
}
コード例 #4
0
ファイル: env_context.c プロジェクト: jeffali/core
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;
    }
}
コード例 #5
0
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;
}
コード例 #6
0
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;
}
コード例 #7
0
ファイル: env_context.c プロジェクト: jeffali/core
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;
    }
}
コード例 #8
0
ファイル: arithm_eval.c プロジェクト: LinuxCNC/linuxcnc
/* 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();
		}
	}
}
コード例 #9
0
ファイル: logic_expressions.c プロジェクト: swills/core
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);
    }
}
コード例 #10
0
ファイル: arithm_eval.c プロジェクト: LinuxCNC/linuxcnc
/* 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;
}
コード例 #11
0
ファイル: logic_expressions.c プロジェクト: cstroe/core
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);
    }
}
コード例 #12
0
ファイル: Attribute.cpp プロジェクト: welcheb/jemris
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;
}
コード例 #13
0
ファイル: Attribute.cpp プロジェクト: welcheb/jemris
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;

}
コード例 #14
0
ファイル: Attribute.cpp プロジェクト: welcheb/jemris
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;

}