On Monday, 15 May 2017 at 17:06:34 UTC, ag0aep6g wrote:
On 05/15/2017 05:44 PM, Jonathan Marler wrote:
Not sure if members in this conversation were aware of my DIP
to address
this issue:
https://github.com/dlang/DIPs/pull/61
The DIP uses a different approach to solve this same problem.
It adds
new semantics to specify whether a function should use the
same ABI as a
delegate, called a "delegateable function".
The solution you have proposed would remove the need for my
DIP by
reconciling the difference between the function ABI and
delegate ABI.
I was aware of your DIP. I think they're related, but don't
really overlap that much.
You want to add a special kind of parameter that is taken as
the context pointer when making a delegate of the function. You
also add syntax to combine such a function with a matching
`this` into a delegate.
I'd like the context pointer to be passed differently, so that
a normal function doesn't mistake it for one of its parameters.
I don't think my thing would make your thing obsolete.
You have two ways to go about this, either modify the delegate
ABI to
match the function ABI, or the reverse. The specific change
could be
stated as:
Modify the function/delegate ABI so that the first parameter
of every
function is passed in the same way as the context pointer of a
delegate.
If I'm reading it right, with that rule this would be valid:
----
struct Foo { int x; }
void baz(Foo* foo, int y) { import std.stdio; writeln(foo.x, "
", y); }
void main()
{
void delegate(int y) dg;
dg.funcptr = &baz; /* parameter `foo` is taken as context
pointer */
dg.ptr = new Foo(1);
dg(2); /* would print "1 2" */
}
----
That's not what I'm after. With my (crude) idea, that code
would be just as invalid as it is now. A function's parameters
would have to match the (visible) parameters of the delegate
type. Any context pointer would be passed in a spot where the
function doesn't look.
The point is to allow using functions as delegates that don't
use the context pointer.
Ah ok, you're proposing that the language guarantees that
functions with the same "visible" parameters as delegates use the
same ABI for those parameters. So in this example, foo and bar
would use the same ABI to pass in x:
void foo(int x)
{
}
struct Bar
{
void bar(int x)
{
}
}
The drawback I can see is that it restricts the ABI that
functions can use. Say that our x86 ABI passes all context
pointers using the EAX register (no matter what the other
parameters are). That would imply that function's couldn't use
the EAX register to accept arguments. Note that this would apply
to ALL functions, not just the ones that are going to be called
through delegates, which is a small subset of ALL functions. An
interesting idea but IMO it seems like an odd restriction to put
on all functions.
I do understand wanting a solution to this use case though
(passing a function pointer to a delegate). That is why I
created my DIP after all. However, one could argue that even if
the context pointer is ignored, it might be worth it to
explicitly put it in your function which makes it clear that you
want your function to be ABI compatible with a delegate:
void foo(void* this, int x)
{
// the function doesn't really need the 'this' parameter.
That's
// kind of passing a function to a delegate anyway.
}
struct Bar
{
void bar(int x)
{
}
}
The only drawback here is that you have a 'this' parameter that
you should ignore, but I would actually prefer the more verbose
syntax of adding a "void* this" parameter than forcing all
functions to not use whatever mechanism the equivalent delegate
would use to pass in context pointer.