faq | docs | tutorials | guide | reference | contact | home  

ADVANCED FGL

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.

See the engine startup documentation for additional information on using preloaded libraries.

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.

#####