SmallEiffel & Compiled Libraries 
Author Message
 SmallEiffel & Compiled Libraries

    According to the SmallEiffel website, the developers have no intention
of adding the ability to precompile libraries.  This means that you cannot
"hide" your source code (yes, you can print short forms for developers, but
they can still see the full implementation).  It also means that there is a
memory penalty, since shared libraries are not supported.  Two programs
running at the same time cannot share libraries, and presumably this will
lead to tremendous memory bloat.

    I see these as important problems with respect to attracting developers
to SmallEiffel.  Have people given this much thought?  If I had a clue about
compilers and was competent enough, I would attempt to add this capability
myself, but there seems to be a lot of hurdles to jump in trying to
implement such a thing with an Eiffel compiler.  At best I might be capable
of tackling this in a couple of years, which takes me out of the picture as
far as a realistic and timely solution goes.

    Shouldn't the developers see this as a much higher priority, or am I
overlooking something that makes such a capability irrelevent?!?!

MPC



Thu, 08 Apr 2004 11:48:45 GMT  
 SmallEiffel & Compiled Libraries

Quote:

>    According to the SmallEiffel website, the developers have no intention
>of adding the ability to precompile libraries.  This means that you cannot
>"hide" your source code (yes, you can print short forms for developers, but
>they can still see the full implementation).  It also means that there is a
>memory penalty, since shared libraries are not supported.  Two programs
>running at the same time cannot share libraries, and presumably this will
>lead to tremendous memory bloat.

>    I see these as important problems with respect to attracting developers
>to SmallEiffel.  Have people given this much thought?

I gave dynamic linking some thought a few years ago, and that's relevant
to shared libraries.  My code is here:

  http://www.eiffel-forum.org/archive/doyle/sedl.htm

--
--
Patrick Doyle



Thu, 08 Apr 2004 13:11:50 GMT  
 SmallEiffel & Compiled Libraries

Quote:
> This means that you cannot "hide" your source code (yes, you can
> print short forms for developers, but they can still see the full
> implementation).

That's not a problem. Other compilers had/have this facility and I
don't think it has ever been of any use to anybody. For a compiler
which is open source, promoting close source does not seem
appropriate.

Quote:
> It also means that there is a memory penalty, since shared libraries
> are not supported.

Not necessarily, as SE compiles in only code which is actually used.
So you may have 3 times 10% of a library duplicated, which is smaller
than 1 time 100% of a monolithic shared library.

Of course, in some circumstances you can have a penalty. SE can be
used to produce shared libraries with flat procedural interfaces I
think (or could relatively easily be made to). In any case, the
Eiffel class makes a very bad library boundary, so any effort
towards shared library should use another module mechanism
(flat procedural API, CORBA, whatever) with a coarser granularity
-- and free interoperability if widespread.

Quote:
> Two programs running at the same time cannot share libraries, and
> presumably this will lead to tremendous memory bloat.

People are used to that. After all, Java is still used even if in
practice sharing is limited: each Java program usually comes with
its own copy of the JVM.


Fri, 09 Apr 2004 23:32:07 GMT  
 SmallEiffel & Compiled Libraries

Quote:

>In any case, the
>Eiffel class makes a very bad library boundary, so any effort
>towards shared library should use another module mechanism
>(flat procedural API, CORBA, whatever) with a coarser granularity
>-- and free interoperability if widespread.

Granted, a single class is too small, but collections of Eiffel classes
seem like a great library boundary to me because they support contracts.

--
--
Patrick Doyle



Sat, 10 Apr 2004 01:45:53 GMT  
 SmallEiffel & Compiled Libraries
Patrick Doyle:

Quote:
> Granted, a single class is too small, but collections of Eiffel classes

A collection of Eiffel class implies a single class as an unit of the
interface. This is too fine grained in my opinion, and (likely) includes
polymorphism and inheritance and creating objects accross the boundary,
which is asking for trouble and is likely to conflict or defeat
global system analysis, a nice feature of Eiffel compilers.

Quote:
> seem like a great library boundary to me because they support contracts.

What do you do with contracts? I don't think you can trust a dynamic
client to fulfill them, so you have to check them always. If you export
classes, how do you choose which contracts are at the boundary and which
are not? Seems very tricky to me. Routines may need different contracts
depending on the level of trust and checkability (distinguishing calls
from inside the module to those, untrusted, through a dynamic linking
boundary).

If you have a fully distinct interface, you could have distinct contracts, or
defensive programming, which may be more appropriate for things in a run-time
interface that cannot be checked at least somewhat statically (at library
load time say).



Sat, 10 Apr 2004 18:43:18 GMT  
 SmallEiffel & Compiled Libraries

Quote:

>Patrick Doyle:

>> Granted, a single class is too small, but collections of Eiffel classes

>A collection of Eiffel class implies a single class as an unit of the
>interface. This is too fine grained in my opinion, and (likely) includes
>polymorphism and inheritance and creating objects accross the boundary,
>which is asking for trouble and is likely to conflict or defeat
>global system analysis, a nice feature of Eiffel compilers.

The SEDL project demonstrated how dynamic linking can be achieved without
losing SmallEiffel's global analysis:

  http://www.eiffel-forum.org/archive/doyle/sedl.htm

In short, a single proxy class is added which is capable of calling
any dynamically-linked code through function pointers.  The static
analysis is satisfied because all the compiler sees is the proxy class.
And there's virtually no performance penalty.

Quote:
>> seem like a great library boundary to me because they support contracts.

>What do you do with contracts? I don't think you can trust a dynamic
>client to fulfill them, so you have to check them always.

That doesn't make sense to me.  If you don't trust the dynamically
linked code to do anything, why call it?

The level of trust depends on the situation, and I think contracts
can capture that nicely.  If you really want to model a situation
where you don't trust the dynamically linked code, you can make
all the assertions "True".

Or, you can use a policy where you turn on contract checking at the
dynamic boundary and raise exceptions in the usual Eiffel way.  Checking
for the Precondition exception, for instance, has always been something
that is only done when you don't trust a program's own code to be
bug-free, and this is exactly the situation here.

Quote:
>If you export classes, how do you choose which contracts are at the
>boundary and which are not? Seems very tricky to me.

The authors of Java code seem to have no trouble deciding which classes
should be public and which should be private.  Why is this decision any
harder than deciding which features should be public and private?

Quote:
>Routines may need different contracts
>depending on the level of trust and checkability (distinguishing calls
>from inside the module to those, untrusted, through a dynamic linking
>boundary).

Seems to me the compiler would have no trouble inserting checks at the
dynamic boundary.

Quote:
>If you have a fully distinct interface, you could have distinct contracts, or
>defensive programming, which may be more appropriate for things in a run-time
>interface that cannot be checked at least somewhat statically (at library
>load time say).

Agreed.  None of this seems to preclude using classes as the library
boundary.

I think we're arguing the appropriateness of two different things:
classes, and contracts.  I think it's clear that contracts are
appropriate, because you can simply make them "True" if you really
don't trust the dynamically-loaded code.  That leaves us with the
question of whether classes are appropriate.

The key question I have is, what is the problem posed by having an object-
oriented interface which would be solved by reverting to procedural
programming?

--
--
Patrick Doyle



Sat, 10 Apr 2004 22:47:42 GMT  
 SmallEiffel & Compiled Libraries
SEDL sounds like a hack, but an elegant hack compared to the alternative of
dealing with all the {*filter*}you guys are arguing over.  The SEDL concept seems
like the way to go if shared libraries are needed.  A few questions then:

1.  Why did you stop working on SEDL?  Was it lack of time, loss of
interest, or are there other technical considerations that stopped the
project cold in its tracks?

2.  I think (perhaps incorrectly) that ISE Eiffel can do shared libraries.
Does anyone know how it does this without suffering severe technical
problems?

MPC


Quote:


> >Patrick Doyle:

> >> Granted, a single class is too small, but collections of Eiffel classes

> >A collection of Eiffel class implies a single class as an unit of the
> >interface. This is too fine grained in my opinion, and (likely) includes
> >polymorphism and inheritance and creating objects accross the boundary,
> >which is asking for trouble and is likely to conflict or defeat
> >global system analysis, a nice feature of Eiffel compilers.

> The SEDL project demonstrated how dynamic linking can be achieved without
> losing SmallEiffel's global analysis:

>   http://www.*-*-*.com/

> In short, a single proxy class is added which is capable of calling
> any dynamically-linked code through function pointers.  The static
> analysis is satisfied because all the compiler sees is the proxy class.
> And there's virtually no performance penalty.

> >> seem like a great library boundary to me because they support
contracts.

> >What do you do with contracts? I don't think you can trust a dynamic
> >client to fulfill them, so you have to check them always.

> That doesn't make sense to me.  If you don't trust the dynamically
> linked code to do anything, why call it?

> The level of trust depends on the situation, and I think contracts
> can capture that nicely.  If you really want to model a situation
> where you don't trust the dynamically linked code, you can make
> all the assertions "True".

> Or, you can use a policy where you turn on contract checking at the
> dynamic boundary and raise exceptions in the usual Eiffel way.  Checking
> for the Precondition exception, for instance, has always been something
> that is only done when you don't trust a program's own code to be
> bug-free, and this is exactly the situation here.

> >If you export classes, how do you choose which contracts are at the
> >boundary and which are not? Seems very tricky to me.

> The authors of Java code seem to have no trouble deciding which classes
> should be public and which should be private.  Why is this decision any
> harder than deciding which features should be public and private?

> >Routines may need different contracts
> >depending on the level of trust and checkability (distinguishing calls
> >from inside the module to those, untrusted, through a dynamic linking
> >boundary).

> Seems to me the compiler would have no trouble inserting checks at the
> dynamic boundary.

> >If you have a fully distinct interface, you could have distinct
contracts, or
> >defensive programming, which may be more appropriate for things in a
run-time
> >interface that cannot be checked at least somewhat statically (at library
> >load time say).

> Agreed.  None of this seems to preclude using classes as the library
> boundary.

> I think we're arguing the appropriateness of two different things:
> classes, and contracts.  I think it's clear that contracts are
> appropriate, because you can simply make them "True" if you really
> don't trust the dynamically-loaded code.  That leaves us with the
> question of whether classes are appropriate.

> The key question I have is, what is the problem posed by having an object-
> oriented interface which would be solved by reverting to procedural
> programming?

> --
> --
> Patrick Doyle




Mon, 12 Apr 2004 11:19:42 GMT  
 SmallEiffel & Compiled Libraries
Patrick Doyle:

Quote:
> In short, a single proxy class is added which is capable of calling
> any dynamically-linked code through function pointers.  The static
> analysis is satisfied because all the compiler sees is the proxy class.

I was wondering how you would deal with:

-- client
   --s: STRING
   !CLIENT_STRING! s.make_empty
   object_from_library.play_with_string (s)

-- library (does not know MY_STRING)
   play_with_string (s: STRING) is
       do s.feature_redefined_in_client

Hm. Maybe you can indeed proxy every class reachable from
the boundary, in both directions. Seems a major hassle
though to do in a realistic way (that is, not worth it?)

I then have to agree that "not worth it" is not the same
argument as "not possible".

Quote:
> That doesn't make sense to me.  If you don't trust the dynamically
> linked code to do anything, why call it?

Interestingly I was thinking about the library trusting the caller
rather
than the other way round. I'm not sure why. Maybe I got confused with
an idea of client/server processes. The issue I'm concerned with may
be more like:

To me Design by Contract is a way to ensure a property of a body of
code: code is correct if, under all paths the code can take, all
assertions are true. In my view, we practically have two classes of
assertions/contracts: statically checkable ones (the type system only
in Eiffel) and run-time ones. Ideally, testing goes through all
possible code paths so that you can disable run-time assertion
checking in finished programs.

In a dynamically linked system, static contracts can be checked at
load time. The problem is with run-time contracts: failing formal
checkability, they become somewhat meaningless because you cannot
ensure consistency, eg:

Say that for a routine f you have:
   require pre_1 ensure post_1

Client code is written against that contract:
   if f.pre_1 then f -- and do_something assuming post_1 is true

Then you replace the contract of f with another which has no relation
with the initial contract:
   require pre_2 ensure post_2

Then you link dynamically the pre_2/post_2 version of f with a client
of the pre_1/post_1 version. At best, you have a runtime error, but
for a new type of error: contract changed between compilation and
linking. The value of contracts on the library boundary is diminished
by this new class of errors created by mixing run-time contracts with
dynamic libraries.

Maybe the value is not diminished enough to make it worthless, I don't
know.

Quote:
> where you don't trust the dynamically linked code, you can make
> all the assertions "True".

That is, have no (run-time) contracts. Agreed.

Quote:
>>If you export classes, how do you choose which contracts are at the
>>boundary and which are not? Seems very tricky to me.
> The authors of Java code seem to have no trouble deciding which classes
> should be public and which should be private.  Why is this decision any
> harder than deciding which features should be public and private?

What I was thinking about is indirect calls, and I think I was
mistaken:
  f(x) is do inside.g(x) end
What if f is at the boundary but a call has an x that fails g
contract? I've now realised it's f's business to ensure g's contract,
so f's contract should include whatever is needed to satisfy g.

Quote:
> The key question I have is, what is the problem posed by having an object-
> oriented interface which would be solved by reverting to procedural
> programming?

Fragile base class, for instance. Well, one can argue that against
OO generally, but it (inheritance, really) seems more manageable in
a static system than in a DLL-hell context.


Mon, 12 Apr 2004 20:19:17 GMT  
 SmallEiffel & Compiled Libraries

Quote:

>1.  Why did you stop working on SEDL?  Was it lack of time, loss of
>interest, or are there other technical considerations that stopped the
>project cold in its tracks?

There are no technical reasons I know of.  There was a group of us
working on it.  I had imagined that I would make this prototype as
a proof of concept, and then others would debate the ideas, and
eventually incorporate them into the SE compiler.  I didn't have
the knowledge or inclination to do that myself, and apparently
neither did the others.  :-)

--
--
Patrick Doyle



Mon, 12 Apr 2004 20:18:14 GMT  
 SmallEiffel & Compiled Libraries

Quote:

>Patrick Doyle:

>Hm. Maybe you can indeed proxy every class reachable from
>the boundary, in both directions. Seems a major hassle
>though to do in a realistic way (that is, not worth it?)

Yes, that's what I had in mind.  It's probably not worth doing
manually, but I thought the compiler could take care of it.

Quote:
>I then have to agree that "not worth it" is not the same
>argument as "not possible".

>> That doesn't make sense to me.  If you don't trust the dynamically
>> linked code to do anything, why call it?

>Interestingly I was thinking about the library trusting the caller
>rather
>than the other way round. I'm not sure why. Maybe I got confused with
>an idea of client/server processes.

Oh, ok.  That is interesting actually.  When you write a program,
it is logical to include all the libraries you use as being trusted
by the program.  After all, if you can't trust the library, why
use it?

However, when writing a library, you have no reason to trust programs
that might use it.

I guess a good policy when writing shared libraries is that you should
check for those things that could harm things that are the responsibility
of the library, but don't bother with things which will only harm the
calling program.

For instance, having a "reciprocal" function with a precondition that
the argument must be nonzero is sensible.  If the program breaks that
rule, it gets what it deserves, and no harm is done to the library.
However, if you are writing a file-handling library, you shouldn't
allow an erroneous program to damage the files.  Such things should
not be in preconditions, but should be checked by the library.

This seems to be an issue of robustness.  A library can use
preconditions (in place of checking) when the concequences of
an erroneous call are minor enough.

Quote:
>At best, you have a runtime error, but
>for a new type of error: contract changed between compilation and
>linking. The value of contracts on the library boundary is diminished
>by this new class of errors created by mixing run-time contracts with
>dynamic libraries.

That's very interesting.  So it's also a versioning issue, as well
as a robustness issue.

Quote:
>> The key question I have is, what is the problem posed by having an object-
>> oriented interface which would be solved by reverting to procedural
>> programming?

>Fragile base class, for instance. Well, one can argue that against
>OO generally, but it (inheritance, really) seems more manageable in
>a static system than in a DLL-hell context.

Yep, that's true.  I think this issue needs some more pondering... :-)
--
--
Patrick Doyle



Tue, 13 Apr 2004 03:59:45 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. SmallEiffel - can you compile a library?

2. Can't compile SmallEiffel

3. Problem compiling with SmallEiffel

4. Visual Libraries for SmallEiffel?

5. Win32 library for SmallEiffel?

6. Libraries && Dynamic Linking

7. compiling shared libraries

8. Problem compiling with multi-threading library

9. Compiled REXX Function libraries

10. Compiled Modelsim Libraries

11. Compiling libraries

12. compile process and various libraries

 

 
Powered by phpBB® Forum Software