What facilities does GPC have for forward defining types.
In CW Pascal, I have some code that looks like this:
type MyProc = procedure( browser: MyObjectA ); MyObjectA = object f: MyProc; b: MyObjectB; procedure Doit( proc: MyProc ); function GetB: MyObjectB; end; MyObjectB = object; f: MyObjectA; // other references to ObjectA end;
Keep in mind all the "used before defined" types are pointer types (objects being implicitly pointers) and defined in the same "type" block.
GPC is not happy with this. Needless to say, given the dual referential nature of the references, it is hard to see how I can cleanly untangle this.
Is there any support in GPC or EP for these kinds of forward defined types? Any suggestions how I can untangle them within GPC?
The best I can see is to turn all of them into explicit pointers and explicit dereferences, which is doable, but rather ugly.
Any suggestions?
Thanks, Peter.
Peter N Lewis wrote:
What facilities does GPC have for forward defining types.
In CW Pascal, I have some code that looks like this:
type MyProc = procedure( browser: MyObjectA ); MyObjectA = object f: MyProc; b: MyObjectB; procedure Doit( proc: MyProc ); function GetB: MyObjectB; end; MyObjectB = object; f: MyObjectA; // other references to ObjectA end;
Keep in mind all the "used before defined" types are pointer types (objects being implicitly pointers) and defined in the same "type" block.
GPC is not happy with this. Needless to say, given the dual referential nature of the references, it is hard to see how I can cleanly untangle this.
Is there any support in GPC or EP for these kinds of forward defined types?
EP only supports explicit pointers. These objects are implicit pointers (or references), as you know.
For explicit pointers, there's a provision in standard Pascal (and all dialects I know of), so there is no problem there. (And that's what GPC currently supports.) You just declare pointer types to the object types before the object types themselves and before MyProc.
Implicit references present a new problem here. ATM, I don't see a really nice solution. Allowing forward referencing of any type would be both difficult to implement and IMHO bad style, weakening Pascal's principles.
Looking at OOE ... AFAICS, their solution to this problem is the following:
: 6.1.5 Deferred class definitions. : : A class name can be declared before its structure and contents are defined. : This is specified by: : : TYPE : name = [ kind ] CLASS .. END; : : NOTE: In the above, ".." is a symbol. : : Later in the same type-definition-part, there must be a type definition with : the same name that specifies the contents and structure of the class. A class : cannot be used in a class-inheritance-list before its complete definition is : specified.
I think this could be reasonable. Similarly to a forward-defined pointer type, this forward-defines a reference type.
We could probably add the same with `object' references. (Waldek?)
Frank
At 9:26 +0200 5/7/05, Frank Heckenbach wrote:
Looking at OOE ... AFAICS, their solution to this problem is the following:
: 6.1.5 Deferred class definitions. : : A class name can be declared before its structure and contents are defined. : This is specified by: : : TYPE : name = [ kind ] CLASS .. END; : : NOTE: In the above, ".." is a symbol. : : Later in the same type-definition-part, there must be a type definition with : the same name that specifies the contents and structure of the class. A class : cannot be used in a class-inheritance-list before its complete definition is : specified.
I think this could be reasonable. Similarly to a forward-defined pointer type, this forward-defines a reference type.
We could probably add the same with `object' references. (Waldek?)
Assuming it worked for object references, that would have solved my problem, as I could have added
MyObjectA = object .. end; MyObjectB = object .. end;
to the start of the type declaration and all would be well.
I imagine that would only work with non object reference if GPC was smart enough to know that the size was unknown and therefore it could only be used as parts of types where its size was not needed (eg ^MyObjectA). Whether that would be useful, I don't know, unless it could also cope with a case like:
MyObjectA = object .. end; MyProc = procedure( var obj: MyObjectA ); MyObjectA = object f: MyProc; end;
But that would all be much harder than the case of class/reference object where the type size is known to match SizeOf(Ptr) even though the type is not defined fully yet, just like explicit forward pointer definitions.
Thanks, Peter.
type MyProc = procedure( browser: MyObjectA ); MyObjectA = object f: MyProc; b: MyObjectB; procedure Doit( proc: MyProc ); function GetB: MyObjectB; end; MyObjectB = object; f: MyObjectA; // other references to ObjectA end;
Peter N Lewis wrote:
At 9:26 +0200 5/7/05, Frank Heckenbach wrote:
Looking at OOE ... AFAICS, their solution to this problem is the following:
: 6.1.5 Deferred class definitions. : : A class name can be declared before its structure and contents are defined. : This is specified by: : : TYPE : name = [ kind ] CLASS .. END; : : NOTE: In the above, ".." is a symbol. : : Later in the same type-definition-part, there must be a type definition with : the same name that specifies the contents and structure of the class. A class : cannot be used in a class-inheritance-list before its complete definition is : specified.
I think this could be reasonable. Similarly to a forward-defined pointer type, this forward-defines a reference type.
We could probably add the same with `object' references. (Waldek?)
Assuming it worked for object references, that would have solved my problem, as I could have added
MyObjectA = object .. end; MyObjectB = object .. end;
to the start of the type declaration and all would be well.
Yes, I think so.
I imagine that would only work with non object reference if GPC was smart enough to know that the size was unknown and therefore it could only be used as parts of types where its size was not needed (eg ^MyObjectA). Whether that would be useful, I don't know, unless it could also cope with a case like:
What are non-object references? I only know var-parameters and in a sense, absolute-variables, both don't apply here.
MyObjectA = object .. end; MyProc = procedure( var obj: MyObjectA ); MyObjectA = object f: MyProc; end;
But that would all be much harder than the case of class/reference object where the type size is known to match SizeOf(Ptr) even though the type is not defined fully yet, just like explicit forward pointer definitions.
Oh, you mean non-reference objects, I suppose. In this case, I don't think it should work. BP doesn't allow the above, though BP (and GPC as well) allow this:
program Foo;
type MyObjectA = object f: procedure( var obj: MyObjectA ); end;
begin end.
And even this (GPC with the usual warning about value object parameters):
program Foo;
type MyObjectA = object f: procedure( obj: MyObjectA ); end;
begin end.
Frank
At 12:50 +0200 5/7/05, Frank Heckenbach wrote:
I imagine that would only work with non object reference if GPC was smart enough to know that the size was unknown and therefore it could only be used as parts of types where its size was not needed (eg ^MyObjectA). Whether that would be useful, I don't know, unless it could also cope with a case like:
What are non-object references? I only know var-parameters and in a sense, absolute-variables, both don't apply here.
Sorry, I was unclear, I meant objects that are not references (ie, the record style objects used by BP and GPC, as opposed to the reference/pointer style objects used by Delphi/Mac/and Waldek's new GPC patches.
But that would all be much harder than the case of class/reference object where the type size is known to match SizeOf(Ptr) even though the type is not defined fully yet, just like explicit forward pointer definitions.
Oh, you mean non-reference objects, I suppose.
Right.
In this case, I don't think it should work. BP doesn't allow the above, though BP (and GPC as well) allow this:
I just try to get as much consistency as is possible within the bounds of the different syntax and facilities.
program Foo;
type MyObjectA = object f: procedure( var obj: MyObjectA ); end;
begin end.
And even this (GPC with the usual warning about value object parameters):
program Foo;
type MyObjectA = object f: procedure( obj: MyObjectA ); end;
begin end.
Neither of those would allow the case of ObjectA referencing ObjectB and vice versa though (it doesn't really come up in non-reference objects though because you have to have a pointer anyway, and so the normal "forward defined pointer types" trick works. Peter.
Peter N Lewis wrote:
In this case, I don't think it should work. BP doesn't allow the above, though BP (and GPC as well) allow this:
I just try to get as much consistency as is possible within the bounds of the different syntax and facilities.
program Foo;
type MyObjectA = object f: procedure( var obj: MyObjectA ); end;
begin end.
And even this (GPC with the usual warning about value object parameters):
program Foo;
type MyObjectA = object f: procedure( obj: MyObjectA ); end;
begin end.
Neither of those would allow the case of ObjectA referencing ObjectB and vice versa though (it doesn't really come up in non-reference objects though because you have to have a pointer anyway, and so the normal "forward defined pointer types" trick works.
Indeed (and this was about this model, i.e. BP). For the other models, forward declaring object types/classes (even with different syntaxes, alas) seems to fill this gap.
Frank