April 03, 2012
On 04/03/2012 02:08 PM, Don Clugston wrote:
> On 03/04/12 13:58, Timon Gehr wrote:
>> On 04/03/2012 01:55 PM, Don Clugston wrote:
>>> On 03/04/12 13:35, Timon Gehr wrote:
>>>> On 04/03/2012 01:08 PM, Don Clugston wrote:
>>>>>
>>>>> Y b() { ... }
>>>>> Y y = b();
>>>>> X x = ...
>>>>>
>>>>> Prove that y doesn't depend on x.
>>>>
>>>> Since only function declarations are immune to ordering rules, b cannot
>>>> forward reference x.
>>>
>>> But there could be another function a() which is below x, and which b()
>>> calls.
>>
>> This scenario can be forbidden conservatively.
>
> How?

Don't allow forward referencing function a() if there is an intervening order-dependent declaration.

(Alternatively, just analyse which symbols are referenced where and don't allow calling a local function that can transitively reach some symbols that have not yet been declared. I think this might be too complicated to be justifiable.)
April 03, 2012
>>> void foo(){
>>>      void a()(){ ... }
>>>      void b()  { ... }
>>> }
>>>
>>
>> That's a very simple workaround (albiet unintuitive - unless I'm just too
>> tired right now). It leads me to two questions:
>>
>> 1. How the heck does that work?
>>
>
> Symbol lookup is done upon the first instantiation of the local template.
>

I'd argue it shouldn't work, but it'd require copying the scope.
instantiation scope -> declaration scope -> sequence snapshot
So again b shouldn't be is a's scope.
April 04, 2012
On 03/04/12 07:38, Nick Sabalausky wrote:
> Regarding this:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=790
>
> I submit that nested functions should be exempt from the usual sequential
> visibility rules. (Therefore, mutually recursive nested functions would
> become possible.)
>
> Or at the very *least*, this horrific C-like workaround should be possible:
>
> void foo()
> {
>      void b();
>      void a() {...};
>      void b() {...};
> }
>
> ...Flame away! ;)
>
>

The most flexible method is to declare a local, nested struct. Any member functions (and variables!) of that struct have non-sequential semantics, so they can forward reference each other just fine.

void foo()
{
    struct Local
    {
	static void a() { b(); }
        static void b() { };
    }
    Local.a();
}

If they need to access stack variables, you'll need to create an actual instance of the struct. You can make it a static struct if they don't need access to any stack variables of foo.

Note that this completely sidesteps all the nasty issues I mentioned in other posts.
April 04, 2012
On Tuesday, 3 April 2012 at 12:13:00 UTC, Timon Gehr wrote:
> On 04/03/2012 02:00 PM, Nick Sabalausky wrote:
>> "Timon Gehr"<timon.gehr@gmx.ch>  wrote in message
>> news:jlej27$mvi$1@digitalmars.com...
>>>
>>> This is the right way to work around this issue. It works now and does not
>>> imply any kind of overhead at runtime:
>>>
>>> void foo(){
>>>     void a()(){ ... }
>>>     void b()  { ... }
>>> }
>>>
>>
>> 1. How the heck does that work?
>>
>
> Symbol lookup is done upon the first instantiation of the local template.

Currently, it prints 365. But remove the commented line, and it prints 500 twice. But it's a minor issue at worst that's easy to avoid, and this is a very simple workaround.

int two()
{
	return 500;
}

void main()
{
	int x = 365;
	
	int one()()
	{
		return two();
	}
	
	// writeln(one());
	
	int two()
	{
		return x;
	}
	
	writeln(one());
}


I found another solution involving templates, though not as convenient:

template foo()
{
	int one(){
		return two();
	}
	
	int two(){
		return x + y;
	}
	
	int y = 12;
}

void main()
{
	int x = 365;
	mixin foo;
	writeln(one());
}

April 05, 2012
On 4/3/2012 2:56 AM, Don Clugston wrote:
> Difficult but doable, but I think you end up with a really funky rule.
> It's a morass of special cases.

I agree with Don. And in the end, is a morass of complexity worth it to deal with one special case that is both unusual and has a reasonable workaround?

I'd say no.
April 05, 2012
On 4/4/2012 12:57 AM, Don Clugston wrote:
> The most flexible method is to declare a local, nested struct. Any member
> functions (and variables!) of that struct have non-sequential semantics, so they
> can forward reference each other just fine.

Thanks, Don. I didn't think of this, and it's an awesome solution. Can you put it in the D FAQ?
October 11, 2012
>> The most flexible method is to declare a local, nested struct.
> ... it's an awesome solution.

It is a solution, but IMO it looks unpleasant.
Reminds me C++, where I had to do this trick all the time.

> It's a morass of special cases.

If D had a notion of pure pure functions - pure functions without any "concessions to practicality" then we could consider this simple rule:
"local pure pure functions can be forward referenced".
1 2 3
Next ›   Last »