.
contact contact

Eloquence Language Enhancements

 
.
  A.06.00 Release Notes
[Part 1] [Part 2] [Part 3]


User defined data types

The Eloquence language has been enhanced to support user defined data types. A user defined data type consists of a list of variables, called member variables. When a type is derived it inherits all properties (in this case, the member variables) of the base type. When you derive a type from a base type, you can use the derived type to call functions or subprograms which accept the base type.

Type definition

Type definitions are enclosed in the TYPE .. END TYPE keywords. All variable declarations between will be part of the new data type. When the EXTENDS keyword is present, the new data type is derived from the given base type.
   TYPE TypeName [EXTENDS BaseTypeName]
   END TYPE
The example below defines the data type Tphone, containing the member variables Id, Name$ and Phone$.
   TYPE Tphone
      INTEGER Id
      DIM Name$[30],Phone$[20]
   END TYPE
The example below defines the data type Tphone_ex. Since it is derived from the type Tphone, it includes all member variables of the base type. In addition, it adds the new member variable Comment$.
   TYPE Tphone_ex EXTENDS Tphone
      DIM Comment$[40]
   END TYPE
Please note, that a base type can be defined after a derived type. It must be defined however before a derived type is instantiated.

In addition to a type definition in the program, data types can be defined from the database schema.

   IN DATA SET data_set DEFINE TYPE type_name
Where data_set is either a data set name or number and type_name is the name of the data type.

The example below defines the data type Tcustomer from the data set CUSTOMER.

   DBOPEN(Db$,"",1,S(*))
   ...
   IN DATA SET "CUSTOMER" DEFINE TYPE Tcustomer
A data type has a scope, defining its lifetime and visibility:
  • If a type is defined globally (in the main program), it is available to all subprograms and functions. It is deleted, when another program is LOADed.
  • If defined in a SUB/FN program segment, a type definition is only known inside the subprogram. In addition, it can be passed to other functions and subprograms as an argument. The type definition is deleted when the segment returns.

When defining user defined COM variables, the type definition is deleted when LOADing another program. In order to retain the variable values across programs, you must define an identical type in the new program.

Type instantiation

Since a type definition is merely a blueprint rather than a real object, it must be instantiated before it can be used. This can either be done before execution by using the COM and DIM statements or at runtime with the NEW statement.

DIM and COM statements:

   COM Instance_name:Type_name
   COM Instance_name AS Type_name
   DIM Instance_name:Type_name
   DIM Instance_name AS Type_name
The NEW statement:
   NEW Instance_name:Type_name
   NEW Instance_name AS Type_name
The Instance_name is the variable name and the Type_name is the name of the data type. The instance name and data type name are either separated by a colon or the keyword AS.

The example below defines the variables Phone1 and Phone2. They are of type Tphone.

   DIM Phone1:Tphone
   NEW Phone2 AS Tphone

In addition, the NEW STRUCT statement can be used to create a new, identical copy of the referenced object.

   NEW STRUCT Instance_name=Instance_Name
The example below creates a new object named "Clone". It will be an exact copy of the referenced object "Entry".
   DIM Entry:Tphone
   Entry.Name$="Joe Sample"
   Entry.Phone$="(202) 243 1440"
   NEW STRUCT Clone=Entry

Using member variables

Member variables can be used like any other variable. A member variable is specified by giving the variable name (instance name) and the name of the member variable, separated by a dot.
   Phone1.Comment$="*Fancy Comment*"
   PRINT Phone1.Comment$
In addition to accessing single variables, you can specify the whole object at once. The example below prints all member variables of Entry.
   PRINT STRUCT Entry

The STRUCT statement can also be used to copy the value of an object:

   STRUCT A=B
When copying an object to another, both must be compatible.
  • Both objects must have the same data type. In this case, all member variables are copied.
  • Both objects must have a common base type. In this case, only the common member variables are copied.

Passing a struct to a subprogram or function

When calling a subprogram or function with a STRUCT argument, you can pass an object either anonymously or specify a type name.
   CALL Sub(STRUCT A)
   ...
   SUB Sub(A {AS|:} TypeName)
   SUB Sub(STRUCT A)
Like regular variables, types can either be passed by value or by reference. When passed by value, a copy is passed to the subroutine.

For example:

   TYPE Type
      INTEGER I
   END TYPE
!
   DIM Inst:Type
   Inst.I=0
   CALL Sub(Inst)
   PRINT Inst.I
   CALL Sub((Inst))
   PRINT Inst.I
   STOP
!
   SUB Sub(STRUCT A)
      A.I=A.I+1
   SUBEND
Instances can be passed to a SUBroutine either anonymous or with an associated type.
  • When a type is specified and it is defined globally, the passed variable must either be of the same type or it must have a common base type.
  • Then the type specified is not defined globally, it is defined with the given name from the parent environment.
For example:
! Define type Tsample
   TYPE Tsample
      INTEGER I
      DIM X$[20]
   END TYPE

! DIM variable A with type Tsample
   DIM A AS Tsample

! Pass A to SUB
   CALL Sub1(STRUCT A)
   CALL Sub2(STRUCT A)
   STOP

! Sub1 requires a type Tsample (or any derived type)
   SUB Sub1(A AS Tsample)
      PRINT A.I;A.X$
   SUBEND

! Sub2 does accept an anoymous variable
   SUB Sub2(STRUCT A)
      PRINT A.I;A.X$
   SUBEND

The STRUCT keyword

The STRUCT keyword can be used with some statements to operate on the whole object instead of a single member variable. This is similar to the Array(*) notation in Eloquence which causes an operation on the whole array instead of a single element.

The following statements can be used with STRUCT:

  • PRINT
  • READ
  • PRINT #, READ #
  • IN DATA SET USE, IN DATA SET LIST
  • PACKFMT
  • XPACK, XUNPACK

Runtime type identification

The TYPEOF$ function can be used to identify an instance.

   X$=TYPEOF$(instance_name)
This returns the type name of the given instance.

The IS A operator can be used to categorize an instance.

   IF instance_name IS A type_name THEN ...
If the instance is either of the specified type or derived from it, the IS A operator returns nonzero.

For example:

   TYPE Tbase
      INTEGER A
   END TYPE
   TYPE Tderived EXTENDS Tbase
      INTEGER Q
   END TYPE
!
   DIM Derived:Tderived,Base:Tbase
   DISP "Base is of type ";TYPEOF$(Base)
   DISP "Inst is of type ";TYPEOF$(Derived)
   DISP "Base    is a Tbase    =";Base IS A Tbase
   DISP "Base    is a Tderived =";Base IS A Tderived
   DISP "Derived is a Tbase    =";Derived IS A Tbase
   DISP "Derived is a Tderived =";Derived IS A Tderived
   STOP

Data base integration

The user defined type concept is designed to operate with the Eloquence data base. The IN DATA SET ... DEFINE TYPE statement can be used to define data types from the data base schema at runtime, the PACKFMT, IN DATA SET LIST and IN DATA SET ... USE have been enhanced to support user defined data types. For example:
   DBOPEN(Db$,"",1,S(*))
   ...
   IN DATA SET "CUSTOMER" DEFINE TYPE Tcust
   NEW Cust:Tcust
   IN DATA SET "CUSTOMER" USE STRUCT Cust
   ...
   DBGET(Db$,"CUSTOMER",7,S(*),"@",Buf$,Key$)
   ...
Of course, types can also be defined statically in your program:
   TYPE Tcust
      DIM No$[6]
      DIM Name$[30]
      ...
   END TYPE
   DIM Cust:Tcust
!
   DBOPEN(Db$,"",1,S(*))
   ...
   IN DATA SET "CUSTOMER" USE STRUCT Cust
   ...
   DBGET(Db$,"CUSTOMER",7,S(*),"@",Buf$,Key$)
   ...

XPACK and XUNPACK

The XPACK and XUNAPCK statements can operate on a STRUCT. STRUCT is treated as a list of variables. The XPACK statement packs each member variable in a buffer. The XUNPACK statement unpacks to a user defined type if it is passed as an argument to XUNPACK and the member variable matches the name in the buffer.

Error Messages

The following runtime errors are used with types:
ERRNDescription
12Attempt to re-declare a variable or label
13Array dimensions not specified or undefined type
900Undefined base type
901Nested types are not supported
902Statement not allowed in type definition
903Illegal or incomplete type definition

Example program

This section provides a more useful example. It demonstrates, how user defined types can be used to enhance or replace the current usage of the COMmon block.
! common block
TYPE Tglobal
  INTEGER Iv
  DIM Xv$[18]
  INTEGER A(1:2)
END TYPE
!
COM Global:Tglobal
READ STRUCT Global
DATA 123,"COMMON",1,2
!
PRINT "Global.Iv=";Global.Iv
PRINT "Global.Xv$=";Global.Xv$
PRINT "Global.A(*)=";Global.A(1);Global.A(2)
CALL Sub
STOP
!
SUB Sub
   COM Global:Tglobal
   PRINT "Global.Iv=";Global.Iv
   PRINT "Global.Xv$=";Global.Xv$
   PRINT "Global.A(*)=";Global.A(1);Global.A(2)
SUBEND


 
 
.
 
 
  Privacy | Webmaster | Terms of use | Impressum Revision:  2002-11-18  
  Copyright © 1995-2002 Marxmeier Software AG