Analytics and script function?

Hello! Is it possible to link a function from the Analytics library to a Delphi application function?

For example, the program contains a function:
function Solve(S: string): Double;

Can I somehow "register" or link it to TTranslator? To further evaluate the expression:
"2 * sin(Pi) + Solve('diameter')"

In other words, is it possible in TTranslator to use a function with string parameters to organize access to the script?

Please see this blog post that explains this:

Thanks Bruno, I've seen these possibilities in the help documentation. As I understand, TTranslator works only with identifiers that it "knows"... But I need to call a function with arguments that are not TTranslator's variables. I need to pass an arbitrary string to a function, process it inside the program and return the result to an expression.

In my example above, variable 'diameter' belongs to the internal script and the translator does not know about it. It is important for me that when executing the Solve function, I can programmatically handle the 'diameter' and return the Solve value to the translator.

Maybe it is possible to control the execution of the Solve function programmatically, and programmatically generate its value, which will be returned to TTranslator?

The question can be put this way. How can I use a physical quantity with units from the Physics package in TTranslator, for example:

'2 * sin(Pi) + 45 kN'

where 45 kN — force, physical quantity.

Or in other case, how can I assign a value and units to variable using Analytics expression:

'F := 45 kN;'
'2 * sin(Pi) + F'

Can't you return what you internally treat as a variable by a function you declare to TTranslator?

The user enters this variable in the script (for example, via PascalScript) and TTranslator at the stage of parsing the expression does not know about this variable.

When TTranslator sees such unknown variable, it throws an exception. Therefore, I would like to programmatically calculate its value and use it in the final TTranslator expression. Planning to use some function Solve(s: string): TFloat which knows TTranslator.

Am I right?

So far, I haven't been able to create a function that can take a string as an argument and return a string...

Is it possible to override these methods to work with strings?

type
  TScriptFunction = class(TFunction)
  protected
    function GetArgumentTypes: TArray<PTypeInfo>; override;
    function GetResultType: PTypeInfo; override;
  end;

function TScriptFunction.GetArgumentTypes: TArray<PTypeInfo>;
begin
  // string argument
end;

function TScriptFunction.GetResultType: PTypeInfo;
begin
  // string result
  Result := TypeInfo(string);
end;

Vitalii,
the only way to link to a Delphi function is creating and registering a new Analytics function.
How to do this please see docs http://www.tmssoftware.biz/download/manuals/TMS%20ANALYTICS%20Delphi%20Development.pdf
p 42.

1 Like

For using quantity with units you need to register your converters for the translator
those must convert a string of quantity with units to the structure of some type.
An example of this is a common fracture converter
See the code TFractionLiterals.Initialize.
If you then want to use math operations with these values,
you must override and register the Operators for these value types.
See doc on p. 37.
I hope you understand that you must not add quantities with different
dimensions as in your example '2 * sin(Pi) + 45 kN'

1 Like

Vitalii,
you can create and register a function with string arguments.
But it will not work by default, because the core of the Analytics library
does not include 'string' type in formulae.
So, you also need creating and registering parsers those can
parse the 'string' literals, like in Analytics.Fractions package.

1 Like

Thank you, Sergey! Yes, of course I operate in expressions with the same units of measurement.
As you said, I create

TMathPhysicalQuantity = packed record
and
TMathPhysicalQuantityVariable = class sealed (TScalarVariable)

types. Everything is generally clear, but there is a problem with getting the value of TMathPhysicalQuantityVariable.

For example, expression is:
a:=10 cm

Program creates a variable a: TMathPhysicalQuantityVariable with correct Value (10) and Units (cm). Then I am calling the method of TFormula:
V := F.Calculate;

How can I get the result after that (Value and Units) using V? So far, the result indicates only V.AsType<TFloat>...

Vitalii,
could you specify the expression of F?
Calculate method always return a TValue.
But this is a container for any type, so in contains the value
of type returned by the evaluation of the expression.
If the result of the expression was of type TMathPhysicalQuantity
you can use V.AsType<TMathPhysicalQuantity> to get the value.

It's strange — after Calculate, F.ResultType.Name = TMathPhysicalQuantity, but
V.IsType<TMathPhysicalQuantity> returns False and V.IsType<TFloat> returns True.

Accordingly, when I try to access the variable directly V.AsType<TMathPhysicalQuantity>, I get an exception.

My test expression is just a simple variable, without any operations:

a:=10 cm // here add a:TMathPhysicalQuantityVariable to the translator
F:=Translator.BuildFormula('a'); // here no exceptions
V:=F.Calculate; // here we get a TFloat, not TMathPhysicalQuantity

I think I gave incomplete type information to the translator, but where exactly..?

The problem seems to be resolved. I didn't override the GetValue function of the variable class, I needed to write
Result := TValue.From(FPhysicalQuantity).

Thanks for the help!

1 Like