segunda-feira, 29 de outubro de 2007

Execute code dinamically with Caché

...Or How to evaluate and execute an user input's expression

The scenario: with the application, an user can input some math expressions, using variables previously defined (by himself or another users). These variables might be simple or they might depend on some parameter. An example of expression is below:

(0.50 * ([VAR1(I)] / [VAR1(0)])) + (0.50 * [VAR2])

where:

  • VAR1(I) is a variable, which depends on parameter "I".

  • VAR1(0) is a variable (in fact, the same variable above), but depends on another parameter, "0".

  • VAR2 is a simple variable.


By convention, variables are written between "[]". Most variables are in fact, historical series of values, and those parameters indicate the specific time/period to be considered.

The problem: given a time interval, I need the value the expression evaluates to. Or, with another terms, I need to execute the expression, as if it was part of the program. Some other script languages have the eval function, which takes a text (i.e., an String) and executes it as if it were program code. In this link, an example of JavaScript's eval(). With Caché Object Script, we have the command XECUTE, which does the same thing, it gets the content of an string and executes it, i.e., it does macro substitution.

Well, even with this feature, I still need to identify within the %String, each variable. To make this, I wrote a little function, which I put in a .MAC file:

(A snapshot of the function, the text source code is here.)

For this function, we pass as parameters: the expression, two characters used to delimit what is considered a variable, (in our case, the characters "[" and "]"), a %String to be place where each variable was, and another character to delimit parts of %String (something used a lot with MUMPS-like systems, to create lists - without list functions - see here some discussion.)

Using the expression above in this function, with "?" as the %String to replace the variables, and "~" as delimiting character, we get:

(0.50 * (? / ?)) + (0.50 * ?)~VAR1(I)~VAR1(0)~VAR2

The next step, we get from the system the value of each variable, and replace it within the expression. I will not show these steps, since they are very specific to our problem. After that, our expression String is something like:

(0.50 * (12.3 / 10.88)) + (0.50 * 10)

Note that the expression is mathematically correct, and the precedence of operator is explicit with the use of parenthesis. This REALLY is something to be done, since Caché DOES NOT follow math conventions of operators precedence, as I already posted.

Now, we can finally execute the expression. First, we set the command SET inside a %String, as follows:

SET someVariable = "SET result = " _ stringWithExpression

And then we call XECUTE:

XECUTE someVariable

That's it! The value of the evaluated expression is in variable "result"! Using XECUTE is very handy, but you might pay attention to not abuse it's use, since it can turn your code into a really great mess!

0 comentários: