Welcome to the advanced area of the FGL Foundation website. The information contained
here is designed to consolidate some of the advanced features and uses of FGL. This is not
for the squeamish -- it is not for the new programmer – and it is certainly not the final
word on the subject. But, it is a good place to start to get familiar with some of the
advanced functionality of the FGL environment.
Topics in this Document:
Pack and Unpack
These are two of the most advanced and powerful functions in the FGL language. The pack()
function will take any FGL data type, including complex data structures and non-linear data,
and pack them into a single linear data stream that can be saved to a database, disk, or
transferred via the net. Unpack() will restore the data to its original format.
Along with the data itself, the pack() function will store all of the information
necessary to rebuild the data during a subsequent call to the unpack( ) function within the
packed data stream. This includes references to external libraries and class definitions.
Furthermore, if the unpack() function is restoring object data, it will automatically
interleave the saved data with the referenced objects. For example, if you have an object
that consists of a bunch of top-level information, and it includes several arrays of
additional objects that in turn may include additional string, numeric, array, and other
object data, the pack() function will save all of this information to a single stream.
When the unpack() function is called, the object data that was saved will be restored to
the current object definitions. If the current objects have changed since the data was
saved, the unpack() function will automatically restore active fields, initialize new
fields, and ignore fields that no longer exist.
See the pack(),
unpack(),
IsPackString(), and
PackLibraries()
functions for additional information.
Preload Libraries
FGL’s ability to create binary libraries makes it easy to group classes and functions
for a variety of uses. It is also a convenient way to distribute code in a secure and
efficient manner.
When a web-based application, through an FGL Active Page, references a library, the
engine will dynamically load the library and resolve all internal references as required.
In fact, it is entirely possible to have almost all of the page generation code, or certainly
significant portions, embedded within one or more libraries. This might be in the form of
page header, footer, and body generation components, or specialized segments as required.
When used with Active Pages, the engine will dynamically load and unload libraries as
required by the various web pages of your application. This process is highly optimized --
but never-the-less requires overhead. FGL provides a mechanism to preload one or more
libraries so that they are initialized only once during startup. You do not have to change
your code in any way to utilize this feature and you can enable and disable individual
preloaded libraries as desired.
Forms Automation
FGL provides a number of features for the advanced automation of web forms. This can be
as simple as a web-based data entry screen or as complex as any paper-form you have ever
encountered. FGL accomplishes this through a combination of features and process – all
without the need for 3rd-party additions or plug-ins.
In general, automated web-forms, regardless of their complexity, consist of three primary
components: static textual content, static graphical content, and dynamic textual and/or
graphical content. FGL renders these components as individual layers that can be abstracted
and rendered on-the-fly as needed.
By separating the individual layers, FGL makes it easy to connect a dynamically-rendered
form to a corresponding data object which, through the use of pack() and unpack(), can easily
be stored and retrieved in any variable-length database field or binary file.
FGL provides an optimized special case of dynamic form creation and interaction through
the use of FGL’s “FRX” architecture. This provides a mechanism for the engine to
automatically pre-compile dynamic forms for their optimized use and interaction.
See apTranslate(),
cacheRead(),
and compile()
functions for additional information.
Arrays
FGL’s advanced array functionality provides a number of optimized options for an
extremely advanced data type. In general, arrays can hold any other type of information,
including other arrays and complex data types such as objects and code-blocks.
Array support includes single and multi-dimensional arrays, but also includes sparse and
ragged support. Sparse support means that you can have an array that includes defined
elements for the 1st, 5th, and 5-millionth array entry, and FGL would handle this perfectly
and efficiently.
Ragged support refers to the individual elements within a multi-dimensional array.
Specifically, the 1st array element may contain an array of five numeric values, the 2nd
element may contain only three, the third element may be NULL, and the fourth may contain
a combination of one hundred and three numeric, string, and object values.
Individual elements within multi-dimensional FGL arrays can be addressed traditionally,
as in: a[i][5], or via short-hand, as in: a[i,5], the latter method having a slight
performance edge over the former.
For additional performance enhancement, FGL supports both fixed and dynamic arrays. Fixed
arrays are extremely fast, but you need to know the number of elements in advance. The
array() function is used to define a fixed array and the asize() function can resize a
fixed array if required.
Dynamic arrays do not have to be specifically declared and their size does not have to
be known in advance. They provide the ultimate in flexibility, though they are not quite
as efficient as fixed arrays are. Simply storing a value, such as: a[i,5] = “whatever”,
will automatically create a dynamic array.
Fixed arrays utilize highly-optimized fixed-length memory structures, while dynamic
arrays utilize linked-list architecture with optimized hash table access. Individual
elements within either type of array can be accessed directly or through the anexti()
function (required when “walking” a sparse array).
See the array(),
asize(), and
anexti()
functions for additional information on fixed and dynamic FGL arrays,
as well as the Array Area
of the FGL documentation.
Objects
FGL provides advanced support for procedural, functional, and object oriented programming
methodologies. FGL’s OO implementation includes standard, enhanced, and custom components.
Standard object features include:
- Methods
- Instance variables with initializers
- Variable parameter passing with default initializers
- Support of "self" and shorthand "::" object references
- Class-wide static variables with initializers
- Properties: assign/access/default methods
- Class constants
- Operator overloading
- Inheritance
- Virtual methods
- Base-class overriding
- Private/Public/Protected object elements
- Objects can be passed as parameters, returned from functions, and stored in arrays or any other data type
Enhanced object features include:
- Multiple inheritance: lets classes inherit from multiple base classes
- Virtual classes: when multiple base classes are themselves inheriting from the same base class, provides support for single or multiple instances of the common classes.
- Message renaming: lets developers overcome duplicate names when inheriting from single or multiple base classes
- Compile-time resolution of object interaction for advanced performance
- Optional run-time resolution for maximum flexibility, as in: a."message", a.(var), and (obj).(method)
- Objects are always referential, however object variables can be passed by value or reference
- Complex objects can be "flattened" into data streams and fully restored using the pack() and unpack() functions
Custom object features include:
- Full extension module API provides C-level manipulation of classes, including class creation and registration of C-functions as methods
- API-level maniuplation of FGL objects, including assigning and accessing variables
- Support for per-object memory buffer for use by the extension module builder
- Call-back support for custom pack/unpack object searialization
- Garbage collection call-back for customized resource management
See the Object Area
of the FGL documentation for additional information on the advanced use of objects.
Resource Management
FGL provides a number of convenient and advanced resource management features, including:
automated memory management and garbage collection, optimized thread-pooling and task
management, low-level file manipulation, scoping, caching, and distributed database
integration.
In general, when you use a resource in FGL it is not necessary to perform any “clean-up”
when you are finished with it. Allocation of memory is transparent and automatic – you
simply use it. The engine monitors when it goes out of scope and will automatically release
it at the optimum time. You can force memory to be released by assigning NULL to the
corresponding variable at any time, though this is not required. The only time you might
consider doing this is when simultaneously dealing with extremely large amounts of data in
a low-memory environment.
File handles are likewise automatically maintained by the system. Good programming style
dictates that whenever you open a file using low-level functions you should also close it.
The FGL documentation also recommends this method, however, the engine will treat file
handles in the same way as it does memory – releasing them automatically (closing the file)
when they go out of scope.
The engine’s internal database takes this several steps further. The first request to
access a database will cause the database and accompanying indexes to be opened. Subsequent
calls requesting the opening or closing of the database will be processed by the distributed
database engine and will be management automatically in accordance with performance,
optimization, security, and data integrity considerations.
The engine manages raw-code, binaries, and pre-compiled objects in a similar optimized
manner. The FGL environment always wants to execute the most efficient form of code
available – even if it has to create it and cache it on-the-fly. Clear-text Active Pages
are automatically compiled into APX binary files, libraries are created from compiled FGL
through FGX binary intermediate files, code-blocks are precompiled as are regular
expression (RegEx*) queries, and the internal just-in-time (JIT) compiler maintains a
memory-based cache of the latest optimized executable code.
All of these features combine to provide a powerful and automated set of resources for
the optimized execution of FGL applications. See the
developer's tools for additional information.
Enhancing and Extending FGL
As complete as the FGL environment is, it was never-the-less designed for optimized
enhancement using a number of languages and extensions through the FGL third-party
interface, “TPI”. These enhancements generally fall into one of two categories: simple
integration and advanced integration.
FGL can be enhanced by other languages through the support of industry-standard DLL,
ActiveX, and COM files, as well as .NET and Java assemblies. These can be added to the
base FGL environment through core-registration, thus providing external functionality as
if they were internal components.
Simple integration requires no changes to the existing enhancement component. FGL
provides a mechanism through its funcRegister( ) function (and task-specific variants)
to register enhancement components as directly callable FGL components. This allows any
of the thousands of available industry standard add-ins to work directly with FGL
-- unaltered.
Advanced integration provides enhancement components with robust access to FGL’s
internals, functions, and data structures. Enhancements in this category can be
specifically tailored to support this functionality or an intermediate object can be
created to provide the advanced integration without requiring change to the original
component.
The object-nature of the FGL world, coupled with the environment’s enhancement ability
and numerous abstraction layers, makes FGL an ideal centralized core for inclusion of your
favorite and most treasured add-in components.
Furthermore, the environment’s support of FGL binaries and the dynamic and optimized
loading of FGL libraries provide an ideal platform for expansion, optimization, and
customization.
See the FGL funcRegister(),
netRegister(),
LoadLibrary(), and the
UnLoadLibrary() functions,
as well as the
COM Object
class definition for additional information.
For advanced access to the FifthGen Engine and FGL internals, including
the externalized creation and manipulation of variables, objects, memory, functions,
class registrations, garbage collection, code blocks, and more, access the
FGL External API
for details, documentation, and source code, and examples.
|