OK, I have the new wrapper generator working for primitives, struct and cstruct
constructors, and non-const union variants.

However there's a problem with projections. For a struct or record v you can 
write

        v.fieldname

or equivalently

        fieldname v

and also this works for a pointer. However this should work and
name the projection:

        fieldname of (T)

where T is the struct or record type but it doesn't. For tuples that would be
quite weird:

        1 of (int * long)

would be the name of the second projection. I know why it doesn't work:
the lookups only work in an application  f(x). So for the moment you will
have to manually eta-expand, that is, write the wrapper by hand like:

        struct X { x:int; };
        fun x_value_projection (X:a) => a.x;

The lookup code in the compiler (src/compiler/flx_bind/flx_lookup.ml) is
extremely complex and fragile. Each context is handled separately,
and consistency requires much code duplication. It's hard to factor the
code properly, partly because Ocaml is very bad at functional decomposition
(weird .. for a functional language), and partly because there really are
minor but essential differences between contexts.

Currently the "x" of "X" above is NOT exported to the surrounding scope,
so a lookup requires recognising the type X can have fields in it.
This is easy enough, but it isn't quite so easy to get the "timing" right.
Lookups proceed through the layers of the environment so it isn't
clear what the outcome of this should be:

        struct X {x:int; };
        fun x(a:X)=>1;
        println$ X(42).x;

Which 'x' is found? There is already a routine that does Koenig lookup.
However that looks in the module containing a type definition .. that's
not the same as looking for a field inside the type definition itself.

It used to be that these projections were actually generated physically,
that is, when a struct got put in the symbol table, all the field projections
went in too.

However that mechanism does not work for a record, since record types
are not nominal types (there's no entry in the symbol table).

For unions, however, the constructors ARE put in the symbol table.
[I note: there is a "variant" type which is the dual of a record type,
I have not explored or tested it much though.]

There's a further quirk. At present suffixed names look like this:

        name of (type)

However overload resolution of a call like:

        fold_left f init lst

considers all three arguments (because it can!). This should be allowed
for suffixed names too:

        name of (T1, T2, T3)

The term in parens is a type tuple, they already exist.


To make things more complex: there's a difference between a name with a type

        f of (T)

and a suffixed name which is a QUALIFIED name with a type:

        M::f of (T)


Simple name and qualified name lookup are quite different: qualified name
lookup ONLY searches the given module (and any opens in it), never the parent.
Unqualified name lookup searches parents too.

So part of the problem here is that there is no syntax for an unqualified name 
with
a suffix: suffixed names are qualified names with a suffix.


There are probably some other cases too. Here's one I think: you can use
the name of a struct as a function, it becomes a constructor for the struct
which accepts a tuple argument, with tuple components matches in order
of definition or struct fields.

Of course this cannot work for records, since record fields are not ordered.
However, records and structs should be interconvertible somehow.

You can also use a struct name as a function VALUE, indeed the wrapper
generator recognises when you do that and creates a wrapper.

However for ANY type with a simple name, including any typedef name,
you can define a constructor (actually a conversion function):

        typedef complex = double * double;
        ctor complex (x:double) => x,x;

This actually generates a function

        _ctor_complex: double -> complex

It's an ordinary function, you can actually do lookups on this name and you 
could
just define _ctor_complex. The way this works is that if the compiler see an 
application
of a name to an expression, and the name turns out to be a type name instead of 
a 
function name, the compiler does a second lookup for _ctor_typename.

So, you can apply a type name to an argument .. but you can NOT pass that
constructor as a functional value using the type name (you have to use 
_ctor_typename
instead). Why? Because the code handling the second lookup is nested inside code
deciphering applications, and doesn't include other routines handling other 
contexts
such as suffixed names.

In principle a suffixed *simple* name should act the same as a name in an 
application.
That is if arg has type T then

        f (arg)
        f of (T)

should find the same f.

I can fix all this but I am still trying to enforce

        x .f <--> f x

and right now I'm working on the optimisation and other code handling bound 
terms,
not the parser and binding code. So I don't want to fix these inconsistencies 
at the moment.

--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=157005751&iu=/4140/ostg.clktrk
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to