[m-dev.] abstract equivalence types & .NET / JVM

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Apr 18 19:11:06 AEST 2001


Mercury allows modules to define abstract types which are implemented
as type synonyms.

Unfortunately there is no directly support for this in .NET or JVM.
So we need some way of handling abstract equivalence types
for the .NET and JVM back-ends.

Tyson and I have discussed several possible approaches.
All of the different approaches suck in one way or another,
so it's just a question of finding the one that sucks the least.

1.  Our current approach for the high-level C and .NET back-ends is to use
    `--no-high-level-data';
    i.e. map everything except the basic types to `Object'.

    This is very bad for interoperability (which is the whole point of
    these back-ends), and probably very bad for performance too).
    It also has problems with abstract equivalence types that
    are defined as equivalent to basic types (such as `int' or `float').

2.  Rather than mapping *everything* to `Object', we could be a bit more
    selective.  We could have the Mercury compiler generate code which uses
    `Object' for all parameters whose type is an abstract data type,
    with the called procedure internally casting to and from the type
    that the ADT is implemented as. 
    
    But this is still bad for both efficiency and interoperability.
    Also it is not easy to implement.  It requires the Mercury compiler not
    expand abstract equivalence types until after code generation, which is
    hard.  And it requires modifications to code generation.

3.  We could have the Mercury compiler treat abstract equivalence types as if
    they were concrete types rather than abstract types, for the purposes of
    code generation.  (Hopefully we can still treat them as abstract types
    for the purposes of type checking, though.)
    
    The problem with this approach is that it breaks our versioning
    model; if a module defines an abstract type, then other
    modules which make use of the abstract type may need to be
    recompiled if the *implementation* (rather than just the
    interface) of that module changes.

    If we don't treat abstract equivalence types as abstract for the
    purposes of typechecking, then it is even worse; that would break
    the abstraction guarantees that the type system normally enforces,
    i.e. guarantees about the source, rather than just breaking the
    versioning properties, which are guarantees about the binaries.

    This approach can be done in a couple of different ways:

    (a) We could put the definitions of abstract equivalence types in
	the `.int' files, for all grades.  These could then be expanded
	either before or after type checking.

    (b) We could put the definitions of abstract equivalence types in
	the `.int' files, but only for .NET/Java.
	We'd install two different copies of the `.int' files,
	and decide which one to use based on the grade.

    (c) We could put the definitions of abstract equivalence types in
        files with some new extension, e.g. `.typ'.

    (d) We could use the definitions of abstract equivalence types that
        are already put in the `.opt' files.  For .NET/Java, we could
	just require users to compile with `--intermodule-optimization'
	enabled.

	For a while this seemed like the most promising approach.
	I spent quite a bit of time working on it.
	Unfortunately it turns out to be a lot more difficult than
	I first thought.  There are various problems:
		- Currently we don't read in the `.opt' files transitively.
		  But to expand all abstract equivalence types, we need to
		  do that.
		- Reading in the `.opt' files transitively is not enough,
		  because some of the stuff in the `.opt' files depends on
		  stuff in the corresponding `.int' files.  So we need to
		  also read in the `.int' files which have not already been
		  read.
		- Reading in the `.int' files would cause problems,
		  because some of the stuff in the `.int' files would
		  clash with stuff in the `.int2' files that we've already
		  read in.
		- Currently we don't read in the `.opt' files for nested
		  modules; that would need to change.  We don't read in
		  the `.opt' files for nested modules because we don't
		  read in the `.int0' files for the contaiing modules,
		  which in turns is because the `.int0' files would
		  clash with the `.int' files that we've already read.
	<sigh>
	Anyway, at the moment I'm continuing to work on this approach.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list