tags:

views:

159

answers:

1

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

+5  A: 

figured it out...

TFloat64MethodFunc = function: TFloat of object;

X-Ray