4GL Programming language
Short, quick-and-dirty, general intro to x4GL
Structure of a program
4GL programming language was born in Informix corp., about 15 years ago. Because of that, and not to conflict with with 4GL as general programming concept (BASIC is in principle also Fourth Generation Language, as opposed to C, that is Third Generation Language), we should refer to basic 4GL syntax as I-4GL.
Today, even among Informix-distributed products, there is distinction among "classic" I-4GL and D4GL (Informix name for 4Js 4gl compiler), that introduced number of language enhancements. Then Informix implemented some of this enhancements back to "classic" 4gl, and added some of it's own (v 7.3), that 4Js in turn implemented in 'Universal Compiler" V3 (this is actual name for 4Js product that Informix distributes under the name "D4GL" - Dynamic 4GL.)
Confused? Why am I not surprised. So here is how we will refer to different implementations of LANGUAGE syntax:
I4GL - Informix non-GUI, a.k.a. "classic" products syntax, V 7.3
D4GL - 4Js extended syntax, including I4GL
A4GL - Aubit 4GL specific syntax, including I4GL.
x4GL - all of the above as general name for all
Lucky for us, Querix decided that it will not change language, and instead do all GUI related configuration from separate configuration files.
Aubit 4GL, as package, and A4GL, as language definition, is a superset of I4GL. Our first aim is to provide full UNCONDITIONAL compatibility with I4GL.
Since this means that 90% of the syntax used in A4GL will be I4GL, and since this document is not intended to be I4GL manual, we strongly suggest that if you refer to existing Informix documentation and tutorials downloadable from there web site, and books about 4gl, like:
Informix Unleashed, (ISBN 0672306506) complete book in HTML format about Informix products, by John McNally. You will find several complete chapters about 4GL language there, including chapters on Informix database servers. You will also learn there that "To develop with a 4gl, the developer does not have to be an expert programmer".
(I have asked the author for permission to include his book in Aubit 4GL distribution, but received no answer)
The rest of this page will serve more like quick and dirty crash course to give you some idea how the I4GL look like, as the language. For A4GL extensions. please refer to the appropriate sections of this manual.
To learn I4GL, refer to Informix manuals for Informix-4GL version 7.3 ( http://www.informix.com or direct links to Informix 4gl by example, Informix 4gl concepts and use, Informix 4gl Reference Manual - please remember that exact locations can change, and if they do, use search function on Informix web site to find new locations of this documents), and third-party books
To learn about A4GL extensions, read this manual
To get some idea about how I4GL looks like, and get some idea about combined I4GL and A4GL functionality, continue reading this page
Structure of a program
A 4gl program consists of a series of modules and forms. Each 4gl module can contain functions and reports and each program must contain exactly one 'main' section and must end in a .4gl extension. C modules can also be included in programs
This section is optional and is of the format :
The database name is actually the DATA SOURCE NAME (DSN) from the ODBC drivers.
This optional section allows you to define variables which are accessible to all modules. There is normally a single file (typically called 'globals.4gl') where variables are defined. All other modules which need these variables then include that file using the a global statement .
DEFINE a INTEGER
Note: In Aubit 4GL the any 'globals' module (containing the GLOBALS / END GLOBALS) must be compiled first.
A function in 4GL is a set of commands which are executed when called from another block of code. A function can accepts parameters and can return values.
A function is defined :
FUNCTION function-name ( parameter-list )
Values are returned using the RETURN keyword:
Each program must contain a main section - it is the starting point in any program.
This optional section allows you to define variables which may be used subsequently:
In its simplest form
DEFINE variable_names datatype
DEFINE CONSTANT constant_name "Value"
DEFINE CONSTANT constant_name Number-Value
More than one variable can be defined as any type in the same statement by separating the names with a comma:
DEFINE a,b,c INTEGER
Available datatypes are :
SMALLINT (2 byte integer)
INTEGER (4 byte integer)
CHAR (Single character 'string')
CHAR(n) (n character string
DECIMAL (These are not fully implemented)
FLOAT (8 byte floating point number - (C double))
SMALLFLOAT (4 byte floating point number - (C float))
DATE (date - number of days since 31/12/1899)
VARCHAR Unimplemented yet
LIKE tablename.columnname '1
RECORD LIKE tablename.* '1
'1 - can only be used when the module has a DATABASE statement These copy the datatypes directly from the database either for a simple column, or to generate an entire record (see below)
Special datatypes are :
ARRAY [n] OF datatype defines an array
RECORD .. END RECORD defines a record structure
These special types are used with the other datatypes.
DEFINE vars ARRAY [n] OF datatype
DEFINE lv_arr ARRAY OF INTEGER
defines an array of 200 elements each being an integer
Elements of an array are indexed from 1 to the number of elements specified.
IMPORTANT: NO BOUNDS CHECKS ARE MADE, accessing elements which are outside those defined (ie <1 or > n) will result in an error (Usually a core dump).
LET lv_arr=201 # this will cause a program fault!
Records are structured groups of data, with the entries are separated by commas.
Elements within a record are accessed via the record name '.' element name.
DEFINE recordname RECORD
DEFINE lv_rec RECORD
Defines a record with two elements.
Record may also be nested and used in conjunction with arrays.
The following are all therefore valid:
DEFINE lv_record ARRAY OF RECORD
DEFINE lv_record RECORD
a ARRAY of INTEGER,
DEFINE lv_record RECORD
Associative arrays allow you to access data from an array using a string as a subscript rather than an integer. For example:
This can be especially useful when dealing with codes and code desciptions:
(This is for illustration, the data would normally be read from a database!)
To define an associate array:
DEFINE name ASSOCIATE [CHAR] (nc) WITH ARRAY [nx] OF datatype
Where nc is the number of characters to use for the index, and nx is the total number of elements that may be stored.
Internally, associate arrays are stored using hash tables, for performance reasons always declare 'nx' larger than is actually required. A factor of two is optimum in most cases.
Again the datatype used in this form of array may be a RECORD, ARRAY etc.
DEFINE lv_asoc1 ASSOCIATE CHAR(10) WITH ARRAY OF INTEGER
DEFINE lv_asoc3 ASSOCIATE (10) WITH ARRAY OF INTEGER
DEFINE lv_asoc2 ASSOCIATE CHAR(10) WITH ARRAY OF RECORD
Constants are defined using
DEFINE CONSTANT name value
DEFINE CONSTANT max_num_vars 30
DEFINE CONSTANT err_string "There is an error"
IF num_vars>max_num_vars THEN
It is also possible to use constants in any subsequent define sections:
DEFINE CONSTANT num_elems 20
DEFINE lv_arr ARRAY [num_elems] OF INTEGER
IF num_vars<=num_elems THEN
(syntax and documentation in Informix manuals)