To understand the Execution Context provided by the Monarch Framework better, it is useful to first review some IBM i® concepts.
Program Execution Management on the IBM i
The basic functions performed by the PEM on the IBM i are:
- Activates a program: Puts a program into a ready-to-execute state.
- Invokes a program: Causes the program to execute.
- Modifies storage allocation: Extends or truncates the allocated process automatic storage area, and extends the allocated process static storage area.
- Deactivates a program: Removes the program from an executable state.
- Destroys a program invocation: Terminates the execution of a program.
Program Activation
All programs executing in the system operate under the control of a Job. The process under which a program is to execute must be established before it can be activated and executed. The primary objective of the activation is to initialize the process's static storage area and initially allocate the areas used. Once a process has been established, PEM can activate a program.
Program Invocation
The invocation function of PEM controls the synchronous
execution of programs within a process. It also allows
control to be passed from one program instruction stream to
another and allows for a subsequent return of control when a
function is complete. The high-level language command to
accomplish invocations is CALL.
Invocation Destruction
When an invoked program relinquishes control, the
associated invocation is deallocated and control passes to
the calling program. Note too that the program remains active
until an explicit deactivation occurs. When the *INLR
indicator is *ON in an RPG program whose invocation is to be
deallocated, the program's activation entry is also
destroyed. The high-level language command used to relinquish
control is RETURN.
Call Instruction
The instruction preserves the calling invocation and
passes control to the external entry point of the program
specified. It also ensures the program is properly activated
before the invocation occurs. In a sequence of program calls,
while the programs are called, they are both active and
invoked. The value of a program's variables, the location of
the cursor in each of the files it has opened, and the
following instruction to execute is: the
program state. When a program returns with
*INLR set *OFF, the program is considered active but not
invoked. Note that should this program be called again, any
variables will retain their current value.
ILE Model
With the advent of ILE, RPG introduced new constructs to take advantage of the facilities available in the new (IL) Environment. The most significant from the PEM point of view were activation groups and procedures.
Activation groups enable a programmer to explicitly
differentiate the areas where program activations are to be
allocated and allow programs to be recursively called.
There are 3 basic types of activation groups: explicitly
named by the user, statically created by the system (like
*DFTACTGRP) and dynamically created by the system to support
those programs marked with an activation group of
*NEW.
A procedure allows better control over the main entry
point of a program while sub-procedures provide a modern
alternative to subroutines. One of the main advantages
of procedures and sub-procedures is the finer control of the
parameters being passed, particularly the ability to omit
parameters via *OMIT and to not pass them at all.
The op-code
CALLB (CALL BOUND) was introduced to support
procedures. CALLB resolves the procedure to be called
at program creation time, whereas
CALL resolves the program at runtime.
ASNA Visual RPG support of PEM
AVR draws its heritage from the implementations of RPG
under IBM i but also strives to participate within the .NET
framework. In IBM i, the
CALL/RETURN instructions were supported by
all major programming languages and it was the preferred
mechanism by which most applications were segmented into
manageable / reusable portions. Most applications
depend upon two programming languages, CL and COBOL or CL and
RPG. However, few utilize more than two
languages.
The .NET framework does not directly support the concept
of a
program (as understood in the IBM i world),
therefore there is no direct support in .NET for the
semantics required to implement CALL/RETURN.
In .NET, applications are partitioned using the concept of a Class. A class defines the operations an object can perform (methods, events, or properties) and defines a value that holds the state of the object (fields). An instance of a class is an object. You access an object's functionality by calling its methods and accessing its properties, events, and fields. There are certain kinds of methods and fields that are shared across all object instances of a class. These fields and methods are "shared" (or "static" in languages like C++ and C#). To access shared methods, all that is needed is the name of the class and not an actual instance of it.
AVR Procedures
AVR 8.0 introduced procedures into the language to facilitate the migration of RPG applications via Monarch. AVR Procedures are similar to AVR functions but have the following differences:
- Are invoked via or in an expression.
- Can have absent and omitted parameters.
- May cause a new activation of the containing class (program).
A class may contain a special procedure named *ENTRY.
This procedure acts as the default
entry point of a class when the class name is used as the
target of a CALLB. The parameters of *ENTRY are also
different. They are just references to global fields defined
at the class (program) level and as such, the
DclSrParm commands may not have type keywords.
When a *ENTRY procedure is invoked, the parameters
passed to it are copied to (or referred by) the global
fields.
The implementation of Procedures by AVR has no direct implementation of activations. Instead, AVR relies on the user providing an activation manager via a static member of the runtime support. Monarch sets up this manager, as we will see later.
As part of the preamble generated by the compiler when expanding the code for a procedure, AVR invokes the activation manager to obtain the proper activation for the program and sets up exception handling routines to trap the ASNA.VisualRPG.Runtime.Return exception (see below).
Visual RPG CALL/CALLB/CALLD/RETURN
Constructs
Because .NET does not provide the support for jobs,
programs, and activation groups, and because AVR must remain
nimble to play well with the rest of the .NET framework and
languages, its implementations of
CALL,
CALLB,
CALLD, and
RETURN are very simple, leaving the burden of
providing the same semantics as IBM i to the user. In the
case of Monarch applications, the Monarch Framework assumes
you will take this responsibility. Let us examine what tools
AVR provides.
AVR implementation of allows the calling of a remote
program. The
CALLB opcode can be used to call a procedure
defined in the same class or a
public procedure in a different class.
CALLD on the other hand, supports a call
to a local Monarch Program on the same assembly, on a
different assembly, or even if the assembly does not yet
exist. This conveniently allows compilation of
programs that reference other programs that are
not compiled yet. This feature is invaluable when
migrating large applications where local program calls
in separate assemblies can be compiled successfully,
even before the application is
fully tested. This replicates the development
cycle on the IBM i and makes AVR a unique language in
that no other languages available for .NET allow dynamic
referencing of assemblies without adding advanced reflection
support by the user.
The implementation that AVR provides for the
RETURN op-code is
also very primitive. It simply throws the exception
ASNA.VisualRPG.Runtime.Return.
