Waldek Hebisch wrote:
There are two issues here. First, Delphi objects and OOE object can not be distinguished using syntax. Some differences have to be controlled by compiler switches (`-fmethods-always-virtual'),
As I wrote sometime, I think I'd prefer a "object model" switch. Individual feature switches can also be added (or remain existent, such as `--methods-always-virtual'), but it's unreasonable to expect a programmer to know all different features, instead of setting a particular object model.
but I would like to hide as many differences as possible.
I agree, but let's say, as reasonable possible (i.e., not at any cost). Root/TObject might be a questionable case ...
I just noticed that Delphi `Create' is static, but in OOE all methods (so also constructors) are virtual. If the difference is observable then we would have to separate TObject from Root.
The second issue is single root vs. multiple roots. I have no strong opinion in favour of either (but since we already support multiple roots I see no reason not to do so in the future). In Delphi an OOE the _only_ way to create a class instance is to call a constructor. So, it is reasonable to insist that non-abstract classes have a constructor. Common base gives such warranty.
Yes -- though I don't see this as a strict requirement. If (for some reason) we make it possible to create a non-abstract class without a constructor, the programmer will notice this no later than when he tries to instantiate it ...
Another issue comes due to exceptions. In Delphi exceptions are classes. Once the exception is handled the exception object should be destroyed. So, it is natural to require that all exceptions have a "well known" destructor.
Agreed. (In fact, I know of few, if any, cases where multiple destructors are really useful at all ...)
Peter N Lewis wrote:
Ok. Mac objects don't have any concept of Root or TObject base object (various class library frameworks have implemented their own base object, but that is a code level issue).
Same for BP OOP.
I guess as long as there is no significant overhead it would not matter if there was some invisible Root/TObject/base object, although personally I'd prefer to avoid it,
The overhead is mostly space: virtual methods tables need some extra slots (tens of bytes per class). Also, full TObject functionality would require much of symbolic information at runtime -- but it is some time before we start generating it.
I am more concerned about semantics, I am affraid that the presence/ absence of Root/TObject can be detected.
Quite possible. Also we should consider that Borland may change TObject in future versions. If we decide that we can, and want to, identify it with Root now, and later they change it so it's not compatible anymore, we'll have a problem.
Me too (for BP OOP). I see no problem to add an implicit ancestor if no explicit one is given in Delphi and OOE, and not do so in the other two models.
I certainly do not want to mess with BP objects. I am not sure about Mac objects. For Delphi and OOE we have no choice. My current plan for implementing Root/TObject is to have extra module, with code included in RTS and .gpi file loaded at compiler startup. To compile this "builtin" module we need ability to have classes with no ancestor. There are other valid reasons not to add common base. But then we will have to add some restictions on use of classes not derived from "common base".
We're getting into some kind of bootstrapping problems here.
Sorry for getting a bit off-topic, but basically, I'd also like to do some other things via automatically loaded (RTS) .gpi files in the long run. Many of the predefined routines, which are not completely inlined, could be handled this way. The compiler would handle any nonstandard syntax and semantics and then call the RTS routines normally. E.g., given `WriteLn (foo : 42)', the compiler would check the type of foo, and then call, say:
_p_Write_Integer (Output, foo, 42); _p_WriteLn (Output);
where _p_Write_Integer and _p_WriteLn would then be standard Pascal routines declared in the RTS. Well, actually, it's almost so already, except that the binding is now done via linker names rather than GPI declarations, so apart from removing one possible source of interface mismatch and therefore ease maintenance, the change wouldn't gain much in practical terms immediately. That's why it's not high priority to me. (Until we had qualified identifiers, it wasn't really possible to do so, now I think it's possible at least ...)
There are bootstrapping problems there, too, in particular if the RTS is split into several modules, as it is now (and anything else would seem unreasonable). E.g., if one RTS module did a `WriteLn', but the module containing `_p_WriteLn' wasn't imported yet, it would fail with a missing declaration. (Of course, we're a bit outside of standard Pascal semantics here ... ;-) But these kinds of problems can probably be solved using cyclic module dependencies (sigh), and reordering the RTS to reduce the amount of affected code. (I expect there will be a core of interdependent low-level stuff, including basic I/O, well at least output, as well as error handling, and a few string operations, and then a larger part of code that builds upon it in a more acyclic way.)
But another, more elementary thing that will come up then is that while compiling the RTS, the compiler must be told not to automatically import the RTS (even if it exists from a previous build, of course). So I think we need a special option here, and perhaps this options could also applied to the special needs WRT the base object type. Something like: This "bootstrap" option disables the automatic base class for Delphi/OOE classes. And perhaps also marks such a class to become the default base class for regular compilations later. (This way, the names TObject and Root would not need to be "magical".) Depending on the question discussed above, we will need one or two such "slots" for the two relevant models. Since this option should be used only in the RTS, we could make sure there that no strange things are done with classes that have no base class. (Of course, those who'd write their own RTS would need to check this for themselves.)
These are just some thoughts. I probably haven't considered all issues yet, and I'm not completely convinced that coupling these two things (no auto import, no auto base class) is good, but at first sight, there seems to be some correlation ...
Frank