D - Language design... and implementation
- Juan Carlos Arevalo Baeza (66/70) Jan 18 2002 I guess I should start by apologizing to Walter for starting in this
- Pavel Minayev (40/60) Jan 18 2002 able
- Juan Carlos Arevalo Baeza (22/57) Jan 18 2002 "and you can be sure that compiler does his best". Hmmm... No.
- Pavel Minayev (14/24) Jan 18 2002 I guess D is a wrong tool for this.
- Juan Carlos Arevalo Baeza (23/47) Jan 18 2002 compiler
- Pavel Minayev (6/12) Jan 18 2002 ...which gives an opportunity for D to make functions inline
- Juan Carlos Arevalo Baeza (23/29) Jan 18 2002 possible".
- Walter (9/11) Jan 19 2002 Yes! One thing in C++ that caused me incessant bugs was a class with
I guess I should start by apologizing to Walter for starting in this forum in "harsh critic mode". I guess he probably gets that a lot. Probably a "fair" punishment for going ahead and do what most of us would like to do but don't, namely, designing (and implementing, for Chrissakes!) his own language and compiler. So from here, I'd like to commend his work. It's awesome to say the least. Nevetheless, there's always opinions and opinions, so I'll keep pusing for mine. If you want me to stop, Walter, then tell me. Ok... So... From the online documentation...Functions: "There is no inline keyword. The compiler makes the decisionwhether to inline a function or not" Hmmm... My inclination is exactly the opposite. What I'd want is a "macro" keyword that enforces the inlining of a function. I want to be able to tell the compiler to inline it, and fail with an error if for any reason it can't.Classes, Constructors: "The vptr initialization is performed before theconstructor is ever called (by the new operator)" I suppose that you're aware that this by itself makes constructors behave very differently from the C++ standard. I actually like it this way no less than what the C++ does. It brings me back to my times with Turbo Pascal :) Still, it should be a BIG emphatical point in the "Programming in D for C++ Programmers" section.Asserts:Asserts are a very powerful thing. I believe that the decission of making them a primitive is a very good one. Still, it would be even better to formalize compile-time asserts. Those are asserts where the asserted expression is constant. It would be a good thing to force compilers to evaluate such asserts at compile-timeContracts: "If a function in a derived class overrides a function in itssuper class, then only one of the in contracts of the base functions must be satisified" I'm not sure this is advisable. The "in" contract of a derived method should be forced to be implied by the contract for the parent method. For example: --- class A { int[10] nums; int Convert(int k) in { assert(k >= 0 && k < 10); } body { return nums[k]; } } class B: A { int Convert(int k) in { assert(k >= 0 && k < 12); } body { printf("Converting %d\n", k); return super.Convert(k); } } --- This allows you to do: --- B b = new b; b.Convert(11); --- Which would blow. The derived class has broken the contract of its parent. I agree that it shouldn't happen, but then the compiler should help with enforcing it. Instead, a somewhat acceptable alternative would be to use only the derived's contract when calling, and have the parent's contract be used only if/when the parent implementation is called. Salutaciones, JCAB
Jan 18 2002
"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message news:a2acct$bi$1 digitaldaemon.com...ableFunctions: "There is no inline keyword. The compiler makes the decisionwhether to inline a function or not" Hmmm... My inclination is exactly the opposite. What I'd want is a "macro" keyword that enforces the inlining of a function. I want to beto tell the compiler to inline it, and fail with an error if for anyreasonit can't.Why exactly do you need it? From your POV there is no difference other than perfomance, and you can be sure that compiler does his best to optimize it... inline functions aren't C macro, anyhow...behaveClasses, Constructors: "The vptr initialization is performed before theconstructor is ever called (by the new operator)" I suppose that you're aware that this by itself makes constructorsvery differently from the C++ standard. I actually like it this way nolessthan what the C++ does. It brings me back to my times with Turbo Pascal :) Still, it should be a BIG emphatical point in the "Programming in D forC++Programmers" section.What is great in it is that constructor in base classes can call virtual methods of child classes. This was impossible to do in C++. Also, constructors can call each other this way - so no need to make a separate initialization function, a common thing in C++.Asserts are a very powerful thing. I believe that the decission ofmakingthem a primitive is a very good one. Still, it would be even better to formalize compile-time asserts. Those are asserts where the asserted expression is constant. It would be a good thing to force compilers to evaluate such asserts at compile-timeI woudln't be surprised if there's already something like that in D.I'm not sure this is advisable. The "in" contract of a derived method should be forced to be implied by the contract for the parent method. ForIn-contracts are what _function_ expects. Since function in derived class might be different of that in base class, providing its own implementation, it _can_ cover an extended range of values (remember, deriving from a class means _extending_ this class!). This can be demonstrated with this example: class A { void func(int x) in { assert(x > 0 && x < 10); } { ... } } class B: A { override void func(int x) in { assert(x > 0 && x < 20); } { ... } } A obj = new B; obj.func(5); // since B is child of A, it must be able // to do at least what A can... obj.func(15); // ...but might do even more! Programmer is responsible for calling super() with appropriate arguments. If his function doesn't, it breaks the contract with super() - but not the user who called that function!
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2afi4$2hh$1 digitaldaemon.com..."Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message news:a2acct$bi$1 digitaldaemon.com..."and you can be sure that compiler does his best". Hmmm... No. I want to do things like put in functions for accessible properties, (which D does, for example), and still be 100% assured that there's no performance penalty. Even in debug mode. I don't want to give the compiler the choice.Hmmm... My inclination is exactly the opposite. What I'd want is a "macro" keyword that enforces the inlining of a function. I want to beableto tell the compiler to inline it, and fail with an error if for anyreasonit can't.Why exactly do you need it? From your POV there is no difference other than perfomance, and you can be sure that compiler does his best to optimize it... inline functions aren't C macro, anyhow...theClasses, Constructors: "The vptr initialization is performed before:) Yes.constructor is ever called (by the new operator)"What is great in it is that constructor in base classes can call virtual methods of child classes. This was impossible to do in C++.Also, constructors can call each other this way - so no need to make a separate initialization function, a common thing in C++.Exactly. The downside is that it loses the strictness of C++ as far as the "life" of objects is concerned, which is a good thing, even if it gets in the way sometimes.:) It wouldn't see its potential until some form of parametric polymorphism (templates) made it into the language. But it'd shine then. Imagine being able to add an error message to the assert. I'd buy into the language, despite my differences of opinion with Walter, just to get that.Asserts are a very powerful thing. I believe that the decission ofmakingthem a primitive is a very good one. Still, it would be even better to formalize compile-time asserts. Those are asserts where the asserted expression is constant. It would be a good thing to force compilers to evaluate such asserts at compile-timeI woudln't be surprised if there's already something like that in D.ForI'm not sure this is advisable. The "in" contract of a derived method should be forced to be implied by the contract for the parent method.In-contracts are what _function_ expects. Since function in derived class might be different of that in base class, providing its own implementation, it _can_ cover an extended range of values (remember, deriving from a class means _extending_ this class!). This can be demonstrated with this example: [...] obj.func(5); // since B is child of A, it must be able // to do at least what A can... obj.func(15); // ...but might do even more!But it still could do less and get away with it! Until it crashes! What I'm talking is about the compiler (or the runtime, in this case) _enforcing_ that. Salutaciones, JCAB
Jan 18 2002
"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message news:a2aguf$3hf$1 digitaldaemon.com...I want to do things like put in functions for accessible properties, (which D does, for example), and still be 100% assured that there's no performance penalty. Even in debug mode. I don't want to give the compiler the choice.I guess D is a wrong tool for this. BTW why do you want "no perfomance penalty" in debug mode? It was never supposed to run fast! Just remember about DBC, invariants etc...Exactly. The downside is that it loses the strictness of C++ as far as the "life" of objects is concerned, which is a good thing, even if it gets in the way sometimes.I don't see any good way to combine this power with strictness of C++. If I have to choose, I choose the D way.But it still could do less and get away with it! Until it crashes! What I'm talking is about the compiler (or the runtime, in this case)_enforcing_that.How can this be implemented? Remember, in-blocks don't only contain simple asserts - they can have loops (see string.toStringz() for an example of such), and are in general just another sort of subroutines. You can run one then another (as it's done with out-blocks), but how do you check if it provides _at least_ (and not _at most_) the same "range" as its superclass?
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2aifk$4ja$1 digitaldaemon.com..."Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message news:a2aguf$3hf$1 digitaldaemon.com...compilerI want to do things like put in functions for accessible properties, (which D does, for example), and still be 100% assured that there's no performance penalty. Even in debug mode. I don't want to give theI develop games. I often run in debug mode because it's easier to debug (duh! ;). The problem is that I also want to use high-level abstractions that don't change the semantics of my program. Macros are perfect for that. And, AFAIKS, there's absolutely no technical reason why the debugger (MSVC's for example) couldn't single-step inlined functions (macros) on their original source. It's one of those things that make me miserable sometimes. Remember: debug doesn't necessarily have to mean "as slow as possible". Just "slow enough to be easily debuggeable" would be enough.the choice.I guess D is a wrong tool for this. BTW why do you want "no perfomance penalty" in debug mode? It was never supposed to run fast! Just remember about DBC, invariants etc...asExactly. The downside is that it loses the strictness of C++ as fargetsthe "life" of objects is concerned, which is a good thing, even if it:) That's fair enough. Personally, I'd have to play with it a while before I'll buy into that.in the way sometimes.I don't see any good way to combine this power with strictness of C++. If I have to choose, I choose the D way.WhatBut it still could do less and get away with it! Until it crashes!Yes. That baffles me. :) Still...I'm talking is about the compiler (or the runtime, in this case)_enforcing_that.How can this be implemented? Remember, in-blocks don't only contain simple asserts - they can have loops (see string.toStringz() for an example of such), and are in general just another sort of subroutines.You can run one then another (as it's done with out-blocks), but how do you check if it provides _at least_ (and not _at most_) the same "range" as its superclass?You can't, you're right. The other option is what I said before: that only the actually called method's contract is the valid one, and that calling through "super" invokes super's contract instead. That is definitely doable by the compiler, and it swould be safe. Salutaciones, JCAB
Jan 18 2002
"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message news:a2ak4n$5mq$1 digitaldaemon.com...Remember: debug doesn't necessarily have to mean "as slow as possible". Just "slow enough to be easily debuggeable" would be enough....which gives an opportunity for D to make functions inline even in debug build, if it can then handle them properly.You can't, you're right. The other option is what I said before: that only the actually called method's contract is the valid one, and that calling through "super" invokes super's contract instead. That isdefinitelydoable by the compiler, and it swould be safe.Invoking parent contract with super() - I like the idea!
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2alq1$6ik$1 digitaldaemon.com..."Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message news:a2ak4n$5mq$1 digitaldaemon.com...possible".Remember: debug doesn't necessarily have to mean "as slow asI admit it... I'm a "control freak" of sorts. :) Still... if I intend for something to have no impact on performance, I'm the one who knows it, not the compiler, so I _should_ be able to express it. I'd like the compiler to tell me if it has a problem with that. On MSVC, we have the "__forceinline" extension, but MSVC will use only if it feels like it, as it stands. Intel's compiler will respect it very well, but it's a generally poorer compiler in my experience. Also, sometimes, it's hard for the compiler to inline a chain of 10 function calls, even if the result would be a single simple assembler instruction. If they haven't been able to get it right, I doubt the D compiler will. Sincerely. It'd make me warmer at night just to know I can get a compiler error when things are not done the way I intended them. This happens a lot when making functions that just redirect the call elsewhere (to "super", or to another aggregated class, for example). This brings me to another interesting point: function redirections. Having to make a whole new function with body just have it call a similar function in an aggregated object seems like a good place to improve the user-friendliness of the language. Salutaciones, JCABJust "slow enough to be easily debuggeable" would be enough....which gives an opportunity for D to make functions inline even in debug build, if it can then handle them properly.
Jan 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a2afi4$2hh$1 digitaldaemon.com...Also, constructors can call each other this way - so no need to make a separate initialization function, a common thing in C++.Yes! One thing in C++ that caused me incessant bugs was a class with multiple constructors. I'd add a new member as a routine improvement, and forget to put the initializer for it into one of the constructors. With D, you can have the more complex constructors call a "default" constructor, which sets all the members. Alternatively, the default for a member can be set in the member declaration itself. Worst case, the member is automatically initialized by a default set by the type.
Jan 19 2002