Ticket #1 (new defect)

Opened 5 years ago

Last modified 5 years ago

Check for partial application of functions to unboxed args.

Reported by: benl Owned by:
Priority: minor Milestone: 0.1.3
Component: Core to Sea Translation Version: 0.1.2
Keywords: Cc:

Description (last modified by benl) (diff)

Runtime system cannot handle partial application of functions to unboxed args. It'd be easy to check for this problem in the core language, and panic.

Test is T1-CurryUnboxed.

Change History

Changed 5 years ago by benl

  • description modified (diff)

This currently causes a GCC error when it tries to build the thunk.

        _dEF2_a0_exp:
        _S(1)                   = _allocThunk (Main_fun, 2, 1);
        _TARG(_S(1), 0)         = 2;   ********** type error
        _S(2)                   = _allocThunk (System_Console_putStr, 1, 0);
        _S(3)                   = _allocThunk (Class_Show_instance_Show_Int32_show, 1, 0);

./test/Broken-skip/T1-CurryUnboxed/Main.ddc.c: In function ‘Main_main’:
./test/Broken-skip/T1-CurryUnboxed/Main.ddc.c:39: warning: assignment makes pointer from integer without a cast
./test/Broken-skip/T1-CurryUnboxed/Main.ddc.c:42: warning: passing argument 2 of ‘_apply1’ makes pointer from integer without a cast
./test/Broken-skip/T1-CurryUnboxed/Main.ddc.c:42: warning: assignment makes integer from pointer without a cast
d

Changed 5 years ago by benl

  • description modified (diff)

Changed 5 years ago by benl

  • description modified (diff)

Changed 5 years ago by benl

  • version set to 0.1.2

Changed 5 years ago by benl

  • component changed from Sea Generator to Core to Sea Translation

Changed 5 years ago by erikd

Richard said on IRC he didn't understand this bug so I'll try to explain (and possibly end up explaining stuff he already knows). Hopefully Ben will correct anything thats wrong.

Partial application is relayed to Currying:

http://en.wikipedia.org/wiki/Currying

Given a function f of say 3 arguments, it is be possible to create a function g of 1 argument by setting the first two arguments of f and leaving the third argument free.

For boxed vs unboxed, try this:

http://en.wikipedia.org/wiki/Boxing_%28computer_science%29#Boxing

For example, Disciple has both boxed Int32 values and unboxed Int32# values (note the '#' sign signifying unboxed).

The problem in this bug is that the runtime system cannot handle partial application of functions to unboxed arguments. That is in the example above, when creating function g, the first two arguments to f must be boxed for the runtime to do the right thing.

Ben's suggestion to fix this is to disallow unboxed values during partial application.

Changed 5 years ago by erikd

  • owner set to benl

Rough fix for this in the following patch:

Tue Sep 1 06:08:58 EST 2009 Erik de Castro Lopo <erikd@…>

  • Fix #1 : Check for partial application of functions to unboxed args.

Also move test/Broken-skip/T1-CurryUnboxed? to test/01-Error/60-ToSea?/T1-CurryUnboxed? and add an error.check file.

Reassigning to Ben to convert the panic to a compiler error.

Changed 5 years ago by benl

  • owner changed from benl to -

From the mailing list ...

I've thought some more about it, and I don't think it's easy to fix.

Changing the representation of thunks to hold unboxed arguments is the easy part. The hard part is to actually call the function after all all the arguments have been collected. The code we're using at the moment is in runtime/Eval.ci.

Say we have a function of the following type: int fun (Obj* x1, int x2, char x3, Obj* x4, Obj* x5)

If we have structure containing a value for each of these arguments, how do we take those arguments and call the function? I can't think of any general, portable way to do it...

A brute-force solution would be to generate code to call a function with any possible combination of argument types, but that'll blow up if there are too many arguments.

Another way would be to make all the parameter types void*, but that doesn't handle functions which accept doubles, as they won't fit in a single machine word on 32 bit platforms.

Without resorting to non-portable hacks, the only way I can think of doing it would be to compile all the .ds sources and then examine the interface files to see what types of C functions they compile to. Once this is done, programatically generate the required eval functions, compile that separately and link it into the main executable. That'd work, and be ok, but it's a reasonable amount of work.

I think I remember seeing a semi-standard C library for doing partial application --- but I can't remember where, or whether it worked for all architectures, and some brief Googling hasn't uncovered it.. worth investigating.

Changed 5 years ago by benl

  • owner - deleted

We can probably do this with libffi.

If it's fast enough, it'd be better to replace the functions in Eval.ci with calls via libffi.

Note: See TracTickets for help on using tickets.