I would like to slightly update Mac objects and Delphi classes support. In particular I ma thinking about options names.
AFAICS there five major axes which differentiate dialects that we would like to support:
1) Value versus reference model:
BP - value model (objects are values)
OOE, Delphi, Mac - pointer model (object are pointer to values)
2) Static versus virtual methods:
OOE, Mac - mehods are always virtual BP, Delphi - there are static methods
3) Keywords used:
BP, Mac - use "object" as a keyword (but with different semantics) OOE, Delphi - use "class" keyword
4) Method redefinition:
BP - silent overriding Delphi - silent shadowing, override needs "override" OOE, Mac - explicit "override" needed
5) Base object:
BP, Mac - no base object, multiple roots OOE - "Root" is the root of inheritance tree Delphi - "TObject" is the root of inheritance tree
There is also question if constructors are mandatory for objects with virtual methods. ATM I think that we may tie this to object model: in value model (BP) make them mandatory, in reference mode make them optional. Namely, Mac objects have no constructors while OOE and Delphi will get them without any explicit declaration.
I propose to have the following options:
-fobjects-are-references -- choose reference model even if the declaration uses "object" keyword, on for Mac Pascal, off otherwise -fmethods-always-virtual -- leave it as is -fobjects-require-override -- to require "override" even for objects declared using "object" keyword (classes will always require "override") -fdelphi-method-shadowing -- redefinition without override will shadow (hide) old definition. By default to hide old definition one would have to use OOE "view" or Delphi "reintroduce" directive
-fbase-object= -- to add default parent to object without an explicit parent
the last option will require some effort to implement.
Additionally, we may have -fmac-objects directive, which would be equivalent to sum of -fobjects-require-override, -fmethods-always-virtual and -fobjects-are-references.
Comments?
Waldek Hebisch wrote:
I would like to slightly update Mac objects and Delphi classes support. In particular I ma thinking about options names.
Good idea. I agree for the most part, except as noted below.
There is also question if constructors are mandatory for objects with virtual methods. ATM I think that we may tie this to object model: in value model (BP) make them mandatory, in reference mode make them optional. Namely, Mac objects have no constructors while OOE and Delphi will get them without any explicit declaration.
(Yes, from the implicit base object.)
I think I also wouldn't mind coupling it to the BP dialect option even. BP's implementation requires this, so for strict compatibility, we should offer to check this (it's only a warning ATM, anyway), otherwise I don't really see it required with GPC's implementation for any model. (In fact, I'd rather think about warning if in a model that has constructors at all, an object has no constructors -- regardless of whatever methods it has. This would be a more consistent demand, whereas the existing check is just to satisfy a detail of the BP implementation. Anyway, such a more general warning is not a high priority to me. I don't mean to implement it now. I just mention it to avoid overestimating the value of the existing warning.)
I propose to have the following options:
-fobjects-are-references -- choose reference model even if the declaration uses "object" keyword, on for Mac Pascal, off otherwise
(Yes, while `class' will always mean references.)
-fbase-object= -- to add default parent to object without an explicit parent
the last option will require some effort to implement.
It would also be a bit strange to have command-line options and/or compiler directives refer to syntactical entities (we don't do this in other options, apart from {$debug-tree} which is an internal debuging feature), and it might raise semantic questions if classes are renamed in import/export, perhaps even of questions scope (not easily, as object/class definitions have to be global -- I know this in BP and OOE, I suppose it's also so in Mac and Delphi --, but we might have to consider local imports, I didn't think this through yet).
An alternative would be to mark the root classes on declaration (in some way we'd yet have to thing about, whether a special directive, an attribute or whatever), and just have the options activate a previously declared (and usually imported, from the RTS) root class (more precisely, one of two possible root classes, for OOE and Delphi). Of course, it would be errors to declare more than these two potential root classes, or to activate one that wasn't declared, etc., but this shouldn't normally affect a user who uses the default RTS.
This is provided the root classes can be implemented in Pascal properly, without compiler magic. For OOE's Root, I see no problem (apart from the usual compiler magic for constructors and destructors). For Delphi, I don't know. But if it turns out that we do need magic, or that the compiler has to know the specific TObject class for some purpose, this would IMHO even more suggest making them special on declaration, rather then referring to them by name in an option.
Additionally, we may have -fmac-objects directive, which would be equivalent to sum of -fobjects-require-override, -fmethods-always-virtual and -fobjects-are-references.
plus -fno-delphi-method-shadowing -fno-base-object (i.e., so it sets the complete object model, not only turns on certain features. If one wants a mix, one can always give the deviating options afterwards).
I think we should have such an option for all four models, equivalent to the respective combination of positive and negative options. Also, the respective language dialect options should then imply the --foo-objects options (instead of the feature options directly, as e.g. currently --mac-pascal -> --methods-always-virtual).
Frank
Frank Heckenbach wrote:
Waldek Hebisch wrote:
-fbase-object= -- to add default parent to object without an explicit parent
the last option will require some effort to implement.
It would also be a bit strange to have command-line options and/or compiler directives refer to syntactical entities (we don't do this in other options, apart from {$debug-tree} which is an internal debuging feature), and it might raise semantic questions if classes are renamed in import/export, perhaps even of questions scope (not easily, as object/class definitions have to be global -- I know this in BP and OOE, I suppose it's also so in Mac and Delphi --, but we might have to consider local imports, I didn't think this through yet).
I agree that such thing makes more sense as na option (affecting the whole file) then as a (possibly local) directive.
An alternative would be to mark the root classes on declaration (in some way we'd yet have to thing about, whether a special directive, an attribute or whatever), and just have the options activate a previously declared (and usually imported, from the RTS) root class (more precisely, one of two possible root classes, for OOE and Delphi). Of course, it would be errors to declare more than these two potential root classes, or to activate one that wasn't declared, etc., but this shouldn't normally affect a user who uses the default RTS.
This is provided the root classes can be implemented in Pascal properly, without compiler magic. For OOE's Root, I see no problem (apart from the usual compiler magic for constructors and destructors). For Delphi, I don't know. But if it turns out that we do need magic, or that the compiler has to know the specific TObject class for some purpose, this would IMHO even more suggest making them special on declaration, rather then referring to them by name in an option.
ATM I think that we should have a single-rooted tree of exception classess which should be known to the compiler. For compatibility with Delphi exception classess should be TObject descendants.
Implementing such classes in Pascal seems much easier then hardcoding class declaration in the compiler. The -fbase-object= option looks like the easiest way to implement Root/TObject. Actually, before things stabilize I would like to Root/TObject to be user level code, outside of RTS proper. But I agree that such option may be too dangerous/confusing for users.
Additionally, we may have -fmac-objects directive, which would be equivalent to sum of -fobjects-require-override, -fmethods-always-virtual and -fobjects-are-references.
plus -fno-delphi-method-shadowing -fno-base-object (i.e., so it sets the complete object model, not only turns on certain features. If one wants a mix, one can always give the deviating options afterwards).
I think we should have such an option for all four models, equivalent to the respective combination of positive and negative options. Also, the respective language dialect options should then imply the --foo-objects options (instead of the feature options directly, as e.g. currently --mac-pascal -> --methods-always-virtual).
Hmm, I was affraid that I already propose too many options. We would like to have a single "unified" dialect, but the options will allow quite a lot of variation. My reasoning was:
1) we want support the four object models (dialects) 2) we need support for migrating legacy code 3) we need support for "blended code" (code that works both with GPC and other compiler)
1) is handled by dialect options. For 2) we need precise control, hence the detailed options. For 3) our current dialect support is too weak, we frequently have equivalent functionality as other compilers, but using different syntax. So "blended code" have to use full GPC language + macros and conditionals. For bulk of the code it is (or will be) possible to have the same source, with the notable exception of Mac Pascal -- hence I proposed specific option.
BTW: BP and Delphi models coexist in a single compiler (namely Delphi itself). So while meaning of -mac-objects looks reasonable clear to me the other look more fuzzy.
Waldek Hebisch wrote:
ATM I think that we should have a single-rooted tree of exception classess which should be known to the compiler.
Indeed.
For compatibility with Delphi exception classess should be TObject descendants.
Or the other way around, i.e. let TObject be a descendant of the exception root (I'll call it TException in the following). This would be more Delphi compatible (every TObject could be an exception), and I'd prefer it for other reasons (TException didn't have to carry ballast from TObject).
OTOH, I think TException should be a descendant of Root (no compatibility issues as OOE doesn't deal with exceptions; and Root doesn't carry much ballast).
So we'd have:
Root -> TException -> TObject
(About the drawbacks of letting TObject have a parent, see below.)
Implementing such classes in Pascal seems much easier then hardcoding class declaration in the compiler.
Totally agreed. I never meant to hard-code it in the compiler if it can be avoided at all. IMHO it should go in the RTS (at least in the longer run) and be automatically imported (where appropriate).
The -fbase-object= option looks like the easiest way to implement Root/TObject. Actually, before things stabilize I would like to Root/TObject to be user level code, outside of RTS proper. But I agree that such option may be too dangerous/confusing for users.
For testing and developing, this option might not hurt. But if you say it will be difficult to implement, and in the long run we want something different, perhaps we should do the different thing right away to save effort.
I'm still thinking along the lines of an attribute on declaration of the root class or similar. IMHO, the RTS units should have no special properties here, apart from automatic import (later), so everything that should later go into the RTS could be done in user code now.
Additionally, we may have -fmac-objects directive, which would be equivalent to sum of -fobjects-require-override, -fmethods-always-virtual and -fobjects-are-references.
plus -fno-delphi-method-shadowing -fno-base-object (i.e., so it sets the complete object model, not only turns on certain features. If one wants a mix, one can always give the deviating options afterwards).
I think we should have such an option for all four models, equivalent to the respective combination of positive and negative options. Also, the respective language dialect options should then imply the --foo-objects options (instead of the feature options directly, as e.g. currently --mac-pascal -> --methods-always-virtual).
Hmm, I was affraid that I already propose too many options.
Not a big deal IMHO. ;-)
We would like to have a single "unified" dialect, but the options will allow quite a lot of variation. My reasoning was:
we want support the four object models (dialects)
we need support for migrating legacy code
we need support for "blended code" (code that works both with GPC and other compiler)
is handled by dialect options.
But dialect options in general are very strong options and have a lot of "side-effects". That's why I propose object-model-only options, which are part of the dialect options, but without all the other, unrelated, dialect stuff.
For 2) we need precise control, hence the detailed options.
Agreed.
BTW: BP and Delphi models coexist in a single compiler (namely Delphi itself). So while meaning of -mac-objects looks reasonable clear to me the other look more fuzzy.
True, I hadn't considered this.
As you proposed, -fobjects-are-references and -fobjects-require-override would only apply to "object". Couldn't we also restrict -fdelphi-method-shadowing and -fbase-object= (or whatever it will become) to "class" only? Then each object model option would only imply the former two options (for models that use "object") or the latter two (for "class"), so --bp-objects and --delphi-objects could happily coexist.
In particular, they would not disable the respective other keyword, only the full dialect options would do this. (And it can always be done explicitly with --disable-keyword.)
Waldek Hebisch wrote:
Prof A Olowofoyeku (The African Chief) wrote:
With regard to Root and TObject (OOE and Delphi), I have suggested elsewhere that one could probably be a silent ancestor of the other. In fact, they could be one and the same thing (with names changing, and/or members hidden or revealed depending on Delphi or OOE mode). I am not sure whether this makes any sense ...
I don't think hiding declarations based on directives is a good idea. The problems with the built-in `Result' should be a lesson to us (not quite the same, but a similar topic).
Consider the following program:
[...]
while pointer(c) <> nil do begin writeln(c.classname); c := c.classparent;
However, if we add extra parent to TObject the first printouts would change. Note that while prp2 would crash on non-Delphi class, both prp1 and prp2 will work fine if we implement Delphi tree correctly.
Doesn't it depend on the definition of ClassParent (I suppose it's a Delphi builtin)? If we make it stop (return nil) at the Delphi root class, it would still work if there are other superclasses (kind of hidden from Delphi code then). I admit, it may not be the nicest feature, but perhaps better than the alternatives.
Prof A Olowofoyeku (The African Chief) wrote:
However, if we add extra parent to TObject the first printouts would change. Note that while prp2 would crash on non-Delphi class, both prp1 and prp2 will work fine if we implement Delphi tree correctly.
In which case, TObject and Root would need to be independent of each other.
This would make it difficult to write common code (including exception handling).
Waldek Hebisch wrote:
Prof A Olowofoyeku (The African Chief) wrote:
On 22 Oct 2005 at 20:06, Waldek Hebisch wrote:
<snip>
Compile and run this with BP, and you get garbage. With FPC, you get a warning at compile time, and a runtime error at runtime. With Virtual Pascal, you get a runtime error at runtime. Add and call a constructor, and the problem goes away.
So, a warning is not a bad idea (better than a crashing program).
Maybe I was not clear: I do not want to change how BP objects behave, so the warning for BP objects will stay in place. But I see no need for such warning in other models.
I agree. The Chief's example is just what I meant with an "implementation detail". In particular, to a programmer new to the object model, it wouldn't seem very intuitive why turning some method from static to virtual would necessitate a constructor that wasn't needed before. (One can give reasons with VMT pointers and the magic that constructors and virtual method calls do, but then we're already deep into implementation details.)
So I don't see such a warning as a generally-useful concept, even in the BP model. It's useful regarding the BP *implementation*, i.e. when writing code with GPC and trying to make sure it still works with BP. Therefore I'd rather tend to tie it to the --borland-pascal and --delphi dialect options. Of course, dialect options are generally a rather hard hammer (see above), but when writing code meant to run also under BP, you (almost) need it anyway.
BTW, the warning only can do so much anyway. In fact, under BP, a constructor doesn't only have to exist, it must also be called. This can't be checked at compile-time. BP, and since the last alpha also GPC, can do this, BP with "range checking", GPC with --object-checking, also tied to {$R+} for BP compatibility.
The other variants also have drawbacks, that is why I would prefer to leave the choice to programmers.
Yes, the programmers should have the choice - but the question is whether that choice should be exercised in code or at the command line. With regard to default ancestors, I think it would be problematic and error-prone to change default ancestors at the command line.
The point here is to minimize impact on existing code -- if a programmer have to change the code then she has no choice.
I don't think they should have to change the code WRT base classes, with either of our suggestions. After providing the base class (explicitly, and later in the RTS), and perhaps setting the right options, the actual class declarations should be unaffected (compared to OOE and Delphi).
Prof A Olowofoyeku (The African Chief) wrote:
On 22 Oct 2005 at 23:29, Waldek Hebisch wrote:
Of course, we can limit choice to none, "Root" or "TObject". Also, having to give a long chain of options will somewhat reduce abuse.
Since "Class" should (IMHO) mean an OOE or a Delphi class,
It will always mean either of them (until we add more dialects ;-).
I think the choices should be between "TObject" (default) or "Root". If the answer is "none" or something else, then "Class" in that case does not refer to a Delphi or OOE class, because it would be incompatible with both of them. Should this be allowed? I think not.
It will be necessary in order to implement the root class itself without compiler magic.
Of course, this is a very special case (that should occur exactly two times in the long run -- both in the RTS). Therefore we might also make this case a bit more difficult, in order to simplify normal usage:
- The compiler has N "slots" for root classes (currently N=2, unless we want N=3 for experimenting or whatever).
- There is an option that makes one of these N slots active at any time.
- When a "class" without ancestor is declared, and the active slot is filled, it becomes the implicit ancestor.
- When a "class" is declared, and the active slot is not filled, the class goes into that slot. (I'm not saying "without ancestor" here, as TObject might have non-Delphi ancestors, see above.)
- Additionally, in the previous case a warning is given (so it doesn't happen unintentionally in user code). Or stronger, an error, unless the declaration is specially flagged (with an attribute or whatever).
- Root class slots are transported through GPI files, and RTS GPI files are automatically imported, depending on the dialect. (I plan the latter anyway, to reduce the amount of compiler magic in other areas.) Importing into a slot already occupied will be an error. There is no way to change the slot on import (such as renaming does to the name), so once in the slot, a class will always occupy this slot when it's imported at all.
- The RTS can declare both root classes as regular "class"es, while setting respective object model options (locally), and explicitly disabling the above-mentioend warning (locally, of course), or setting the necessary attribute, respectively.
- Depending on the dialect options, respective interfaces from the RTS are automatically imported. As they will define the root classes, under normal circumstances, every "class" in user space will get an implicit ancestor.
Frank
Frank Heckenbach wrote:
Waldek Hebisch wrote:
ATM I think that we should have a single-rooted tree of exception classess which should be known to the compiler.
Indeed.
For compatibility with Delphi exception classess should be TObject descendants.
Or the other way around, i.e. let TObject be a descendant of the exception root (I'll call it TException in the following). This would be more Delphi compatible (every TObject could be an exception), and I'd prefer it for other reasons (TException didn't have to carry ballast from TObject).
Well, we have two things: - classes which may be exceptions - standard exception classes
In Delphi the first is just all Delphi classes = all descendants of TObject. The second is smaller.
For compatibility with Delphi our standard exception classes should be descendants of TObject.
Allowing exception classes outside of Delphi tree limits compatibility.
OTOH, I think TException should be a descendant of Root (no compatibility issues as OOE doesn't deal with exceptions; and Root doesn't carry much ballast).
So we'd have:
Root -> TException -> TObject
(About the drawbacks of letting TObject have a parent, see below.)
Maybe, but: - standard exceptions must live below TObject anyway - the balast of TObject is a bunch of VMT slots, it will matter only if you have thousends of different exceptions
Additionally, we may have -fmac-objects directive, which would be equivalent to sum of -fobjects-require-override, -fmethods-always-virtual and -fobjects-are-references.
plus -fno-delphi-method-shadowing -fno-base-object (i.e., so it sets the complete object model, not only turns on certain features. If one wants a mix, one can always give the deviating options afterwards).
I think we should have such an option for all four models, equivalent to the respective combination of positive and negative options. Also, the respective language dialect options should then imply the --foo-objects options (instead of the feature options directly, as e.g. currently --mac-pascal -> --methods-always-virtual).
Hmm, I was affraid that I already propose too many options.
Not a big deal IMHO. ;-)
We would like to have a single "unified" dialect, but the options will allow quite a lot of variation. My reasoning was:
we want support the four object models (dialects)
we need support for migrating legacy code
we need support for "blended code" (code that works both with GPC and other compiler)
is handled by dialect options.
But dialect options in general are very strong options and have a lot of "side-effects". That's why I propose object-model-only options, which are part of the dialect options, but without all the other, unrelated, dialect stuff.
For 2) we need precise control, hence the detailed options.
Agreed.
BTW: BP and Delphi models coexist in a single compiler (namely Delphi itself). So while meaning of -mac-objects looks reasonable clear to me the other look more fuzzy.
True, I hadn't considered this.
As you proposed, -fobjects-are-references and -fobjects-require-override would only apply to "object". Couldn't we also restrict -fdelphi-method-shadowing and -fbase-object= (or whatever it will become) to "class" only? Then
We could. But it means that BP (and possibly Mac) model will be less capable then others. Namely -fdelphi-method-shadowing makes sense as a step during back-porting from Delphi model to BP model (BP model is closer to C++, so such port while unlikely, is imaginable)
each object model option would only imply the former two options (for models that use "object") or the latter two (for "class"), so --bp-objects and --delphi-objects could happily coexist.
Well, one possibility is to make models disjoint. However, then we will need more options, since -fmethods-always-virtual currently affects also BP objects
Another possibility is: do all what dialect is doing to objects (it is probably what you originally had in mind). Then -fbp-objects would be a subset of -fdelphi-objects (or we could just make a single -fborland-objects). Then we will have:
-fborland-objects -fmac-objects -fooe-objects -fgnu-objects
The -fgnu-objects should reset things to default values
Waldek Hebisch wrote:
Prof A Olowofoyeku (The African Chief) wrote:
With regard to Root and TObject (OOE and Delphi), I have suggested elsewhere that one could probably be a silent ancestor of the other. In fact, they could be one and the same thing (with names changing, and/or members hidden or revealed depending on Delphi or OOE mode). I am not sure whether this makes any sense ...
I don't think hiding declarations based on directives is a good idea. The problems with the built-in `Result' should be a lesson to us (not quite the same, but a similar topic).
Consider the following program:
[...]
while pointer(c) <> nil do begin writeln(c.classname); c := c.classparent;
However, if we add extra parent to TObject the first printouts would change. Note that while prp2 would crash on non-Delphi class, both prp1 and prp2 will work fine if we implement Delphi tree correctly.
Doesn't it depend on the definition of ClassParent (I suppose it's a Delphi builtin)? If we make it stop (return nil) at the Delphi root class, it would still work if there are other superclasses (kind of hidden from Delphi code then). I admit, it may not be the nicest feature, but perhaps better than the alternatives.
Cute idea. It has a drawback: ClassParent is generally usefull, also outside Delphi tree, so we would need a more general version. OTOH I would like to have multiple inheritance, so we probably want something different, which gives us all parents.
Prof A Olowofoyeku (The African Chief) wrote:
However, if we add extra parent to TObject the first printouts would change. Note that while prp2 would crash on non-Delphi class, both prp1 and prp2 will work fine if we implement Delphi tree correctly.
In which case, TObject and Root would need to be independent of each other.
This would make it difficult to write common code (including exception handling).
I am affraid that we will need multiple roots anyway.
Waldek Hebisch wrote:
<snip> Another possibility is: do all what dialect is doing to objects (it is probably what you originally had in mind). Then -fbp-objects would be a subset of -fdelphi-objects (or we could just make a single -fborland-objects). Then we will have:
-fborland-objects -fmac-objects -fooe-objects -fgnu-objects
From a user's (programmer's) point of view this seems logical, at least to me.
Regards,
Adriaan van Os
Waldek Hebisch wrote:
<snip> Another possibility is: do all what dialect is doing to objects (it is probably what you originally had in mind). Then -fbp-objects would be a subset of -fdelphi-objects (or we could just make a single -fborland-objects). Then we will have:
-fborland-objects -fmac-objects -fooe-objects -fgnu-objects
From a user's (programmer's) point of view this seems logical, at least to me.
Or maybe (since they are mutually exclusive) -fobject-model=xx, where xx is bp,delphi,mac,ooe or default. The default model links to the dialect setting.
Regards,
Adriaan van Os
Adriaan van Os wrote:
Waldek Hebisch wrote:
<snip> Another possibility is: do all what dialect is doing to objects (it is probably what you originally had in mind). Then -fbp-objects would be a subset of -fdelphi-objects (or we could just make a single -fborland-objects). Then we will have:
-fborland-objects -fmac-objects -fooe-objects -fgnu-objects
From a user's (programmer's) point of view this seems logical, at least to me.
Or maybe (since they are mutually exclusive) -fobject-model=xx, where xx is bp,delphi,mac,ooe or default. The default model links to the dialect setting.
I have already implemented the -fxxx-objects version. -fobject-model=xx requires more work...
Waldek Hebisch dixit:
Adriaan van Os wrote:
[...]
-fborland-objects -fmac-objects -fooe-objects -fgnu-objects
Or maybe (since they are mutually exclusive) -fobject-model=xx, where xx is bp,delphi,mac,ooe or default. The default model links to the dialect setting.
I have already implemented the -fxxx-objects version. -fobject-model=xx requires more work...
But it does look more logical, compared with all the other recent changes (such as -march= instead of e.g. -mpentium), and less bloated.
By the way, I just digged out my old TP 6.01 manual and started throwing some random OOP code at gpc (20050217), and to my (but not too big) surprise everything worked as I remember from long ago. What, exactly, does "gnu objects" differently than borland (turbo pascal) as long as I use the object keyword?
TIA
bye, //mirabile
On 22 Oct 2005 at 0:02, Waldek Hebisch wrote:
I would like to slightly update Mac objects and Delphi classes support. In particular I ma thinking about options names.
AFAICS there five major axes which differentiate dialects that we would like to support:
- Value versus reference model:
BP - value model (objects are values)
OOE, Delphi, Mac - pointer model (object are pointer to values)
- Static versus virtual methods:
OOE, Mac - mehods are always virtual BP, Delphi - there are static methods
- Keywords used:
BP, Mac - use "object" as a keyword (but with different semantics) OOE, Delphi - use "class" keyword
- Method redefinition:
BP - silent overriding Delphi - silent shadowing, override needs "override" OOE, Mac - explicit "override" needed
- Base object:
BP, Mac - no base object, multiple roots OOE - "Root" is the root of inheritance tree Delphi - "TObject" is the root of inheritance tree
I am generally in favour, subject to the exceptions below.
There is also question if constructors are mandatory for objects with virtual methods.
IMHO they should be - or at least a warning should be generated, except in Mac mode.
[...]
-fbase-object= -- to add default parent to object without an explicit parent
I think this should probably be avoided. If someone wants something to be his base object, he should be able to say so when declaring the object.
With regard to Root and TObject (OOE and Delphi), I have suggested elsewhere that one could probably be a silent ancestor of the other. In fact, they could be one and the same thing (with names changing, and/or members hidden or revealed depending on Delphi or OOE mode). I am not sure whether this makes any sense ...
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof. Abimbola A. Olowofoyeku (The African Chief) wrote:
On 22 Oct 2005 at 0:02, Waldek Hebisch wrote:
There is also question if constructors are mandatory for objects with virtual methods.
IMHO they should be - or at least a warning should be generated, except in Mac mode.
Constructors for Delphi and OOE classes will be inherited from base object, so there is no need to check for them. Other classes may work fine without constructors. So the check is debatable.
[...]
-fbase-object= -- to add default parent to object without an explicit parent
I think this should probably be avoided. If someone wants something to be his base object, he should be able to say so when declaring the object.
That was my first thought. But if we require explicit base we will break almost every Delphi program in existence...
With regard to Root and TObject (OOE and Delphi), I have suggested elsewhere that one could probably be a silent ancestor of the other. In fact, they could be one and the same thing (with names changing, and/or members hidden or revealed depending on Delphi or OOE mode). I am not sure whether this makes any sense ...
Consider the following program:
program tsp; type cl = class of TObject; Ob = class(TObject) end; procedure prp1(c : cl); begin while pointer(c) <> nil do begin writeln(c.classname); c := c.classparent; end; end; procedure prp2(c : cl); begin while true do begin writeln(c.classname); if c = TObject then break; c := c.classparent; end; end; begin prp1(ob); prp2(ob); end .
when run using Free Pascal it prints:
Ob TObject Ob TObject
However, if we add extra parent to TObject the first printouts would change. Note that while prp2 would crash on non-Delphi class, both prp1 and prp2 will work fine if we implement Delphi tree correctly.
The other variants also have drawbacks, that is why I would prefer to leave the choice to programmers.
On 22 Oct 2005 at 20:06, Waldek Hebisch wrote:
Prof. Abimbola A. Olowofoyeku (The African Chief) wrote:
On 22 Oct 2005 at 0:02, Waldek Hebisch wrote:
There is also question if constructors are mandatory for objects with virtual methods.
IMHO they should be - or at least a warning should be generated, except in Mac mode.
Constructors for Delphi and OOE classes will be inherited from base object, so there is no need to check for them. Other classes may work fine without constructors. So the check is debatable.
Consider this:
program afoo;
type foo = object procedure one; virtual; procedure two; virtual; end;
bar = object (foo) procedure two; virtual; procedure three; end;
procedure foo.one; begin writeln ('foo.one'); end;
procedure foo.two; begin writeln ('foo.two'); end;
procedure bar.two; begin writeln ('bar.two'); end;
procedure bar.three; begin writeln ('bar.three'); end;
var a1 : foo; b1 : bar; begin a1.one; a1.two; b1.one; b1.two; b1.three; end.
Compile and run this with BP, and you get garbage. With FPC, you get a warning at compile time, and a runtime error at runtime. With Virtual Pascal, you get a runtime error at runtime. Add and call a constructor, and the problem goes away.
So, a warning is not a bad idea (better than a crashing program).
[...]
-fbase-object= -- to add default parent to object without an explicit parent
I think this should probably be avoided. If someone wants something to be his base object, he should be able to say so when declaring the object.
That was my first thought. But if we require explicit base we will break almost every Delphi program in existence...
I think you misunderstood me. In Delphi mode, "TObject" should be the implicit ancestor of all classes, and in OOE mode, "Root" should fill this role. This should not be susceptible to being overridden by a command line switch.
With regard to Root and TObject (OOE and Delphi), I have suggested elsewhere that one could probably be a silent ancestor of the other. In fact, they could be one and the same thing (with names changing, and/or members hidden or revealed depending on Delphi or OOE mode). I am not sure whether this makes any sense ...
Consider the following program:
program tsp; type cl = class of TObject; Ob = class(TObject) end; procedure prp1(c : cl); begin while pointer(c) <> nil do begin writeln(c.classname); c := c.classparent; end; end; procedure prp2(c : cl); begin while true do begin writeln(c.classname); if c = TObject then break; c := c.classparent; end; end; begin prp1(ob); prp2(ob); end .
when run using Free Pascal it prints:
Ob TObject Ob TObject
And it does exactly the same in Delphi and Virtual Pascal.
However, if we add extra parent to TObject the first printouts would change. Note that while prp2 would crash on non-Delphi class, both prp1 and prp2 will work fine if we implement Delphi tree correctly.
In which case, TObject and Root would need to be independent of each other.
The other variants also have drawbacks, that is why I would prefer to leave the choice to programmers.
Yes, the programmers should have the choice - but the question is whether that choice should be exercised in code or at the command line. With regard to default ancestors, I think it would be problematic and error-prone to change default ancestors at the command line.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
On 22 Oct 2005 at 20:06, Waldek Hebisch wrote:
<snip>
Compile and run this with BP, and you get garbage. With FPC, you get a warning at compile time, and a runtime error at runtime. With Virtual Pascal, you get a runtime error at runtime. Add and call a constructor, and the problem goes away.
So, a warning is not a bad idea (better than a crashing program).
Maybe I was not clear: I do not want to change how BP objects behave, so the warning for BP objects will stay in place. But I see no need for such warning in other models.
I think you misunderstood me. In Delphi mode, "TObject" should be the implicit ancestor of all classes, and in OOE mode, "Root" should fill this role. This should not be susceptible to being overridden by a command line switch.
But this will be susceptible to being overridden: you choose model using command line switch and then override any other aspect of the model so only the choice of base object remains. Of course, we can limit choice to none, "Root" or "TObject". Also, having to give a long chain of options will somewhat reduce abuse.
The other variants also have drawbacks, that is why I would prefer to leave the choice to programmers.
Yes, the programmers should have the choice - but the question is whether that choice should be exercised in code or at the command line. With regard to default ancestors, I think it would be problematic and error-prone to change default ancestors at the command line.
The point here is to minimize impact on existing code -- if a programmer have to change the code then she has no choice.
I agree that playing with default ancestors may lead to weird errors. But I am affraid that sometimes it may be necessary. So we need to find good balance.
On 22 Oct 2005 at 23:29, Waldek Hebisch wrote:
Prof A Olowofoyeku (The African Chief) wrote:
On 22 Oct 2005 at 20:06, Waldek Hebisch wrote:
<snip>
Compile and run this with BP, and you get garbage. With FPC, you get a warning at compile time, and a runtime error at runtime. With Virtual Pascal, you get a runtime error at runtime. Add and call a constructor, and the problem goes away.
So, a warning is not a bad idea (better than a crashing program).
Maybe I was not clear: I do not want to change how BP objects behave, so the warning for BP objects will stay in place. But I see no need for such warning in other models.
Ok. I did misunderstand you.
I think you misunderstood me. In Delphi mode, "TObject" should be the implicit ancestor of all classes, and in OOE mode, "Root" should fill this role. This should not be susceptible to being overridden by a command line switch.
But this will be susceptible to being overridden: you choose model using command line switch and then override any other aspect of the model so only the choice of base object remains.
True. In that case, I think there should be a default mode when "Class" is used. If you have "Type foo = Class" - does that mean an OOE class or a Delphi class? I suggest that, by default, it should mean a Delphi class (e.g., if no class dialect is supplied at the command line).
Of course, we can limit choice to none, "Root" or "TObject". Also, having to give a long chain of options will somewhat reduce abuse.
Since "Class" should (IMHO) mean an OOE or a Delphi class, I think the choices should be between "TObject" (default) or "Root". If the answer is "none" or something else, then "Class" in that case does not refer to a Delphi or OOE class, because it would be incompatible with both of them. Should this be allowed? I think not. It is one thing to support classes and objects that conform to one or other standard, and it is quite another thing to support those that conform to no known standard.
The other variants also have drawbacks, that is why I would prefer to leave the choice to programmers.
Yes, the programmers should have the choice - but the question is whether that choice should be exercised in code or at the command line. With regard to default ancestors, I think it would be problematic and error-prone to change default ancestors at the command line.
The point here is to minimize impact on existing code -- if a programmer have to change the code then she has no choice.
True.
I agree that playing with default ancestors may lead to weird errors. But I am affraid that sometimes it may be necessary. So we need to find good balance.
Agreed - if limited as suggested above.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Waldek Hebisch wrote:
- Value versus reference model:
BP - value model (objects are values) OOE, Delphi, Mac - pointer model (object are pointer to values)
I have a question regarding your newly-proposed options:
-fobjects-are-references -- choose reference model even if the declaration uses "object" keyword, on for Mac Pascal, off otherwise
So do I understand you right: By default (i.e. without this option), objects will still be values, so the correct way of calling a method would be something like `someObject^.doSomething'?
More generally spoken, without any options everything (esp. the way methods are handled) will remain as it is now?
Regards,
Markus
Markus Gerwinski wrote:
Waldek Hebisch wrote:
- Value versus reference model:
BP - value model (objects are values) OOE, Delphi, Mac - pointer model (object are pointer to values)
I have a question regarding your newly-proposed options:
-fobjects-are-references -- choose reference model even if the declaration uses "object" keyword, on for Mac Pascal, off otherwise
So do I understand you right: By default (i.e. without this option), objects will still be values,
Yes.
so the correct way of calling a method would be something like `someObject^.doSomething'?
Yes, if someObject is a pointer. (In this BP model, objects do not have to be pointers, as you probably know.)
More generally spoken, without any options everything (esp. the way methods are handled) will remain as it is now?
I'd strongly suggest so, unless there's a very compelling reason to change defaults.
Of course, everything WRT `object'. Whereas `class' wasn't supported before at all, and will be then. But it makes no difference as long as you don't use `class'.
Frank
Frank Heckenbach wrote:
Markus Gerwinski wrote:
More generally spoken, without any options everything (esp. the way methods are handled) will remain as it is now?
I'd strongly suggest so, unless there's a very compelling reason to change defaults.
Great! :-) No, I'm very fine with the defaults as they are.
Of course, everything WRT `object'. Whereas `class' wasn't supported before at all, and will be then. But it makes no difference as long as you don't use `class'.
So what will be the default for `class', then? The Delphi default, where `class' denotes objects by reference? Or some other standard?
Regards,
Markus