TCOMPILE Method

Method for compiling entities of a given type (stored procedures, events, datasets, or windows) into an executable form, as well as all the entities within it, such as code associated with window events within a window or $INSERT records in a stored procedure.

One style of programming we generally try to avoid is placing executable code statements (*) in a "$insert" record (i.e. an STPROCINS entity) and using that in another program because it usually suffers from the following problems:

  • Inserted code cannot be traced properly with the debugger, making it hard to step through a procedure and possibly obscuring variable initialization and manipulation.
  • Changes to the inserted code will force all the hosting stored procedures to need recompilation.
  • The BLint() process that the compiler uses to check for suspected unassigned variables will not follow the $insert statement and process the insert record, making compile time errors more difficult to detect.

However, while developing the new Form Designer we found there was quite a bit of common code that was shared between the various modules used by the form parser and compiler, and we obviously did not want to duplicate this in each one. Normally we would just move the code into a separate stored procedure and call that from each module, but that just adds extra overhead in a process that we really wanted to keep as fast as possible, and so we looked at another option: moving it into an insert record instead. sharing code this way means that it runs "inline", thereby removing the need to create another call-frame, move variables on and off the stack, and so on.

The shared code involved was fairly straightforward, well-tested, and limited to a few small subroutines, so the only real issue to overcome was: how can we easily update any "host" stored procedures in the event of the insert record being changed?

One of the nice things about the OpenInsight repository is that it tracks the various relationships between entities in an application, and some types support a method called TCOMPILE (Tree-Compile) that allows an entity to compile any other entities they are using during the compilation process as well. However, in this case we needed to do the opposite and compile those entities that were using the insert record instead, and so we created a TCOMPILE method for the STPROCINS type that processes this list of "used-by" entities and executes their normal COMPILE method after the insert record has been saved. This results in a simple way to ensure that changes are implemented across any affected programs.

While we wouldn't say we exactly endorse embedding programs in this way, it does remain a useful technique for sharing code in some limited cases, and with the new TCOMPILE method it is now much easier to manage too.

retval = Repository('TCOMPILE', entID, parameter1, parameter2, parameter3)

The arguments in parameter1, parameter2, and parameter3 vary depending on entity type.

The TCOMPILE message has the following parameters

ParameterDescription
Message'TCOMPILE'
entIDentID consists of four elements, which are '*' (asterisk) delimited:

* Application name
* Type ID
* Class ID
* Entity name

Methods are executed as follows: if class specific, execute at the class level; if type specific, execute at the type level; otherwise, execute the method.
parameter1a boolean indicating whether or not the entity should be compiled if it has not been changed since the last compilation
parameter2for windows, a boolean indicating whether cleanup of orphan entities should be done. Ignored for other entity types
parameter3for windows, a boolean indicating whether or not linemarks should be kept.

null = Compilation failed. Use Get_Status() to test for error return.

1 = Compilation not needed.

2 = Compilation successful. Field 2 returns the date and time of compilation.

Note: Stored procedures can be recompiled using the Recompile_Proc subroutine.

Note: Always call the Get_Status function after calling Repository().

Repository() function, Recompile_Proc, Repository("COMPILE"), Get_Repos_Entities(). Also, Stored Procedures chapter in the Guide to Application Development.

/* Compile the window INV_ENTRY, as well as event code in the window */

Declare Function Repository, Get_Status

AppID = @APPID<1>  ;* current application

TypeID = "OIWIN"  ;* OpenInsight windows

ClassID = ""  ;* Not Applicable

Win_Name = 'INV_ENTRY'

recompile_if_unchanged = ''

cleanup_orphan_entities = ''

creserve_linemarks = ''

entid = AppID : '*' : TypeID : '*' : ClassID : '*' : Win_Name

result = Repository("TCOMPILE", entid, recompile_if_unchanged, cleanup_orphan_entities, preserve_linemarks)

*  test result

begin case

   case result = ''

     If Get_Status(ErrCode) then

        call msg(@window, 'Error Message returned: ' : ErrCode)

     end

   case result = 1

        call msg(@window, 'Tree Compilation not needed')

   case result<1> = 2

        call msg(@window, 'Tree compilation successful, compiled at ' : result<2>)

end case
  • guides/programming/programmers_reference_manual/tcompile.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1