Miva, Miva Script, Miva Empresa, Miva Mia amd Miva Merchant are registered trademarks of the Miva Corporation
 
Ivo Truxa - truXoft control systems: advanced programming and custom IT solutions home / about / webdesign / Miva / automation / contact

http://mivo.truxoft.com
MIVO!
miva beyond limits

 

MIVA®  COMPILER:  Dynamic Function Calls

by Ivo Truxa, 05/29/2002

  1. Miva parser built-in the Virtual Machine
  2. Test script
  3. Return values
  4. Useful links
  5. User Comments

top

Miva parser built-in the Virtual Machine

One of the most often posted problems with the compiler was a simple replacement of a very efficient dynamic function call, that in interpreted Miva Script could be done in the following way:

<MvEVAL EXPR="{&[g.function];()}">

Up to date, the only proposed replacements were using MvIFs (or possibly MvDOs). I have now tested a more efficient and very simple way for doing the same in compiled Miva programs without the necessity to build long MvIF blocks. The method allows also interpreting Miva expressions in real-time (in compiled environment of course).

The Miva Virtual Machine contains an interpreter that is capable of executing functions and expressions (not the tags) in real-time. Currently it may be used only through a tricky code, but I wonder why there is not a simple 'execute()' function that would allow doing the same directly and would allow reading the result simpler!? Any reason for hiding this feature from us, Miva Corp.? I see now that it is possible without any problems, the code is in the Miva Virtual Machine, and it works just fine, so why not offering it officially?

Here is the code - amazingly simple:

<MvFILTER NAME="test" FILTER_TYPE="variable" FILTER="g.function">

The 'test' database has to be open, of course, and it should be empty for the best performance. Better yet is having a single record in it - the NOT test.d.EOF may be then used to test the return result of the function or expression (only true / false). You can assign code to the g.function dynamically in the run-time and you may use functions with and without arguments.

The same code may be used for executing/interpreting Miva expressions (including multiple function calls) without recompiling the program:

<MvFILTER NAME="test" FILTER_TYPE="variable" FILTER="g.expression">

The possibilities of using it are almost unlimited. It can be dangerous similarly as the macro, of course too, so be careful when using it!!!

Please note that if a function is not defined (at user functions) or used (at built-in functions) in the compiled file, you would get a run-time error. So for example you get a run-time error if you try to assign 'glosub(...)' to the filter in run-time and it is nowhere used in the script. Once it is used (coded and compiled), it has also an entry in the function table of the compiled code and can be called in run-time without problems.


top

Test Script

Here is a sample test script, asigning the function name or the expression dynamically from a user input in a HTML form:


<MvFUNCTION NAME="typeMeIn" PARAMETERS="ret">
 <MvCOMMENT>Just for testing</MvCOMMENT>
 <MvFUNCRETURN VALUE="{l.ret}">
</MvFUNCTION>

<FORM ACTION="{s.documenturl}" METHOD="post">
 <INPUT TYPE="text" NAME="filter" VALUE="{g.filter}" SIZE="60">  
 <INPUT TYPE="submit" NAME="ok" VALUE="OK"> 
</FORM>

<MvOPEN NAME="test" DATABASE="test.dbf">
<MvIF EXPR="{len(g.filter)}">
 <MvFILTER NAME="test" FILTER_TYPE="variable" FILTER="g.filter"> 
 <P>Result: <MvEVAL EXPR="{NOT test.d.eof}"></P>
</MvIF>

Compile it, put a test.dbf with one record in the data dir, run it, and type typeMeIn(0) and typeMeIn(1) into the form. It should return the argument. Try different Miva expressions and built-in functions, too. Note that although the filter executes almost any expression, only true / false result is returned through the test.d.EOF. For extracting the result value, please see below.


top

Return values

Jeff Huber wrote:

“I read the online article and I am uncomfortable about the use of the global variable to gain access to the function return but I have an alternative that should work. Passing values by reference.”

Yes, of course, a reference can be used too, but it makes no big difference if used directly - it requires designing all function in this way and does not allow pure built-in functions and Miva expressions. Additionally and unfortunately references do no seem to work yet smoothly in the v0.9 compiler.

Better is writing a small assign function. Again you can use a global variable or a reference for passing the result. The proposed reference is here indeed probably better suited. The following example with the reference does not yet work compiled, although uncompiled there is no problem:


<MvFUNCTION NAME="assign" PARAMETERS="result VAR, expr">
 <MvASSIGN NAME="l.result" VALUE="{l.expr}">
</MvFUNCTION> 

You would then call the functions or expressions in the MvFilter in this way:

assign(variablename,function(arguments))
or
assign(variablename,expression)

For example:

assign(g.ver,'Version ' $ gettoken(s.mivaversion,'.',1) $ '.xx')




Enjoy!
Ivo


top

Some Useful Links

Miva Script Reference Manual
Miva Merchant User List Archive


top

   

Miva and some other terms used on this page are registerd trademarks of the Miva Corporation
copyright  truXoft  © 1997-2010