2012-07-04 65 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;