An IDL Binding for Dylan#
Introduction#
This chapter proposes an IDL binding for Dylan. It is based on the draft OMG Request For Comment submission.
Document conventions#
The requirements of this specification are indicated by the verb “shall”. All other statements are either explanatory, amplifying, or relaxing. All implementation notes are so labeled.
Dylan names within the text and all example Dylan code appears in
fixed-point font, like this
.
Bibliography#
This specification mentions the following documents.
- [DP 97]
Neal Feinberg, S. E. Keene, R.O. Mathews, P. T. Withington, Dylan Programming, Addison Wesley, 1997.
- [DRM 96]
L. M. Shalit, The Dylan Reference Manual, Addison Wesley, 1996.
- [OMG 94.3.11]
T. J. Mowbray, and K. L. White, OMG IDL Mapping for Common Lisp, OMG 94.3.11, 1994.
- [OMG 98.07.01]
The Common Object Request Broker: Architecture and Specification, Revision 2.2, formal/98-07-01, <https://www.omg.org/spec/CORBA/2.2>, July 1998.
Design rationale#
Glossary of terms#
This document uses terms from both the CORBA 2.2 specification [OMG 98.7.1] and the Dylan Reference Manual [DRM 96]. Any additional terminology is described below.
Design philosophy#
Linguistic requirements#
The design should be:
- Conformant
Provide a mapping that conforms to the CORBA 2.0 specification.
- Complete
Provide a complete language mapping between IDL and Dylan.
- Correct
Provide a mapping that correctly maps legal IDL definitions to equivalent Dylan definitions.
- Consistent
Provide a mapping that is consistent in its translation of IDL constructs to Dylan constructs.
- Natural
Provide a mapping that produces Dylan definitions that would be judged to be expressed in “natural Dylan”.
- Stable
Small changes in an IDL description should not lead to disproportionately large changes in the mapping to Dylan.
- Concise
Common constructs should be mapped in as simple and direct a manner as possible. If necessary to achieve this goal, rare pieces of syntax can be traded off and absorb the linguistic fallout.
Engineering requirements#
The design should be:
- Extension-free
Do not require extensions to CORBA.
- Implementation-Free
Do not provide implementation descriptions, except as explanatory notes.
- Reliable
The mapping should not adversely impact the reliability of clients or implementations of services built on an ORB.
- Efficient
The mapping should allow for as efficient an implementation as is provided by other language bindings.
- Portable
The mapping should use standard Dylan constructs.
- Encapsulated
The mapping should hide and not constrain the implementation details.
Miscellaneous requirements#
The design should also be:
- Rationalized
Provide a rationale for key design decisions.
Mapping summary#
The following table summarizes the mapping of IDL constructs to Dylan constructs.
IDL constructs mapped to Dylan constructs.
This IDL construct … |
… Maps to this Dylan construct |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Lexical mapping#
This section specifies the mapping of IDL identifiers, literals, and constant expressions.
Identifiers#
Background#
IDL identifiers are defined as follows [OMG 98.7.1]:
An identifier is an arbitrarily long sequence of alphabetic, digit, and underscore (
_
) characters. The first character must be an alphabetic character. All characters are significant.Identifiers that differ only in case collide and yield a compilation error. An identifier for a definition must be spelled consistently (with respect to case) throughout a specification.
…
There is only one namespace for OMG IDL identifiers. Using the same identifier for a constant and an interface, for example, produces a compilation error.
Dylan identifiers defined are as follows [DRM 96]:
A name is one of the following four possibilities:
An alphabetic character followed by zero or more name characters.
A numeric character followed by two or more name characters including at least two alphabetic characters in a row.
A graphic character followed by one or more name characters including at least one alphabetic character.
A
\
(backslash) followed by a function operator.where:
Alphabetic case is not significant except within character and string literals. …
An alphabetic character is any of the 26 letters of the Roman alphabet in upper and lower case.
A numeric character is any of the 10 digits.
A graphic character is one of the following: ! & * < = > | ^ $ % @ _
A name character is an alphabetic character, a numeric character, a graphic character, or one of the following: - + ~ ? /
Specification#
From Section A.3.1.1 it can be seen that Dylan identifiers are a superset of IDL identifiers, and therefore they shall be left unmodified in the mapping except as follows.
IDL provides only underscores to separate individual words, while Dylan identifiers conventionally use hyphens to separate individual words. A mapping shall therefore translate underscores to hyphens.
There are some reserved words in Dylan:
A reserved word is a syntactic token that has the form of a name but
is reserved by the Dylan language and so cannot be given a binding and
cannot be used as a named value reference. There are seven reserved
words in Dylan: define
, end
, handler
, let
, local
,
macro
, and otherwise
.
When an IDL identifier collides with a reserved Dylan word, the string
“-%
” shall be appended to the end of the identifier. The “%
”
character is used instead of, say, the string “idl
”, because it
cannot occur in an IDL identifier, and so we avoid having to deal with
cases where the Dylan identifier together with an existing “-idl
”
suffix also appears in the IDL description.
This “-%
” suffix shall also be added to IDL identifiers ending in
“-setter
” in order to prevent potential collisions with setter
functions mapped from IDL attributes.
There are further grammar-driven modifications of identifiers due to scope and convention described The mapping of IDL to Dylan.
Examples#
Some example mappings of IDL identifiers to Dylan identifiers:
IDL identifiers mapped to Dylan identifiers.
This IDL identifier… |
… maps to this Dylan identifier |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Note
The case of all characters is not lowered in order to avoid
modifying acronyms like: do_TLA
→ do-tla
.
Note
Similarly hyphens are not inserted at lower-to-upper case
boundaries in order to avoid mistaken translations like
LaTex_Parser
→ la-te-x-parser
.
Literals#
IDL literals shall be mapped to lexically equivalent Dylan literals or semantically equivalent Dylan expressions. The following subsections describe the mapping for integers, floating-point numbers, and characters.
Integers#
Background#
Integer literals are defined as follows in IDL [OMG 98.7.1]:
An integer literal consisting of a sequence of digits is taken to be decimal (base ten) unless it begins with 0 (digit zero). A sequence of digits starting with 0 is taken to be an octal integer (base eight). The digits 8 and 9 are not octal digits. A sequence of digits preceded by
0x
or0X
is taken to be a hexadecimal integer (base sixteen). The hexadecimal digits includea
orA
throughf
orF
with decimal values ten through fifteen, respectively.
The corresponding integer literals are defined as follows in Dylan:
A sequence of decimal digits denote a decimal number.
The characters “
#o
” followed by a sequence of octal digits denote an octal number.The characters “
#x
” followed by a sequence of hexadecimal digits denote a hexadecimal number.
Specification#
A mapping shall therefore prepend the characters “#o
” to the
beginning of an octal literal. For a hexadecimal literal a mapping
shall therefore remove the characters “0x
” or “0X
” from the
beginning and prepend the characters “#x
” in their place.
Floating point numbers#
Background#
Floating point literals are defined as follows in IDL [OMG 98.7.1]:
A floating-point literal consists of an integer part, a decimal point, a fraction part, an
e
orE
, and an optionally signed integer exponent. The integer and fraction parts both consist of a sequence of decimal (base ten) digits. Either the integer part or the fraction part (but not both) may be missing; either the decimal point or the lettere
(orE
) and the exponent (but not both) may be missing.
The corresponding floating point literals are defined similarly in Dylan; see Numbers in the Dylan Reference Manual.
Specification#
No modification shall be made to floating point literals during translation.
Character literals#
Background#
IDL character literals are single printing characters, or escape sequences, enclosed by single quotes. The escape sequences are as follows:
IDL character literal escape sequences.
Description |
Escape Sequence |
---|---|
newline |
|
horizontal tab |
|
vertical tab |
|
backspace |
|
carriage return |
|
form feed |
|
alert |
|
backslash |
|
question mark |
|
single quote |
|
double quote |
|
octal |
|
hexadecimal |
|
Dylan character literals are defined in Character and String Literals in the Dylan Reference Manual.
Specification#
A mapping shall leave a single printing character unmodified during translation. A mapping shall leave escape sequences unmodified except as follows:
IDL character-literal escape sequences mapped to Dylan.
Description |
IDL Escape Sequence |
Dylan Translation |
---|---|---|
vertical tab |
|
|
question mark |
|
|
double quote |
|
|
octal |
|
|
hexadecimal |
|
|
String Literals#
Background#
IDL defines a string literal as follows:
A string literal is a sequence of characters (as defined in “Character Literals” …) surrounded by double quotes, as in
"
…"
. Adjacent string literals are concatenated. Characters in concatenated strings are kept distinct.
Dylan defines a string literal as follows:
Specification#
A mapping shall leave string literals unmodified during translation
except as follows. Escape sequences shall be modified in accordance
with the specification for character literals, with one exception:
\"
is left unmodified.
Fixed point decimals#
Background#
IDL defines a fixed point decimal literal as follows:
A fixed point decimal literal consists of an integer part, a decimal part, a fraction part, and a
d
or aD
. The integer and fraction parts both consist of a sequence of decimal (base 10) digits. Either the integer part of the fractional part (but not both) may be missing; the decimal point (but not the letterd
(orD
)) may be missing.
Dylan has no defined fixed point decimal literal format.
Specification#
A fixed point decimal literal shall be mapped to any available Dylan representation of the value.
Constant expressions#
A mapping shall either interpret the IDL constant expression yielding an equivalent Dylan literal or build a Dylan constant expression that will yield the same value.
Operators#
The IDL operators shall be interpreted as, or translated to, Dylan as defined by the following table. Note that the Dylan expressions will necessarily have whitespace around the operators even if the IDL expressions do not.
IDL operators mapped to Dylan.
Operation |
IDL |
Dylan |
---|---|---|
Bitwise Or |
|
|
Bitwise Xor |
|
|
Bitwise And |
|
|
Bitwise Not |
|
|
Shift Left |
|
|
Shift Right |
|
|
Add |
|
|
Subtract |
|
|
Multiply |
|
|
Divide (integer) |
|
|
Divide (float) |
|
|
Remainder |
|
|
Plus |
|
|
Minus |
|
|
The mapping of IDL to Dylan#
This section specifies the syntactic and semantic mapping of OMG IDL to Dylan. Unless otherwise noted, the mapping is applicable to both client-side and server-side interfaces. Issues specific to the server-side only are covered in clearly marked subsections.
Names#
Identifiers#
The lexical mapping of identifiers shall be as specified in Section A.3.1.2, “Specification”
Scoped names#
Specification#
Dylan has very different scoping rules from IDL. In particular, Dylan is not able to introduce new subordinate namespaces at all the linguistic points that IDL allows: files, modules, interfaces, structures, unions, operations, and exceptions. Except for files, the mapping shall handle this by appending together all the enclosing scope identifiers and the scoped identifier, separating them by forward slashes. See Section A.4.2, “IDL Files” for the mapping of IDL files to Dylan.
Rationale#
This is basically what several other languages have done [OMG 98.7.1]. Dylan has the concept of modules, but these are more linguistically heavyweight than the nested scopes they would be trying to model. Modules would also not allow out-of-scope references in the way that IDL does through its scope delimiter “::”.
The slash character is used instead of the hyphen character so in examples like the following the two IDL identifiers below do not clash after translation:
Moorcock::Michael
Moorcock_Michael
Examples#
// IDL
eco::umberto
SOCIETIES::Secret::knights_templar
// Dylan
eco/umberto
SOCIETIES/Secret/knights-templar
IDL Files#
Specification#
An IDL file shall be mapped to three Dylan libraries each exporting a single module with the same name as its respective library.
The three libraries shall be given the same name as the original IDL
file minus its .idl
extension, but adding the suffixes
-protocol
, -stubs
, and -skeletons
respectively.
The protocol library shall minimally use the Dylan library, or a library that uses it an re-exports its bindings. The stubs and skeletons libraries shall similarly minimally use the Dylan library, the Dylan-ORB library (see Section A.4.3), and the protocol library; and shall re-export the latter’s bindings.
Unless otherwise specified, Dylan constructs introduced as part of the IDL mapping shall be created in the protocol library.
Rationale#
The advantages of a mandatory mapping of a complete IDL description to a particular structure of Dylan libraries is:
Libraries are the natural large-scale unit of reuse in Dylan, and will match expectations.
Dylan programmers, applications, and tools will be able to rely on the Dylan “signature” of a service defined by an IDL description.
Enforcing the creation of a libraries allows any required runtime support to be naturally separated into and used from subordinate libraries.
If multiple IDL files are required to be combined into a single trio of libraries, then a single top level file can be used to include them together with any extra IDL module declarations required to prevent name clashes.
For example, an application library wishing to invoke the operations
described in the IDL file http.idl
should use the
http-stubs
library. Similarly, an application library wishing to
implement the operations described in the same IDL file should use the
http-skeletons
library.
The protocol library is available separately for applications wishing to make use of the Dylan framework generated from the IDL without necessarily using an ORB for communication. For example, an application team may wish to introduce the discipline of an IDL description early on in the project lifecycle so that development work on the clients and servers can proceed in parallel using dummy local implementations of the other components.
Implementation notes#
An implementation is free to map an IDL file to as many Dylan source files as is convenient.
An implementation is encouraged to transfer comments from IDL source files to the generated Dylan files.
The DYLAN-ORB library#
The Dylan mapping relies on some runtime support, for example the
built in types like corba/<short>
, and this shall be provided in a
Dylan library called Dylan-ORB that shall be used by a Dylan library
generated from an IDL file. Similarly, the Dylan-ORB library shall
define and export a Dylan module called Dylan-ORB that shall be used
by a Dylan module generated from an IDL file.
The Dylan-ORB library can be used independently of libraries generated from IDL files to build generic applications without specific knowledge of particular services.
Mapping modules#
Background#
IDL modules define a name scope for other declarations including subordinate modules.
Specification#
An IDL module shall be mapped to a Dylan identifier prefix for identifiers declared in the scope of the module declaration as defined by Section A.4.1.2, “Scoped names”.
Rationale#
Although mapping an IDL module to a Dylan module would seem to be more
natural, Dylan modules do not support out-of-scope references to
identifiers, for example, in IDL, foo::bar
.
Examples#
// IDL
module physics {
module quantum_mechanics {
interface schroedinger {};
};
};
// Dylan
define open class physics/quantum-mechanics/<schroedinger> (<object>)
end class;
Mapping for interfaces#
Background#
The CORBA standard [OMG 98.7.1] states:
An interface is a description of a set of possible operations that a client may request of an object. An object satisfies an interface if it can be specified as the target object in each potential request described by the interface.
In practice, an interface declaration introduces a name scope and defines a set of operations on, and attributes of, the interface.
Specification#
An IDL interface shall be mapped to an open, abstract, Dylan class
with no superclasses other than <object>
and classes generated
from inherited IDL interfaces.
The implementation dependent classes used to represent object references (see Section A.5.2.1, “Object references” and servants (see section Section A.5.5.1, “Servants”) shall be subclasses of the open abstract classes, and shall be defined in the stubs and skeletons libraries respectively.
An IDL interface shall also be mapped to a Dylan identifier prefix for identifiers declared in the scope of the class declaration as defined by Section A.4.1.2. Angle brackets shall be added to the start and end of the Dylan class name in accordance with Dylan programming conventions.
A forward declaration of an IDL interface shall not be mapped to anything.
Rationale#
Dylan classes are the natural focus of protocol definition and also allow IDL interface inheritance to be modeled by Dylan class inheritance (see below).
The class is abstract because it is an interface to an
implementation. On the client side the class is uninstantiable since
it is meaningless for Dylan client code to call the make
generic function on an arbitrary remote class. Instead the client must
acquire object references by invoking operations on factory objects as
defined in the IDL description of the particular service concerned.
The class is open to allow users of the server module to implement the interface by subclassing.
The class has no superclasses other than <object>
or those that
might be mapped from inherited IDL interfaces in order that the
protocol library, generated from the IDL interface, may be used
independently of any runtimes, stubs, or skeletons, as an abstract
Dylan protocol.
IDL allows name-only “forward declarations” of interfaces in order to allow interfaces to refer to one another. Two Dylan classes can refer to one another, but there is no special forward reference declaration form. Furthermore, the definition of the language only encourages implementations to support forward references, repeated definitions are not allowed, and bindings are not created in any prescribed order.
It therefore appears that there is nothing particular which the definition of the mapping can do concerning ordering or extra definitions, to ensure that mapped Dylan classes can be compiled by all Dylan implementations.
Examples#
// IDL
interface T34 {};
// Dylan
define open abstract class <T34> (<object>)
end class;
Mapping for interface inheritance#
Background#
The CORBA standard [OMG 98.7.1] states:
Interface inheritance provides the composition mechanism for permitting an object to support multiple interfaces. The principal interface is simply the most-specific interface that the object supports, and consists of all operations in the transitive closure of the interface inheritance graph.
CORBA interfaces can inherit from multiple other interfaces, and Dylan also supports multiple inheritance. However, Dylan’s multiple inheritance is more constrained. The class precedence order must be consistent. That is, any pair of classes must be in the same order with respect to each other wherever they occur together.
Specification#
Interface inheritance shall be mapped to class inheritance in Dylan. The superclass list for the resulting Dylan class shall be canonicalized using lexicographic order. That is, the order shall be alphabetic on the character set used for Dylan identifiers.
Rationale#
Class inheritance is the natural means of sharing protocols in Dylan.
The superclass list needs to be canonicalized to avoid legal IDL interface inheritance lists mapping to illegal Dylan class precedence lists. Reordering cannot affect method selection for IDL operations because IDL explicitly prohibits this kind of overloading. An alphabetic order is as good as any.
Examples#
// IDL
interface T34 : tank soviet_made {};
interface T48 : soviet_made tank {};
interface T1000 : T48 T34 {};
// Dylan
define open abstract class <T34> (<soviet-made>, <tank>)
end class;
define open abstract class <T48> (<soviet-made>, <tank>)
end class;
define open abstract class <T1000> (<T34>, <T48>)
end class;
Mapping for constants#
Specification#
IDL constant declarations shall be mapped to Dylan constant definitions. IDL constant expressions are mapped as defined in Section A.2.3, “Mapping summary”. In addition, a dollar character shall be added to front of the main identifier, but after the scope prefix, in accordance with Dylan programming conventions.
Examples#
// IDL
module time {
const unsigned long SECS_IN_100_YRS
= 100 * 365 * 24 * 60 * 60;
};
// Dylan
define constant time/$SECS-IN-100-YRS :: CORBA/<unsigned-long>
= 100 * 365 * 24 * 60 * 60;
// Or alternatively
define constant time/$SECS-IN-100-YRS :: CORBA/<unsigned-long>
= 3153600000;
Mapping for basic types#
Overall Background#
IDL and Dylan both provide a number of basic built in types and the means of constructing and naming new types.
Specification#
The mapping shall introduce new Dylan types for each CORBA type. The mapping of the new Dylan types to the built-in Dylan types shall be constrained as specified in the following sections, but within these constraints the mapping is implementation dependent.
A generic constraint shall be that legal Dylan literals within the ranges allowed by the type are allowed as values for these new Dylan types. That is, it shall not be necessary to call a constructor function on these values.
Rationale#
This allows implementations of the mapping some latitude, but also allows CORBA applications written in Dylan to succinctly and portably declare their data types and gain such efficiency as is provided by the combination of the mapping implementation and the Dylan compiler. The CORBA-specific types also protect application source code against underlying changes, and ensure that the code automatically benefits from any improvements.
The literals constraint means that programmers can expect to be able
to use, say, the literal “2” where a CORBA short
is expected.
Integers#
Background#
IDL defines six types of integer with the following ranges:
IDL integer type |
Range |
---|---|
|
-215 .. 215 - 1 |
|
-231 .. 231 - 1 |
|
-263 .. 263 - 1 |
|
0 .. 216 - 1 |
|
0 .. 232 - 1 |
|
0 .. 264 - 1 |
Dylan has the class <integer>
which is required to be at least
28 bits of precision. Overflow behavior is implementation defined.
Specification#
All IDL integer types shall be mapped to the following Dylan classes.
IDL and Dylan integer types.
IDL integer type |
Dylan CORBA integer type |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
These classes, in turn, shall be defined as aliases for, or subtypes of, some Dylan implementation’s integer classes, and shall be capable of representing the specified range of values.
Rationale#
The rationale is as given for the general case above. In this
particular instance, although an individual Dylan compiler could
convert a limited
expression to the best concrete class that the
runtime supports, this is not guaranteed. The runtime may have a good
class for implementing a CORBA class, but the compiler may not be
capable of translating a limited
expression into it.
Even if the translation of the limited
expression to the best
runtime class was guaranteed, the expressions are quite long an
cumbersome to use repeatedly in code, and an alias is convenient.
Examples#
// IDL
const long DIM_OF_UNIV = 11;
// Dylan
define constant $DIM_OF_UNIV :: CORBA/<long> = 11;
// Some alternative binding implementations
define constant CORBA/<long> = <integer>;
define constant CORBA/<long> = <machine-word>;
define constant CORBA/<long> =
limited(<integer>, min: -(2 ^ 31), max: (2 ^ 31) -1);
Floating-point numbers#
Background#
IDL defines three types of floating-point numbers:
IDL floating point number types.
IDL float type |
Range |
---|---|
|
ANSI/IEEE 754-1985 single precision |
|
ANSI/IEEE 754-1985 double precision |
|
ANSI/IEEE 754-1985 double-extended precision |
The Dylan types <single-float>
, <double-float>
, and
<extended-float>
are intended to correspond to the IEEE types
but may not.
Specification#
The IDL floating-point types shall be mapped to Dylan as follows:
IDL floating point types mapped to Dylan.
IDL float type |
Dylan float type |
---|---|
|
|
|
|
|
|
These classes, in turn, shall be aliases for or subclasses of the
Dylan <float>
class and shall be capable of representing the specified
range of values.
Rationale#
As above.
Examples#
// IDL
const double E = 2.71828182845904523536;
const float LYRS_TO_ALPHA_CENTAURI = 4.35;
// Dylan
define constant $E :: CORBA/<double> = 2.71828182845904523536;
define constant $LYRS-TO-ALPHA-CENTAURI :: CORBA/<float> = 4.35;
Fixed-point decimals#
Background#
IDL fixed-point decimals are defined as follows:
The
fixed
data type represents a fixed-point decimal number of up to 31 significant digits. The scale factor is normally a non-negative integer less than or equal to the total number of digits (note that constants with effectively negative scale, such as 10000, are always permitted.). However, some languages and environments may be able to accommodate types that have a negative scale or scale greater then than the number of digits.
Dylan has no defined fixed-point decimal type, but does have a rational type.
Specification#
The IDL fixed
type shall be mapped to the Dylan class
CORBA/<fixed>
, which shall be a subtype of the Dylan type
<rational>
.
Subtypes of the IDL fixed
type of the form fixed<d,s>
, where d
is the number of digits and s is the scale, shall be mapped to Dylan
types of the form
limited(CORBA/<fixed>, digits: d, scale: s)
The Dylan language operators and functions on rationals shall have
methods defined on instances of CORBA/<fixed>
.
In addition, instances of CORBA/<fixed>
shall support the
following functions:
CORBA/Fixed/digits(x :: CORBA/<Fixed>)
=> (digits :: CORBA/<unsigned-short>)
CORBA/Fixed/scale(x :: CORBA/<Fixed>)
=> (scale :: CORBA/<short>)
as(class == CORBA/<long-double>, x :: CORBA/<Fixed>)
=> (value :: CORBA/<long-double>)
as(class :: subclass(CORBA/<Fixed>), x :: CORBA/<Fixed>)
=> (fixed :: CORBA/<Fixed>)
as(class :: subclass(CORBA/<Fixed>), x :: CORBA/<long-double>)
=> (fixed :: CORBA/<Fixed>)
as(class :: subclass(CORBA/<Fixed>), x :: CORBA/<long>)
=> (fixed :: CORBA/<Fixed>)
Rationale#
This seems to be the natural mapping to Dylan and approximately mirrors the C++ mapping.
Examples#
// IDL
const fixed<6,2> salary_increment = 0100.50d;
// Dylan
define constant $foo
:: limited(CORBA/<Fixed>, digits: 6, scale: 2)
= make(limited(CORBA/<Fixed>, digits: 6, scale: 2),
digits: "100.5");
Characters#
Background#
IDL characters are elements of the 8 bit ISO Latin-1 (8859.1)
character set. Dylan’s characters are unspecified. Dylan has a
<character>
class and has three string classes:
<string>
, <byte-string>
, and
<unicode-string>
. Objects of these string types have elements
that are subtypes of <character>
.
Specification#
The IDL char
type shall be mapped to the Dylan class
CORBA/<char>
, which will be an alias for or a subclass of the
Dylan class <character>
.
Rationale#
As above.
Examples#
// IDL
const char ALEPH = 'a';
// Dylan
define constant $ALEPH :: CORBA/<char> = 'a';
Wide characters#
Background#
IDL wide characters are implementation defined.
Dylan defines a <unicode-string>
type.
Specification#
The IDL wchar
type shall be mapped to CORBA/<wchar>
, which
shall be a subclass of <character>
. Instances of CORBA/<wchar>
shall be allowed as elements of instances of <unicode-string>
.
Rationale#
The natural mapping to Dylan.
Examples#
// IDL
const wchar ALEPH = 'a';
// Dylan
define constant $ALEPH :: CORBA/<wchar> = 'a';
Boolean values#
Background#
IDL boolean
type can take the values TRUE
or FALSE
.
Dylan’s <boolean>
class similarly can take the values #t
,
and #f
.
Specification#
The IDL boolean
type shall be mapped onto the Dylan
CORBA/<boolean>
class which shall be an alias for the Dylan
<boolean>
class.
Rationale#
The extra CORBA prefix class is introduced for completeness and consistency, but there is no need to allow it to be a subclass of the built-in class.
Examples#
// IDL
const boolean CANTORS_HYPOTHESIS = TRUE;
// Dylan
define constant $CANTORS-HYPOTHESIS :: CORBA/<boolean> = #t;
Octets#
Background#
An IDL octet is an 8-bit quantity that undergoes no conversion of representation during transmission.
Specification#
The IDL octet
type shall be mapped to the Dylan class
CORBA/<octet>
which shall be an alias for or a subclass of some
Dylan implementation’s integer class allowing values in the range 0
to 255.
Rationale#
As above.
Examples#
// IDL
const octet BOND_ID = 007;
// Dylan
define constant $BOND-ID :: CORBA/<octet> = #o007;
The “any” type#
Background#
The IDL any
type permits the specification of values that can
express any OMG IDL type.
Dylan is a dynamic language with runtime type information.
Specification#
The IDL any
type shall be mapped to a sealed Dylan class
CORBA/<any>
with sealed getter and setter generic functions and
initialization keywords for the underlying value and the associated
typecode:
define generic CORBA/any/type
(any :: CORBA/<any>)
=> (typecode :: CORBA/<typecode>);
define generic CORBA/any/type-setter
(typecode :: CORBA/<typecode>, any :: CORBA/<any>)
=> (typecode :: CORBA/<typecode>);
define generic CORBA/any/value
(any :: CORBA/<any>)
=> (value :: <object>);
define generic CORBA/any/value-setter
(value :: <object>, any :: CORBA/<any>)
=> (value :: <object>);
In addition, anywhere that an object of type Any
is required the
Dylan programmer can supply objects that are instances of any mapped
IDL type.
At least one of the value:
initialization and typecode:
keywords shall be required. If the latter is not supplied then it is
coerced from the value in an implementation defined manner.
Explicit coercion to and from objects of type Any
shall be
provided by sealed methods on the Dylan generic function as
.
The function CORBA/any/value
shall signal an error if the value
cannot be coerced to a native Dylan type corresponding to a mapped IDL
type.
Rationale#
Although it is awkward for the Dylan programmer to have to deal with
an explicit Any
type, it allows the typecode to be preserved
across requests and replies in cases where it matters.
In some cases, for example where the Any
contains a structure
whose Dylan type is unknown (to the current program) it is not
possible for CORBA/any/value
to return a meaningful value. In
these cases the DynAny
interface should be used to navigate the
data inside the Any
.
Examples#
// IDL
long goedel_number(in any thing);
// Dylan
define open generic goedel-number (thing :: CORBA/<any>)
=> (result :: CORBA/<long>);
Note
The mapping of operations is described in more detail later.
Mapping for constructed types#
Mapping for typedefs#
Background#
An IDL typedef
declaration introduces aliases for a given type.
Dylan has a single namespace for identifiers and so no separate defining form is needed to introduce a new alias for a class.
Specification#
An IDL typedef
declaration shall be mapped to as many Dylan
define constant
definitions as there are declarators being
introduced by the IDL declaration.
Examples#
// IDL
typedef short mozart_symphony_no, layston_park_house_no;
// Dylan
define constant <mozart-symphony-no> = CORBA/<short>;
define constant <layston-park-house-no> = CORBA/<short>;
Mapping for enumeration types#
Background#
An IDL enumerated type consists of ordered lists of identifiers.
Specification#
An IDL enumerated type shall be mapped to a type union of singleton
symbol types. In addition, four sealed generic functions shall be
defined on the enumerated type (as if in its scope) for traversing and
comparing the enumerated values: successor
, predecessor
,
<
, and >
.
It shall be an error to call these functions on symbols outside the enumeration.
Rationale#
This is the straightforward implementation of enumerated types described in [DP 97]. We retain this basic format with a view to benefiting from the compiler optimizations encouraged in [DP 97]. However, we also specify successor, predecessor, and comparison functions for convenience.
Examples#
// IDL
enum planet {Mercury, Venus, Earth, Mars,
Jupiter, Saturn, Uranus, Neptune, Pluto};
// Dylan
define constant <planet>
= apply(type-union,
map(singleton, #(#"Mercury", #"Venus",
#"Earth", #"Mars", #"Jupiter", #"Saturn",
#"Uranus", #"Neptune", #"Pluto")));
define generic planet/successor
(value :: <planet>) => (succ :: <planet>);
define generic planet/predecessor (value :: <planet>)
=> (pred :: <planet>);
define generic planet/<(lesser :: <planet>, greater :: <planet>)
=> (lesser? :: <boolean>);
define generic planet/> (greater :: <planet>, lesser :: <planet>)
=> (greater? :: <boolean>);
Mapping for structure types#
Background#
IDL defines a structure
type that aggregates together multiple
pieces of data of potentially heterogeneous types.
Dylan programmers define new classes for this purpose.
Specification#
An IDL structure shall be mapped to a sealed, concrete, Dylan subclass
of CORBA/<struct>
together with pairs of sealed getter and setter
generic functions and a required initialization keyword for each
struct member. The initialization keywords shall be Dylan symbols
mapped using the normal identifier mapping rules, but without any
scope prefixes. It shall be an error to call the getter and setter
functions on instances of types other than those mapped from the IDL
structure. Furthermore the Dylan protocol functions make
and
initialize
shall be sealed over the domain of the mapped class.
Rationale#
The Dylan class, the getters, the setters, and initializers, are defined to be sealed in the anticipation that operations on structures are expected to be as efficient as possible without any need for extension.
There is no need to specify whether the getter and setter generic functions are defined as Dylan slots. The data may in fact be maintained in a foreign internal format convenient for network transmission.
The initialization keywords are required so as not to introduce complicated defaulting rules.
The superclass CORBA/<struct>
is made explicit to allow
instance?
tests.
Examples#
// IDL
struct meeting {
string topic, venue, convenor;
long date, duration;
sequence<string> attendees, agenda, hidden_agenda, minutes;
};
// Dylan (using slots)
define class <meeting> (CORBA/<struct>)
slot meeting/topic :: CORBA/<string>,
required-init-keyword: topic:;
slot meeting/venue :: CORBA/<string>,
required-init-keyword: venue:;
slot meeting/convenor :: CORBA/<string>,
required-init-keyword: convenor:;
slot meeting/date :: CORBA/<long>,
required-init-keyword: date:;
slot meeting/duration :: CORBA/<long>,
required-init-keyword: duration:;
slot meeting/attendees ::
limited(CORBA/<sequence>, of: CORBA/<string>)>,
required-init-keyword: attendees:;
slot meeting/agenda ::
limited(CORBA/<sequence>, of: CORBA/<string>)>,
required-init-keyword: agenda:;
slot meeting/hidden-agenda ::
limited(CORBA/<sequence>, of: CORBA/<string>)>,
required-init-keyword: hidden-agenda:;
slot meeting/minutes ::
limited(CORBA/<sequence>, of: CORBA/<string>),
required-init-keyword: minutes:;
end class;
define sealed domain make (singleton(<meeting>));
define sealed domain initialize (<meeting>);
Mapping for discriminated union type#
Background#
IDL defines a union
type that allows data of heterogeneous types
used interchangeably in places like parameters, results, arrays, and
sequences. An explicit tag called a discriminator is used to determine
the type of the data in a given object that is of the union type.
Dylan is a dynamic language with runtime type information and has no explicit tagging mechanism.
Specification#
An IDL union type shall be mapped to a sealed, concrete, Dylan
subclass of CORBA/<union>
with pairs of sealed getter and setter
functions and an initialization keyword for each union branch. Every
mapped union shall also have the following sealed getter and setter
functions:
corba/union/discriminator
corba/union/discriminator-setter
corba/union/value
corba/union/value-setter
and the following initialization keywords:
discriminator:
value:
It is an error to call these functions on instances of types other
than those mapped from the IDL union definition. Furthermore the Dylan
protocol functions:drm:make and initialize
shall be sealed
over the domain of the mapped class.
The initialization keywords shall be mapped as for structs. However,
they are not required in the same manner. Instead, either the caller
shall supply the discriminator:
and the value:
or an
initialization keyword mapped from one of the branches.
In addition, wherever a union is required (for example, in the parameter of an operation) the Dylan programmer shall be able to give any Dylan object that is an instance of one of the types of the branches of the union.
Explicit coercion to and from a union shall also be available as
sealed methods on the Dylan as
generic function. It is
undefined which discriminator is used in ambiguous cases.
Rationale#
Although it is unnatural for a Dylan programmer to have to manipulate explicit union discriminators, there are ambiguous cases that require this explicit treatment. By reifying the union the Dylan programmer is given as much direct control as a static language provides, and yet can also use the implicit coercion and value getter to ignore the details if so desired.
It is not necessary to state whether the getter and setter functions are implemented by slots.
The superclass CORBA/<union>
is made explicit to allow
instance?
tests.
Examples#
// IDL
union RLE_entity switch (short) {
case 1: long length;
case 2: char character;
};
// Dylan (sample)
define class <RLE-entity> (CORBA/<union>)
end class;
define sealed domain make (singleton(<RLE-entity>));
define sealed domain initialize (<RLE-entity>);
define sealed method as
(class == <RLE-entity>, length :: CORBA/<long>)
=> (object :: <RLE-entity>)
make(<RLE-entity>, length: length);
end method;
define sealed method as
(class == CORBA/<long>, object :: <RLE-entity>)
=> (length :: CORBA/<long>)
RLE-entity/length(object);
end method;
define method RLE-entity/length (union :: <RLE-entity>)
=> (length :: CORBA/<long>)
select (corba/union/discriminator(union))
1 => corba/union/value(union);
otherwise => error(...);
end select;
end method;
define method RLE-entity/length-setter
(length :: CORBA/<long>, union :: <RLE-entity>)
=> (length :: CORBA/<long>)
corba/union/value(union) := length;
corba/union/discriminator(union) := 1;
end method;
// ...
Mapping for sequence type#
Background#
IDL defines a sequence
type. A sequence is a one-dimensional array
with an element type, an optional maximum size (fixed at compile
time), and a current length (determined at run time).
Dylan defines several sequence-like classes including <sequence>
itself.
Specification#
The IDL sequence
type shall be mapped onto the a new Dylan
CORBA/<sequence>
class that shall be an alias for or a subclass of
the Dylan <stretchy-vector>
class. An element type shall be
mapped to a limited
type of CORBA/<sequence>
. The maximum
size is not modeled in Dylan and must be checked on marshalling.
Rationale#
Dylan’s <stretchy-vector>
class appears closest in intent to
IDL’s sequence
type.
Examples#
// IDL
typedef sequence<long, CHAIN-MAX> chromosomes;
// Dylan
define constant <chromosomes> =
limited(CORBA/<sequence>, of: CORBA/<long>);
Mapping for string type#
Background#
IDL defines a string
type. A string is a one-dimensional array of
all possible 8-bit quantities except NUL, with an optional maximum
size.
A string is similar to a sequence of char
.
Dylan defines <string>
, <byte-string>
, and
<unicode-string>
classes.
Specification#
The IDL string
type shall be mapped onto a Dylan
CORBA/<string>
class that shall be an alias for or a subclass of
the Dylan <string>
class.
Rationale#
The <byte-string>
class is not mandated in the mapping to
retain the flexibility and efficiency of the underlying Dylan
implementation. The effect of storing a NUL in a CORBA/<string>
that is passed as an argument to a request is undefined.
Examples#
// IDL
typedef string constellation;
// Dylan
define constant <constellation> = CORBA/<string>;
Mapping for wide string type#
Background#
The IDL wstring
data type represents a sequence of wchar
elements.
Dylan defines a <unicode-string>
type.
Specification#
The wstring
type shall be mapped to the Dylan type
CORBA/<wstring>
which shall be an alias for
<unicode-string>
.
Rationale#
The natural mapping to Dylan.
Examples#
// IDL
typedef wstring local_name;
// Dylan
define constant <local-name> = CORBA/<wstring>;
Mapping for array type#
Background#
IDL defines an array
type for multidimensional fixed-size arrays,
with explicit sizes for each dimension.
Dylan has a similar <array>
class.
Specification#
The IDL array type shall be mapped onto the Dylan CORBA/<array>
class. The new class shall be an alias for or a subclass of the Dylan
<array>
class. An element type shall be mapped to a limited
type of CORBA/<array>
.
Rationale#
This is the straightforward, natural mapping, albeit hidden behind a CORBA-specific class for portability across implementations and versions.
Examples#
// IDL
typedef long tensor[3][3][3];
// Dylan
define constant <tensor> =
limited(CORBA/<array>, of: CORBA/<long>,
dimensions: #(3,3,3));
Mapping for exceptions#
Background#
IDL defines exceptions as:
… struct-like data structures which may be returned to indicate that an exceptional situation has occurred during the performance of a request.
Dylan defines a rich, object-oriented, condition signalling and handling facility.
Specification#
IDL exceptions shall be mapped onto sealed Dylan conditions that are
subclasses of CORBA/<user-exception>
, which shall be a subtype of
CORBA/<exception>
, which itself shall be a subtype of the Dylan
<condition>
class. As with IDL structures, any members shall be
mapped to pairs of sealed setter and getter generic functions and
corresponding initialization keywords. It shall be an error to call
these functions on instances of types other than those mapped from the
IDL exception definition. Furthermore the Dylan protocol functions
make
and initialize
shall be sealed over the domain of
the mapped class.
Conditions shall be signalled in the standard Dylan manner by the CORBA runtime and not returned or passed as arguments.
Standard system exceptions shall be direct or indirect subclasses of
CORBA/<system-exception>
which shall be a subtype of
CORBA/<exception>
.
Rationale#
This is the natural mapping of IDL exceptions into the Dylan language.
Examples#
// IDL
exception melt_down {
short seconds_remaining;
};
// Dylan (using slots)
define class <melt-down> (CORBA/<user-exception>)
slot melt-down/seconds-remaining :: CORBA/<short>,
required-init-keyword: seconds-remaining:;
end class;
define sealed domain make (singleton(<melt-down>));
define sealed domain initialize (<melt-down>);
Mapping for operations#
Background#
IDL uses operations as the basic means by which CORBA-compliant programs communicate with each other. Operation declarations are akin to C function declarations, but they also have to deal with parameter directions, exceptions, and client contexts. All operations are defined within the scope of an interface.
Dylan programs call generic functions to communicate with other Dylan programs. The generic functions are implemented by methods.
Specification#
An IDL operation shall be mapped to an open Dylan generic function. The generic function name is subject to the usual identifier translation specified earlier. It shall be an error to call the function on instances of types not mapped from the IDL operation definition.
An IDL operation declared as oneway
shall be mapped on to a
generic function that returns zero results.
The IDL interface object shall become the first parameter to the Dylan
generic function. A IDL operation parameter declared as in
shall
become a parameter of the Dylan generic function. A parameter declared
as out
shall become a result of the Dylan generic function. A
parameter declared as inout
shall become both a parameter and a
result of the Dylan generic function. The Dylan parameters and results
shall maintain the order of the original parameters, with the
interface object and operation return value coming before any further
parameters and results defined by the IDL parameters.
An IDL raises
declaration describes the additional, non-standard,
exceptions that may be raised by invocation of the operation. This is
not mapped to any visible feature of the generic function that is
mapped from the operation declaration. If any exceptions are raised,
however, they shall be signalled and not returned from an operation
request.
An IDL context
declaration describes which additional pieces of
client state the service is passed. When a context
clause is
present this shall be mapped to a context:
keyword argument. When
invoking an operation, if a context is passed in then this shall be
used instead of the ORB’s default context for looking up the property
names listed in the operation’s context
clause. When being
invoked, an operation’s context keyword argument shall be filled by
applying the proper names to the given client context.
Rationale#
This is the natural mapping. The generic function is open to allow the server module to implement the function by adding methods.
Contexts are mapped are keyword arguments so that client code does not have to worry about them by default.
Examples#
In Parameters#
// IDL
interface stealth {
exception power_failure {};
void engage_cloak (in long power)
raises (power_failure);
};
// Dylan
define open abstract class <stealth> (<object>)
end class;
define open generic stealth/engage-cloak
(stealth :: <stealth>, power :: CORBA/<long>)
=> ();
define class stealth/<power-failure> (CORBA/<user-exception>)
end class;
define sealed domain make (singleton(stealth/<power-failure>));
define sealed domain initialize (stealth/<power-failure>);
Out Parameters#
// IDL
interface fuel_cell : power_source {
short burn_hydrogen
(in long burn_rate, out sequence<short,7> emissions);
};
// Dylan
define open abstract class <fuel-cell> (<power-source>)
end class;
define open generic fuel-cell/burn-hydrogen
(fuel-cell :: <fuel-cell>, burn-rate :: CORBA/<long>)
=> (result :: CORBA/<short>,
emissions ::limited(CORBA/<sequence>, of: CORBA/<short>));
InOut Parameters#
// IDL
interface frame {
void request-sizes (inout long width, inout long height);
};
// Dylan
define open abstract class <frame> (<object>)
end class;
define open generic frame/request-sizes
(frame :: <frame>,
width :: CORBA/<long>,
height :: CORBA/<height>)
=> (width :: CORBA/<long>,
height :: CORBA/<height>);
Mapping for attributes#
Background#
IDL attributes implicitly define a pair of accessor functions, one for
retrieving the value of the attribute, and another for setting its
value. The names of the accessor functions are language-mapping
specific, but must not collide with legal operation names specifiable
in IDL. Attributes may be defined as readonly
.
Dylan’s slots provide a similar mechanism, including constant
slots.
Specification#
IDL attributes shall be mapped to a pair of open generic functions,
one getter and one setter. The names of the functions shall be derived
by the usual identifier translation rules, with the addition that the
setter function has the suffix -setter
. Attributes declared as
readonly
will only have a getter function. It shall be an error to
call these functions on instances of types other than those mapped
from the IDL attribute definition.
If a mapped attribute name would clash with a mapped operation name
then the mapped attribute name shall have %
prepended.
Rationale#
It is not necessary to specify whether the generic functions are defined by virtual slots.
The identifier translation rules prevent potential name collisions
with the setter functions by appending -%
to the end of an
existing identifier that ends with -setter
.
In the main, attribute names are unlikely to clash with operation names so it seems harsh to punish the normal case with some additional name mangling. Instead, the penalty is put on defining a clashing operation name for an existing attribute. Existing source code would probably then have to be rewritten in order to continue to get at the old attribute.
Examples#
// IDL
interface prisoners_dilemma {
attribute short mutual_cooperation_reward;
attribute short mutual_defection_punishment;
attribute short defectors_temptation;
attribute short suckers_payoff;
};
// Dylan
define open abstract class <prisoners-dilemma> (<object>)
end class;
define open generic prisoners-dilemma/mutual-cooperation-reward
(object :: <prisoners-dilemma>) => (value :: CORBA/<short>);
define open generic
prisoners-dilemma/mutual-cooperation-reward-setter
(value :: CORBA/<short>, object :: <prisoners-dilemma>)
=> (value :: CORBA/<short>);
// ...
Memory management considerations#
Dylan is a garbage-collected language, however a Dylan program may be interacting, via an ORB, with remote data in another address space, and/or with local data not built using the same Dylan implementation or even the same language. In each case, explicit freeing of some data may be necessary.
By default, the ORB shall provide copying semantics for arguments and results and the Dylan garbage collector shall take care of reclaiming the storage occupied by provably unreferenced data. This includes data of basic types, constructed types, and object references.
However, a Dylan ORB may optionally provide non-copying semantics data. That is, Dylan programs may have to deal with pointers to shared data, because the ORB is acting as an efficient in-process interoperability layer. In this case, it is expected that the memory management protocol will be explicitly described in IDL as part of the contract between the interoperating programs.
Multi-threading considerations#
It should be assumed that invocation of a CORBA operation from Dylan is not thread-safe. That is, if two threads in a Dylan program invoke the same operation it is not guaranteed that they will be properly serialized.
An implementation of the IDL-to-Dylan mapping should document whether it is thread-safe, and if it is should document whether the whole program or just the thread is blocked.
The mapping of pseudo-objects to Dylan#
Introduction#
Background#
In addition to defining how application objects and data are accessed,
a language mapping must describe how to access some services
implemented directly by the ORB. These services are concerned with
operations like converting an object reference to a string, making a
request through the Dynamic Invocation Interface (DII), building a
Context
, and so on.
All that is required is that there be some defined mechanism for doing these things in each language-binding specification. However, most language-binding specifications take the pseudo-objects approach in which these ORB services are accessed by applying the binding’s normal mapping rules to OMG’s IDL descriptions of the interfaces to the services.
The advantage of this is that programmers can read the OMG’s descriptions of the interfaces and know how to access them from their preferred language without learning any additional language-specific access methods.
The disadvantage is that some of the interfaces turn out to be particularly clumsy for a given programming language.
Specification#
The IDL pseudo-object interfaces shall be mapped according to the Dylan language binding as specified in the earlier parts of this document, except where it explicitly deviates. In some cases, also where explicitly specified, there will be an additional access path that is more convenient for Dylan programmers. A conforming Dylan language mapping shall support both interfaces.
Rationale#
The pseudo object approach is taken so that experienced CORBA developers can leverage more of their knowledge and so that any new pseudo-object services defined by the OMG will automatically be covered.
However, some of the potential pseudo-object IDL descriptions lead to awkward interfaces from the Dylan programmer’s point of view and incompatible abstractions might arise on top of them; built by different binding. Therefore, in order to provide more natural Dylan abstractions, there are some additional Dylan-friendly interfaces in the following sections.
ORB Interface#
Object references#
Background#
All CORBA interfaces inherit from the CORBA::Object
interface.
Specification#
An IDL interface shall be mapped to a reference class that is a direct
or indirect subclass of both the interface class itself and
corba/<object>
.
Rationale#
This allows object references and servants to inherit from the same protocol class and yet retain their own separate behaviors.
Example#
// IDL
interface ion {};
// Dylan (protocol)
define open abstract class <ion> (<object>)
end class;
// Dylan (possible reference implementation)
define class <ion-reference> (<ion>, corba/<object>)
end class;
Object reference equality#
Background#
CORBA allows for (imprecise) equality testing via
corba::object::is_equivalent
.
Specification#
In addition to mapping the PIDL function above to
corba/object/is-equivalent
, a Dylan ORB shall provide a method on
=
that performs the same function.
Rationale#
It is natural for Dylan programmers to want to use =
on object
references.
Example#
// Dylan
// ...
if (corba/object/is-equivalent(grid1, grid2))
// ...
end if;
// versus
// ...
if (grid1 = grid2)
// ...
end if;
Nil object references#
Background#
CORBA allows for nil object references. These are returned from some operations to indicate situations where, for example, no real object reference could be found.
Dylan programmers normally indicate such a situation by returning the
rogue value #f
and by declaring the type of the return value to be
false-or(<some-type>)
.
Specification#
NIL object references shall be mapped to interface-specific values
that can be tested with CORBA::is_nil
. A nil object reference for
a particular interface shall be obtainable by calling the function
make-nil
on the associated protocol class.
Rationale#
Using #f
to represent nil object references would be natural and
convenient in some respects, notably during testing. However, all
object reference type declarations would have to be wrapped with
false-or
which would be very awkward. Even if we did this then we
would create ambiguous, unorderable methods which all accepted #f
for some generic functions. A less pervasive approach where
false-or
was only used for return values would be better, but then
it would be harder to glue operations together. The glue code would
have to check for #f
output from one operation before calling the
next. This seems an inappropriate place to check this, and should be
left to the receiving operation.
There are also advantages in terms of type safety. A spurious #f
is more easily passed to, or returned from, an operation than a more
explicit nil reference.
Example#
// Dylan
let philosopher = make-nil(<philosopher>);
corba/object/is-nil(philosopher); // returns #t
Dynamic Invocation Interface#
NVList#
Background#
CORBA NVLists are partially opaque in that they can normally only be
created by the ORB create_list
operation and added to by the
add_item
operation.
Specification#
NVLists shall be mapped to CORBA sequences of NamedValues.
Rationale#
Since CORBA sequences shall be mapped to a type that supports the
<stretchy-vector>
protocol, they can be created and added to using
the normal Dylan calls.
This is in addition to the pseudo IDL interfaces create_list
and
add_item
.
Example#
// Dylan
let args = make(corba/<nvlist>);
args := add!(args, make(corba/<namedvalue>,
name: "foo",
argument: as(corba/<any>, 0),
len: 0,
arg-modes: 0));
Dynamic Skeleton Interface#
Dynamic Implementation Routine#
Background#
The Dynamic Implementation Routine (DIR) is intended to support a variety of uses, including dynamic programming/scripting languages, bridge building, debugging, monitoring, and so on.
The idea is that a particular kind of registered servant is invoked via the DIR for all operations instead of invoking particular skeletons and thence particular implementation methods.
An auxiliary function is required for the application to inform the POA of the repository-ID of the most derived interface supported by the dynamic servant.
Specification#
There shall be a subclass of portableserver/<servant>
called
portableserver/<dynamic-servant>
. Instances of subclasses of this
class registered with the adapter as servants for objects shall have
operations invoked via the DIR function
corba/serverrequest/invoke
.
The shall be an open generic function
portableserver/servant/primary-interface
which shall be called by
the POA to determine the repository-ID of the most derived interface
supported by the dynamic servant.
The pseudo IDL of the above is:
// IDL
module CORBA {
interface PortableServer::Dynamic_Servant :
PortableServer::Servant {};
interface ServerRequest {
// ...
void invoke (in PortableServer::Dynamic_Servant servant);
};
};
module PortableServer {
interface Servant {
// ...
RepositoryID primary_interface
(in ObjectID id, in POA poa)
};
};
Rationale#
We just need to specify the function that is called on the registered servant for all operations, plus the auxiliary function for determining the repository-ID.
Example#
// Dylan
define class <buckstop> (portableserver/<dynamic-servant>)
end class;
define method corba/serverrequest/invoke
(request :: corba/<serverrequest>, servant :: <buckstop>)
=> ()
// ...
end method;
define method portableserver/servant/primary-interface
(servant :: <buckstop>,
id :: <string>,
poa :: portableserver/<poa>)
=> (repositoryid :: <string>)
"LOCAL:buckstop"
end method;
The Portable Object Adapter#
Servants#
Background#
The PortableServer
module for the Portable Object Adapter (POA)
defines the native Servant
type.
Specification#
The Dylan mapping for the Servant type shall be the open abstract
class portableserver/<servant>
.
An IDL interface shall be mapped to a skeleton class that is a direct
or indirect subclass of both the interface class itself and
portableserver/<servant>
.
The name of the skeleton class shall be formed by appending
-servant
to the interface name and applying the normal identifier
mapping rules.
The skeleton class shall be exported from the skeletons library generated from the IDL.
Rationale#
- Only instances of subclasses of
portableserver/<servant>
should be created.
Examples#
// Dylan Skeleton (generated from IDL)
define class <grid-servant>
(<grid>, portableserver/<servant>)
end class;
// Dylan Implementation
define class <grid-implementation> (<grid-servant>)
end class;