[comp.lang.eiffel] Posting on behalf of B. Borghi

bertrand@eiffel.UUCP (Bertrand Meyer) (09/10/89)

This is posted on behalf of Bruno Borghi, who seems to have
trouble posting directly.

(I have had no other involvement with this message.)

-- Bertrand Meyer
bertrand@eiffel.com


Abstract

This (rather long) contribution proposes a new construct to facilitate the
declaration and the use of external routines and external variables.  Although
this article may seem theoretic, its motivations are purely practical.

I could have mailed it directly to Dr. Meyer, but I think that this subject is
of interest for every people who try to interface C packages with Eiffel.  It
would be useful if people having interfaced C packages with Eiffel were willing
to share their experience over the net.


I. External routine declaration
-------------------------------

An Eiffel routine that needs one ore more routines written in other languages
must list them in an external clause. This kind of declaration is *local* to
the routine and is similar to the local clause which declares local variables.

There is no way, as far as I know, to make a *global* declaration of an
external routine, i.e., available for every routine in a class. However, under
some circumstances, this may be useful.

(1) When the same external routine is used in more than one routine of a class,
in Eiffel 2.1, it must appear in an external clause for each routine where it
is used. The drawbacks are:
	- it defeats the "no code duplication" rule, which I regard as an
essential rule for software quality; it encourages the "cut and paste" style
rather than factorization.
	- it allows the declaration of the same external routine with different
identifiers in different routines of the class (it *is* local). This is
inconsistent with the fact that in a class an Eiffel feature has only one legal
identifier.

(2) When the same external routine is used in routines in more than one class,
in Eiffel 2.1, it must appear in an external clause for each routine where it
is used and for each class. This problem appears when interfacing large C
packages with Eiffel to encapsulate them. Examples are graphic packages,

In that case, I would like a mechanism similar to the C construct:
	#include "package.h" 

In Eiffel, the inherit clause gives us this mechanism, but one cannot easily
build a class declaring C bindings.


II. A new construct: Foreign routine
------------------------------------

To solve this problem, I propose an addition to Eiffel syntax for routine
declarations. I name it the "foreign routine" to distinguish from the "external
clause". The syntax could be a mixing between an external clause and a constant
declaration ("foreign" is a reserved word, "name" is optional, "language" is
mandatory, as in the external clause):

	c_sqrt(x:REAL):REAL is foreign name "c_sqrt" language "C";

An equivalent declaration is possible with the present Eiffel syntax, but is
rather clumsy:

	c_sqrt(x:REAL):REAL is
		external
			dummy(x:REAL):REAL name "c_sqrt" language "C";
		do
			Result := dummy(x)
		end; 

The "foreign routine" construct would suppress an useless indirection and would
be then more efficient, without the need of a sophisticated postprocessor for
optimization.


III. Generalization: foreign feature
------------------------------------

The "foreign routine" type of construct is not useful only for routines. This
mechanism may be a good one to handle external variables, for which there is no
provision in Eiffel 2.1.  (To keep an Eiffel flavour, I shall use the term of
"external attribute" in place of "external variable")

Suppose you interface a package where there are some global variables (global
variables are ugly, but they do exist in some commercially available C
packages). For each global variable, you must write a lot of code if you
read/write access to it.

As an example, let us consider a variable declared in C as
	int mode;

To access it, you have to write in Eiffel:
	get_mode: INTEGER is
		external
			c_get_mode: INTEGER language "C"
		do
			Result:=c_get_mode
		end;
	set_mode(m: INTEGER) is
		external
			c_set_mode(m: INTEGER) language "C"
		do
			c_set_mode(m)
		end;

You have to write some C as well:
	extern int mode;
	int c_get_mode()
	{
		return(mode);
	}
	void c_set_mode(m)
	int m;
	{
		mode = m;
	}

This is a lot of code. It is not very interesting to type in, and thus it is
error prone. Generalizing the "foreign routine" construct, one can imagine a
"foreign feature" construct which handles attributes. With this construct, you
just need a single line to declare a foreign attribute in a class; there is no
more need for additionnal C code. That gives:

	mode: INTEGER is foreign name "mode" language "C";

and that's all.

There is a problem: if we use the syntax of "foreign feature" for "foreign
features" as above, then there is an ambiguity between a foreign attribute and
a foreign function that takes no argument.

To remove this ambiguity, the construct has to be redesigned. We can add a
"type-of-feature" keyword to the construct:

	mode: INTEGER is foreign attribute name "mode" language "C";
	c_sqrt: INTEGER is foreign routine name "sqrt" language "C";

The construct is longer, but still simpler than what we have today. We can then
just drop the word "foreign"; as the word "language" remains mandatory, it is
still clear (but is it clear enough?) that the attribute or the routine is
external:

	mode: INTEGER is attribute name "mode" language "C";
	c_sqrt: INTEGER is routine name "sqrt" language "C";


IV. Conclusion
--------------

Some points may be discussed, especially for attributes. For instance, one can
imagine "readonly" foreign attributes (that are different from "constant"
attributes). In fact, this is rather related to the question of declaring
attributes of a class readonly for its clients. It is a more general
functionality which is not available in Eiffel. I am not sure it is necessary.

The syntax for "foreign features" that I propose is just an example to
illustrate what I mean. I do *not* mean that this is the syntax that should be
actually retained.


The "foreign feature" construct may lead to some holes in the typechecking
protection. In fact, this holes were already present in the former constructs,
because they are inherent to C: interfacing with C is always a risk. 

So, the "foreign feature"
	- is not more dangerous than an "external clause"
	- reduces dramatically the amount of code to type in, without loss of
clarity
	- extends to attributes
	- and so spares the programmer the bother of cumbersome C coding and of
switching from Eiffel world to C world
	- allows for the design of C-binding classes in similar way as constant
classes


V. About the author
-------------------

Bruno BORGHI	E-mail: bborghi@bebop.gipsi.fr
		Address: METASOFT, 13 rue Duhamel,35000 Rennes,FRANCE
		Phone: +33 - 99 31 25 88