Go to the previous, next section.
This note outlines a proposal for name mappings and restrictions; this proposal is not yet accepted. (Thanks to external standards such as CORBA, this proposal cannot be implemented for some languages, such as ANSI C.) The mappings outlined here are not necessarily the ones used in the current ILU release.
This proposal is about how to name things in the various programming languages, in a way that avoids name clashes. It imposes no restrictions on the ISL source. However, the mappings will be more straightforward if the ISL source avoids two things: (1) two or more concsecutive hyphens in a name, and (2) starting an interface or type name with "ilu-" (in any casing).
The first step in mapping an ISL to a programming language is to scan type and interface names for the substring "ilu-" (in any casing); wherever it occurs, we insert a trailing digit zero.
In a similar way, we next scan the name for sequences of hyphens. Wherever two or more hyphens appear consecutively, the digit zero (`0') is inserted after every other one, starting with inserting a zero after the second hyphen.
The following steps assume the first two steps have already been done.
Where tuples <N1, N2, ... Nk> of ISL names must be mapped into a flat programming namespace, we concatenate the ISL names, with a double hyphen ("--") inserted between each.
Where ISL names (or tuples thereof) must be mapped, together with ILU-chosen names derived from the ISL names, into a flat programming namespace, the derived names begin with fixed strings specific to the derivation, where the fixed strings begin with "ilu-" (with any case), and a double hyphen is inserted between the fixed string and the ISL name.
Where ISL names (or tuples thereof), and possibly ILU-chosen names derived from the ISL names, must be mapped, together with a fixed set of ILU-chosen names, into a flat programming namespace, the fixed ILU-chosen names begin with "ilu-" (with any case) and do not include a double hyphen.
The final step is to translate hyphens to underscores, for programming languages that accept underscores but not hyphens in names.
Following is a specification of how names are mapped in each language. The notation "[N]" is used to denote the application of the first two steps and the last step. Examples of "[..]" are:
[Foo] => Foo [foo-bar] => foo-bar [wait----for--it-] => wait--0--0for--0-it- [iluminate] => iluminate [ilu--uli] => ilu-0--0uliThe mappings also use the notation "[[..]]" to denote the mapping of a type-reference.
[ This mapping, while clean, will never be adopted because of the more problematic mapping specified by the OMG's CORBA document. ]
Item N
from interface I
is mapped to [I]__[N]
. [[I.N]] = [I]__[N]
; [[N]] = [I]__[N]
, where I
is the current interface.
An enumerated value named V
, of type T
in interface I
is mapped to [I]__[T]__[V]
.
A declaration of a record type T
in interface I
with fields F1:TR1
, ... Fn:TRn
is mapped to
typedef struct {[[TR1]] F1; ... [[TRn]] Fn} [I]__[T];
A declaration of a union type T
in interface I
of types TR1
, ... TRn
is mapped to
typedef enum {[[I.T]]__[[TR1]], ... [[I.T]]__[[TRn]]} ilu_tags__[[I.T]]; typedef struct {ilu_tags__[[I.T]] tag; union { [[TR1]] [[TR1]]; ... [[TRn]] [[TRn]]; } val; } [[I.T]];
For passing exceptions through the method calls in interface I
, the following auxiliary declaration is generated (supposing exceptions ER1:TR1
, ... ER2:TR2
are raised):
typedef struct { ilu_Exception returnCode; union { [[TR1]] [[ER1]]; ... [[TRn]] [[ERn]]; } val; } ilu_Status__[I];
An object type named T
in interface I
with methods M1
, ... Mn
maps to
typedef ilu_Ojbect [[I.T]]; [result-type-1] [I]__[T]__[M1]([[I.T]] ilu_self, [[arg-type-1-1]] [arg-name-1-1], ... [[arg-type-1-k]] [arg-name-1-k]); ...
Item N
from interface I
is mapped to [I]__[N]
. [[I.N]] = [I]__[N]
; [[N]] = [I]__[N]
, where I
is the current interface.
A declaration of an enumerated type named T
in interface I
containing values V1
, ... Vn
is mapped to typedef enum {[V1], ... [Vn]} [I]__[T]
.
Record and union declarations are mapped as for C. The exception status declaration is as for C.
Version 1 of ILU supported Modula-3, and this section describes the mapping we worked out for it.
An item named Bar
in ISL interface Foo
becomes an item named Bar
in the Modula-3 interface Foo
. A hyphen in an ISL name becomes an underscore in the corresponding Modula-3 name.
ISL types appear in Modula-3 as follows:
SHORT INTEGER
becomes [-32768 .. 32767]
.
INTEGER
becomes INTEGER
.
LONG INTEGER
becomes
TYPE LongInt = RECORD high: [-16_80000000 .. 2147483647]; low : Word.T (*[0 .. 4294967295]*) END;This represents the number
high*2^32 + low
. We always have the invariants -2^31 <= high < 2^31
and 0 <= low < 2^32
, even on systems whose natural word size is greater than 32 bits.
BYTE
becomes [0 .. 255]
.
SHORT CARDINAL
becomes [0 .. 65535]
.
CARDINAL
becomes Word.T
.
LONG CARDINAL
becomes RECORD high, low: Word.T END
. This representation works analogously to that for LONG CARDINAL
.
SHORT REAL
becomes REAL
.
REAL
becomes LONGREAL
.
LONG REAL
becomes an opaque type. Values of this type can only be handed around; no other operations are provided, not even equality testing. LONG REAL
is not really supported yet.
SHORT CHARACTER
becomes ['\000' .. '\377']
.
CHARACTER
becomes [0 .. 65535]
.
ARRAY
s of SHORT CHARACTER
become TEXT
.
REF ARRAY OF
.
SHORT CHARACTER
become arrays of BITS 8 FOR ['\000' .. '\377']
.
ARRAY
s of BYTE
become arrays of BITS 8 FOR [0 .. 255]
.
ARRAY OF L1, ... Ln
, becomes ARRAY [0 .. L1-1] OF ... ARRAY [0 .. Ln-1] OF
.
TYPE Foo = DiscT UNION case1: T1 = val1-1, ... val1-j END, ... casen: Tn = valn-1, ... valn-k END END OTHERS;maps to the Modula-3
TYPE Foo = BRANDED OBJECT d: DiscT END; TYPE Foo_case1 = Foo BRANDED OBJECT v: T1 END; CONST Foo_case1__Code : DiscT = val1-1; ... TYPE Foo_casen = Foo BRANDED OBJECT v: Tn END; CONST Foo_casen__Code : DiscT = valn-1; TYPE Foo_OTHERS = Foo BRANDED OBJECT END; (* Where every Foo is of one of the subtypes enumerated here, and the tag field (d) is consistent with the subtype. *)The
Foo_OTHERS
subtype appears only for union constructions including the OTHERS
keyword.
If the ISL union has a DEFAULT
arm
cased: Td = DEFAULTit maps to another subtype in Modula-3:
TYPE Foo_cased = Foo BRANDED OBJECT v: Td END;The
Foo_casen__Code
constants are conveniences for filling in and decoding the d
field.
Note that code that creates a Foo is responsible for filling in the d
field.
OPTIONAL Foo
becomes a REF Bar
, unless Bar is a subtype of REFANY
, in which case OPTIONAL Foo
becomes Bar; NIL
encodes the NULL
case.
SINGLETON
, DOCUMENTATION
, COLLECTIBLE
, OPTIONAL
, AUTHENTICATION
, and BRAND
have no effect on the mapping into the Modula-3 type system.
OUT
and INOUT
method parameters in ISL become VAR
parameters in Modula-3; IN
parameters become VALUE
(by default) parameters. The SIBLING
constraint in ISL has no manifestation in the Modula-3 type system.
The methods are declared to raise the exceptions IluBasics.Failed
and Thread.Alerted
in addition to the exceptions declared in the ISL. Exception IluBasics.Failed
is used to convey all the errors that can arise from the RPC mechanism, except Thread.Alerted
. Is the surrogate (and the other surrogates from the same server?) broken after either of these exceptions is raised?
Because ILU has multiple inheritance (i.e., an object type can have more than one direct supertype), the Modula-3 subtype relation is a sub-relation of the ILU subtype relation. In general, an ILU object type is mapped to a suite of Modula-3 object types, and a cohort of Modula-3 objects (one of each of the suite of Modula-3 types) correspond to one ILU object. There will be only one Modula-3 object (type) when only single-inheritance is used in constructing the ILU object type: when every ancestor type has at most one direct ancestor. Except where the programmer knows this is the case, and plans for it to remain so, she must abandon the native Modula-3 TYPECASE
/NARROW
/automatic-widen facilities for explicit calls that invoke the ILU subtype relation.
To generalize the Modula-3 TYPECASE
/NARROW
/automatic-widen facilities, the Modula-3 object type Ilu.Object
includes the following method:
PROCEDURE ILU_Qua_Type(ot: ObjectType): Object;If the object has, in ILU, the given object type, the Modula-3 object of the appropriate Modula-3 type is returned; otherwise, NIL is returned. As an added convenience, the Modula-3 mapping of interface Foo will contain, for each of its object types Bar:
PROCEDURE ILU_Qua_Bar(x: Ilu.Object): Bar;This procedure takes a non-
NIL
argument. If the argument is, in ILU, an instance of Bar or one of its subtypes, the corresponding language-specific object is returned; otherwise, NIL
is returned.
ISL exceptions are exactly like Modula-3 exceptions, and are mapped directly.
Here's a sample ISL spec, and the resulting Modula-3 mappings:
INTERFACE Foo; TYPE String = ilu.CString; TYPE UInt = CARDINAL; TYPE E1 = ENUMERATION val1, val2, val3 = 40 END; TYPE R1 = RECORD field1 : CARDINAL, field2 : E1 END; TYPE FAB = ARRAY OF 200 BYTE; TYPE VAB = SEQUENCE OF BYTE; TYPE FASC = ARRAY OF 10 SHORT CHARACTER; TYPE VASC = SEQUENCE OF SHORT CHARACTER; TYPE FAC = ARRAY OF 5 CHARACTER; TYPE VAC = SEQUENCE OF CHARACTER; TYPE A2 = ARRAY OF 41, 3 R1; TYPE S1 = SEQUENCE OF E1; TYPE U1 = UNION R1, A2 END; EXCEPTION Except1 : String; CONSTANT Zero : CARDINAL = 0; TYPE O1 = OBJECT METHODS M1(r1: R1, INOUT v: VASC, OUT s1: S1): UInt RAISES Except1 END, FUNCTIONAL Hash(v: VASC): FASC, ASYNCHRONOUS Note(x: LONG REAL) END;
The Modula-3 mapping:
INTERFACE Foo; IMPORT Ilu, IluBasics, Thread; IMPORT ilu; <*NOWARN*> TYPE UInt = CARDINAL; TYPE E1 = { val1, val2, val3}; TYPE R1 = RECORD field1 : CARDINAL; field2 : E1; END; TYPE VASC = TEXT; (* NIL not allowed *) TYPE S1 = REF ARRAY OF E1; (* NIL not allowed *) TYPE FASC = ARRAY [0..9] OF Ilu.PackedShortChar; (* declaration of M3 type "Foo.O1" from ILU class "Foo:O1" *) TYPE O1 = Ilu.Object OBJECT METHODS M1 (r1: R1; VAR v: VASC; VAR s1: S1): UInt RAISES {IluBasics.Failed, Thread.Alerted, Except1}; Hash (v: VASC): FASC RAISES {IluBasics.Failed, Thread.Alerted}; Note (x: Ilu.LongReal) RAISES {IluBasics.Failed, Thread.Alerted}; OVERRIDES ILU_Get_Type := ILU_Get_Type_O1 END; PROCEDURE ILU_SBH_To_O1 (sbh: TEXT; mostSpecificTypeID: TEXT := NIL): O1 RAISES {IluBasics.Failed, Thread.Alerted}; PROCEDURE ILU_Get_Type_O1 (self : Ilu.Object): Ilu.ObjectType; PROCEDURE ILU_Qua_O1 (x: Ilu.Object): O1; TYPE A2 = ARRAY [0..40] OF ARRAY [0..2] OF R1; TYPE U1 = BRANDED OBJECT d: Ilu.ShortInt END; (* NIL not allowed *) TYPE U1_R1 = U1 BRANDED OBJECT v: R1 END; CONST U1_R1__Code : [-32768..32767] = 0; TYPE U1_A2 = U1 BRANDED OBJECT v: A2 END; CONST U1_A2__Code : [-32768..32767] = 1; TYPE VAC = REF ARRAY OF Ilu.Character; (* NIL not allowed *) TYPE FAC = ARRAY [0..4] OF Ilu.Character; TYPE VAB = REF ARRAY OF BITS 8 FOR Ilu.Byte; (* NIL not allowed *) TYPE FAB = ARRAY [0..199] OF Ilu.PackedByte; TYPE String = TEXT; (* NIL not allowed *) CONST Zero : CARDINAL = 0; (* Exceptions *) EXCEPTION Except1 (String); END Foo.
Go to the previous, next section.