3

我正在使用该ICompiledBinding接口来评估简单的表达式,如果我使用类似的文字(2*5)+10可以正常工作,但是当我尝试编译类似2*Pi代码的内容时会失败并出现错误:

EEvaluatorError: 找不到 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.

那么如何Pi使用 ICompiledBinding 接口评估包含常量的表达式呢?

4

1 回答 1

5

据我所知存在两种选择

1)您可以使用传递和范围的类来初始化IScope接口。TNestedScopeBasicOperatorsBasicConstants

(BasicConstants 范围定义 nil、true、False 和 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;
于 2012-07-04T22:45:39.480 回答