delphijedi-code-library

need help with interesting call to JCL's TEvaluator


i'm using JCL's expression evaluator TEvaluator (a marvelous creation donated by barry kelly). (THANK YOU barry!)

background

i've used the AddFunc method.

function MyFunc:double;
begin
  // calculations here
  Result:=1;  
end;

you can use the AddFunc method to make the function available:

  AddFunc('MyFunc', MyFunc);

here's the problem...

i need to call a method on an object instead of a standalone routine.

the reason is that i have a list of objects that provide the values.

say we have a list of vehicle objects. each object has a Weight function. i want to be able to make available each object's weight available for use in the formula.

a silly example but it's easy to explain:

type
  TVehicle=class
  private
  public
    function Weight:double;
  end;

function StrangeCalculation:double;
var
  vehicle:TVehicle;
begin
  for iVehicle = 0 to Count - 1 do
    begin
      vehicle:=GetVehicle(iVehicle);
      // E2250 There is no overloaded version of 'AddFunc' that can be called with these arguments
      eval.AddFunc(vehicle.Name, vehicle.Weight);
    end;

  Result:=eval.Evaluate('JeepTJWeight + FordF150Weight * 2');
end;

my options:

  1. AddVar( ) or AddConst( ) -- but that isn't so great because i need to be able to raise an exception if the value is not available.

  2. AddFunc( ) with standalone functions. can't do that because the names of (and number of) variables is unknown until runtime.

  3. modify the object to add a callback if the variable isn't found. i have actually done this but needed to edit a copy of the source to call back to make it do this.

  4. make an AddFunc( ) that's able to use method functions.

option #3 is actually built but an additional AddFunc would be nicer. the trouble is i don't know what method prototype to provide. i thought TMethod would be the way but my knowledge is too limited here... here was my unsuccessful attempt but i still get "E2250 There is no overloaded version of 'AddFunc' that can be called with these arguments" at the eval.AddFunc() call like before.

TFloat64MethodFunc = function(c:pointer): TFloat64;

procedure TEasyEvaluator.AddFunc(const AName: string; AFunc: TFloat64MethodFunc);
begin
  FOwnContext.Add(TExprFloat64MethodFuncSym.Create(AName, AFunc));
end;

TExprFloat64MethodFuncSym = class(TExprAbstractFuncSym)
private
  FFunc: TFloat64MethodFunc;
public
  constructor Create(const AIdent: string; AFunc: TFloat64MethodFunc);
  function Evaluate: TFloat; override;
// not using   function Compile: TExprNode; override;
end;

thank you for your help!

mp


Solution

  • figured it out...

    TFloat64MethodFunc = function: TFloat of object;