Opened 10 years ago

Closed 6 years ago

#1 closed defect (fixed)

Check for partial application of functions to unboxed args.

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

Description (last modified by benl)

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 (17)

comment:1 Changed 10 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

comment:2 Changed 10 years ago by benl

  • Description modified (diff)

comment:3 Changed 10 years ago by benl

  • Description modified (diff)

comment:4 Changed 10 years ago by benl

  • Version set to 0.1.2

comment:5 Changed 10 years ago by benl

  • Component changed from Sea Generator to Core to Sea Translation

comment:6 Changed 10 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.

comment:7 Changed 10 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.

comment:8 Changed 10 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.

comment:9 Changed 10 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.

comment:10 Changed 9 years ago by benl

  • Milestone changed from 0.1.3 to 0.1.5

comment:11 Changed 8 years ago by benl

  • Milestone 0.1.5 deleted

Milestone 0.1.5 deleted

comment:12 Changed 8 years ago by benl

  • Priority changed from minor to project

comment:13 Changed 8 years ago by benl

  • Priority changed from project to normal

comment:14 Changed 7 years ago by benl

  • Milestone set to 0.3.0

comment:15 Changed 7 years ago by benl

  • Milestone changed from 0.3.0 to 0.4.0

We'll be able to check this once we implement the #curry primop in 0.4.0

comment:16 Changed 6 years ago by benl

  • Description modified (diff)
  • Milestone changed from 0.4.0 to 0.4.1

comment:17 Changed 6 years ago by benl

  • Resolution set to fixed
  • Status changed from new to closed

This fix was a long time coming. With DDC 0.4 we can detect partial application of primops and give an error. We also don't have explicit unboxed values in the source language, so we can't do a manual partial application of a function to an unboxed value.

Note: See TracTickets for help on using tickets.