Prof Abimbola Olowofoyeku (The African Chief) wrote:
On Wed, 2010-07-28 at 22:52 +0200, Frank Heckenbach wrote: [...]
My one concern would be about producing yet another Pascal object model that is not compatible with any of the existing ones. But I guess that, if the old BP model is still supported so that existing code would compile, that would be fine.
That's kind of what I half expected and half feared. If I'm the only one to want a new (or at least extended) object model (in particular WRT enforced constructors and automatic destructors) or other features (such as templates), there's no point implementing them.
An extended object model is fine, and Templates sound like a very good idea. My main concern was about existing code. If existing code would still compile, then that concern goes away. Enforced constructors are not a problem (that is already required in the Delphi Class model - your program will crash if you don't call a constructor to instantiate your object).
That's quite the opposite of what I mean with "enforced constructors". In my meaning (C++) if the class designer provides (one or more) constructors, they can be sure that one of them will be called for every object, whatever the user does (unless, of course, they use low-level tricks to specifically work around it). Also, of course, any internal fields (VMT tables etc.) will be automatically set at this point.
In BP (and AIUI also in Delphi), both things are not guaranteed -- the VMT is not initialized if you just "New" an object pointer in BP without calling a constructor (which will usually cause crashes later on, as soon as you call a virtual method), and none of the provided constructors (if any) is guaranteed to be called.
I don't know how automatic destructors work, but I don't have a problem with the idea (in Delphi you would have to call object.free - a method, that calls the appropriate destructor).
Same as in BP then, so if you forget it, it will not be called. What's more, the compiler cannot automatically call the destructor since there may be several of them, or they may take parameters, so objects can't really be used as temporary values (my example: f (g) where g is a function that returns an object and f is a procedure that takes an object parameter -- since the object exists on temporary and anonymously, the programmer can't call a destructor explictly, so if the compiler can't call the destructor automatically, it can't be called at all).
IMHO, any thing that makes the programmer's work less error-prone is good. But it makes sense (if at all possible without a disproportionate amount of effort) to develop/extend the object model in a way that is compatible (as far as possible) with an existing model (perhaps as a superset of one or more).
Sure.
I don't know what you have in mind WRT the object model, and I don't know whether "automatic" con-/destructors refers to implicit or explicit con-/destructors.
Both (see below).
And, would there be a common ancestor (type or template) for all objects?
In general, no. Neither the BP object model nor the C++ model do, so if only for BP compatibility, there's none. ISTR some of the other models might have one, so for them there would be one.
And what would be the difference with the BP model?
Example: { BP model } type foo = object end; {foo has no con-/destructor, which are totally unnecessary; and it has no inherent behaviour or attribute }
{ extended model } type foo = extended_object end; {does foo have any con-/destructor, and/or any inherent behaviours or attitudes?
C++: Foo has a default constructor and destructor, both empty (no parameters and doing nothing), so in this case the automatic calling of the automatic con-/destructor reduces to nothing (and is, of course, optimized away when safe).
However, if foo has any fields that are objects (not pointers or references, but actual objects), then the default con-/destructor of foo calls those of its fields. A typical example is a string field, where string is an STL type that has to initialize some of its fields to a clean state in its constructor, and to free its dynamic memory in its destructor.
An object with a string field doesn't have to do anything (i.e., the programmer doesn't have to write or declare any con-/destructor, as above), but still gets a default con-/destructor that calls those of its fields, so thanks to the automatic calling of foo's con-/destructor, its string field are handled properly. (But of course, foo *can* declare its own con-/destructors to do additional work.)
If foo inherits from bar, foo's default con-/destructor will also automatically call bar's. This is a big difference from BP where you have to call the inherited con-/destructor explicitly. IMHO that's a big source of errors with negligible benefit.
Furthermore, each class has a "copy constructor" by default that takes a reference to an object of the same class and creates a field-by-field copy (which means a binary copy for simple fields, and for fields that are objects, using their copy constructor). This constructor can be overriden or suppressed by the class designer. So this settles the question (which is somewhat unclear in Pascal) whether objects can be copied (by assignment or passing as value parameters): By default, they can. If the copy constructor is suppressed, they can't. If it's overriden, they can, but they "know about it" -- e.g., if you want each object to have a uniqe ID, you can implement a copy-constructor that creates a new ID and copies all other fields (or whatever you like).
what if I want to add my own con-/destructors?}
As I wrote, in the BP model, they should probably be output as regular C++ methods, and explicit calls (even in "New" and "Dispose") would be translated to explicit method calls. (Which would still allow the automatic C++ constructors to do their work, as far as e.g. fields are concerned, i.e. if a BP object has a field that is a string with an automatic constructor, it wold be initialized even if you don't call the constructor in "New". I'd consider this a feature. In pure BP compatible programs, this situation would simply not occur.)
In the "extended model", it should, of course, be possible to declare real (automatic) C++ con-/destructors with all their benefits (which I hope to explain above). But I haven't thought about details yet, including syntax or whether and how to mix those objects with the other models.
I know very little about C++ standards, so what follows may simply be the result of my ignorance. The question is - how confident are you that the compiler's translation from Pascal to C++ would always compile?
Of course, the new compiler will have bugs, which will have to be found and fixed, and this would be just one class of it. (Actually, less harmful than compiling and producing wrong behaviour.)
What C++ standard would it generate code for? Is there a lowest common denominator "standard" that would compile on any C++ compiler?
Ideally strictly the current C++ standard (C++98), a few years from now perhaps the next standard (C++0x). But if necessary, I'd go for compiler extensions, as long as the compiler is free software and reasonably portable (in particular g++ which is at least as portable as the current GPC, so we wouldn't lose anything).
How would GPC verify that there is a compliant C++ compiler?
By testing. All tests would run through the "New GPC" + C++ stages, and bugs found would have to be traced to see whether they're in the new GPC (most of them) or in the C++ compiler (in which case, as I wrote, they could be submitted as regular bugs to the C++ compiler maintainers -- unlike GCC backend bug reports from the current GPC which have often been ignored).
Would the GPC compiler itself compile with every standards-compliant C++ compiler? (for example, would I be able to build it on Windows with MSVC, and g++, and Borland/Turbo C++? - which would be wonderful).
Ideally yes, though I won't be making extra efforts required to support them. (As a case in point, we recently had to compile a little part of our C++ code under MSVC to interface with 3rd party C++ code under Windows. It was problematic -- it wouldn't even start to compile until we #included some obscure special header, and it needed some other little changes. (If interested, ask Peter for details.) I wouldn't like to sparkle the new compiler with such "#ifdef"s, but if it can be managed to keep them localized, this might be an option. Think of something like os-hacks.h.)
Frank