2012-07-04 28 views
3

我使用ICompiledBinding接口来判断简单的表达式,如果我用文字像(2*5)+10工作正常,但是当我尝试编译像2*Pi代码失败,出现错误:如何使用ICompiledBinding来评估包含`Pi`常量的表达式?

EEvaluatorError:Couldn't find Pi

这是我目前代码

{$APPTYPE CONSOLE} 

uses 
    System.Rtti, 
    System.Bindings.EvalProtocol, 
    System.Bindings.EvalSys, 
    System.Bindings.Evaluator, 
    System.SysUtils; 


procedure Test; 
Var 
    RootScope : IScope; 
    CompiledExpr : ICompiledBinding; 
    R : TValue; 
begin 
    RootScope:= BasicOperators; 
    //Compile('(2*5)+10', RootScope); //works 
    CompiledExpr:= Compile('2*Pi', RootScope);//fails 
    R:=CompiledExpr.Evaluate(RootScope, nil, nil).GetValue; 
    if not R.IsEmpty then 
    Writeln(R.ToString); 
end; 

begin 
try 
    Test; 
except 
    on E:Exception do 
     Writeln(E.Classname, ':', E.Message); 
end; 
Writeln('Press Enter to exit'); 
Readln; 
end. 

所以我怎么可以评估其中包含使用ICompiledBinding接口Pi常量表达式?

回答

5

据我所知存在两个选项

1)您可以使用TNestedScope类传递BasicOperatorsBasicConstants范围initializate的IScope接口。

(该BasicConstants范围定义为零,真,假,和Pi)

Var 
    RootScope : IScope; 
    CompiledExpr : ICompiledBinding; 
    R : TValue; 
begin 
    RootScope:= TNestedScope.Create(BasicOperators, BasicConstants); 
    CompiledExpr:= Compile('2*Pi', RootScope); 
    R:=CompiledExpr.Evaluate(RootScope, nil, nil).GetValue; 
    if not R.IsEmpty then 
    Writeln(R.ToString); 
end; 

2),你可以使用这样的句子手动添加pI值的范围。

TDictionaryScope(RootScope).Map.Add('Pi', TValueWrapper.Create(pi)); 

,代码看起来像这样

Var 
    RootScope : IScope; 
    CompiledExpr : ICompiledBinding; 
    R : TValue; 
begin 
    RootScope:= BasicOperators; 
    TDictionaryScope(RootScope).Map.Add('Pi', TValueWrapper.Create(pi)); 
    CompiledExpr:= Compile('2*Pi', RootScope); 
    R:=CompiledExpr.Evaluate(RootScope, nil, nil).GetValue; 
    if not R.IsEmpty then 
    Writeln(R.ToString); 
end;