Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2020-12

Local classes and interfaces

4 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author
Behind the scene, the Closures implementation declares classes and interfaces. And, because I strongly believe it to be conceptually the right way, such entities are declared in the innermost routine scope. For example,
-------8<-------
procedure Foo;
	type Local = reference to procedure;
begin
end;
-------8<-------
is essentially
-------8<-------
procedure Foo;
	type Local = interface
		procedure Invoke;
	end;
begin
end;
-------8<-------

FPC does not allow the user to declare local classes/interfaces†, and this shall remain so. However, in order to /internally/ support such entities, a couple of changes is required. I have those implemented, but, firstly, let us establish that the team is on board with the general idea.

† No idea why, but generic local classes/interfaces are accepted. However, FPC instantiates them in the global scope, which results in this wonderful bug:
-------8<-------
function Foo: TClass;
	type Cls<T> = class end;
begin
	result := Cls<Char>
end;
function Bar: TClass;
	type Cls<T> = class end;
begin
	result := Cls<Char>
end;
begin
	// BUG: 'FALSE'
	writeln( Foo()  Bar() )
end.
-------8<-------
βþ

Reply by email

Sven Barth
to Unknown author

Blaise--- via fpc-devel schrieb am Sa.,
19. Dez. 2020, 12:47:

Show quoted text 24 lines
Behind the scene, the Closures implementation declares classes and interfaces. And, because I strongly believe it to be conceptually the right way, such entities are declared in the innermost routine scope. For example, -------8<------- procedure Foo; type Local = reference to procedure; begin end; -------8<------- is essentially -------8<------- procedure Foo; type Local = interface procedure Invoke; end; begin end; -------8<------- FPC does not allow the user to declare local classes/interfaces†, and this shall remain so. However, in order to /internally/ support such entities, a couple of changes is required. I have those implemented, but, firstly, let us establish that the team is on board with the general idea.

Considering that it's only intended for internal use, yes I'm aboard with that.

Show quoted text 24 lines
† No idea why, but generic local classes/interfaces are accepted. However, FPC instantiates them in the global scope, which results in this wonderful bug: -------8<------- function Foo: TClass; type Cls<T> = class end; begin result := Cls<Char> end; function Bar: TClass; type Cls<T> = class end; begin result := Cls<Char> end; begin // BUG: 'FALSE' writeln( Foo() Bar() ) end. -------8<-------

I'd say in this case the bug is that the declaration of those two Cls types is allowed.

By the way: If I remember correctly *specializations* are already placed in the more nested scope if they use local types (or at least that was the plan, I think there are still some bugs left there...).

Regards,
Sven

Reply by email

Unknown author
to Sven Barth
Sven Barth wrote
Considering that it's only intended for internal use, yes I'm aboard with that.

Here is the first change: http://hg.blaise.ru/public/fpc/rev/7c78bfdaed9a (attached).

Strictly speaking, some local classes and interfaces can be compiled without that -- the ICE 200204175 only occurs when they have their own entities such as nested classes (not used for Closures) and non-abstract methods:
-------8<-------
function Foo: TClass;
	type Local = class
		type Nested = class end;
		procedure Method;
	end;
	procedure Local.Method;
	begin
	end;
begin
	result := Local
end;
begin
	Foo
end.
-------8<-------

To observe the effect, one could temporarily use the second attached patch to force FPC to compile the above test case. The following internal names are generated for it: VMT_$P$PROGRAM$_$FOO_$$_LOCAL // no change
VMT_$P$PROGRAM$_$FOO_$LOCAL_$__$$_NESTED // was: ICE P$PROGRAM$_$FOO_$LOCAL_$__$$_METHOD // was: ICE
Please check that such names are in line with the intended format.

I'd say in this case the bug is that the declaration of those two Cls types is allowed.

Looking at the excerpt from object_dec:

{ objects and class types can't be declared local } if not(symtablestack.top.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) and not assigned(genericlist) then Message(parser_e_no_local_objects);

"assigned(genericlist)" seems intentional. Maybe, it misses a check for generic instantiation; however:

If I remember correctly *specializations* are already placed in the more nested scope if they use local types.

Judging solely by the internal names, that is not what happens.

or at least that was the plan

If you were to implement that, you would encounter the same ICE.

βþ

Reply by email

Sven Barth
to Unknown author
Blaise--- wrote 36 lines
On 19.12.2020 16:51, Sven Barth wrote: > Considering that it's only intended for internal use, yes I'm aboard > with that. Here is the first change: http://hg.blaise.ru/public/fpc/rev/7c78bfdaed9a (attached). Strictly speaking, some local classes and interfaces can be compiled without that -- the ICE 200204175 only occurs when they have their own entities such as nested classes (not used for Closures) and non-abstract methods: -------8<------- function Foo: TClass;     type Local = class         type Nested = class end;         procedure Method;     end;     procedure Local.Method;     begin     end; begin     result := Local end; begin     Foo end. -------8<------- To observe the effect, one could temporarily use the second attached patch to force FPC to compile the above test case. The following internal names are generated for it: VMT_$P$PROGRAM$_$FOO_$$_LOCAL // no change VMT_$P$PROGRAM$_$FOO_$LOCAL_$__$$_NESTED // was: ICE P$PROGRAM$_$FOO_$LOCAL_$__$$_METHOD // was: ICE Please check that such names are in line with the intended format.

The format should indeed be okay. Applied in r47834.

Show quoted text 12 lines
> I'd say in this case the bug is that the declaration of those two > Cls types is allowed. Looking at the excerpt from object_dec: >         { objects and class types can't be declared local } >         if not(symtablestack.top.symtabletype in > [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) and >            not assigned(genericlist) then >           Message(parser_e_no_local_objects); "assigned(genericlist)" seems intentional. Maybe, it misses a check for generic instantiation

That might probably be a left over from old times when genericlist was a rather reliable check.

Show quoted text 10 lines
; however: > If I remember correctly *specializations* are already placed in the > more nested scope if they use local types. Judging solely by the internal names, that is not what happens. > or at least that was the plan If you were to implement that, you would encounter the same ICE.

Could be that I only had intended to do that then, but hadn't yet found the time to indeed do so...

Regards,
Sven

Reply by email