www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Generic memory allocation in D

reply Walter Bright <newshound2 digitalmars.com> writes:
https://github.com/dlang/dmd/pull/16291

I had talked about this in the last DConf. Here's another example of how memory 
allocation can be user-controlled rather than selected by the algorithm. I've 
been turning to this more and more with DMD and the results are good.
Mar 03
next sibling parent reply Dom DiSc <dominikus scherkl.de> writes:
On Monday, 4 March 2024 at 07:35:52 UTC, Walter Bright wrote:
 https://github.com/dlang/dmd/pull/16291

 I had talked about this in the last DConf. Here's another 
 example of how memory allocation can be user-controlled rather 
 than selected by the algorithm. I've been turning to this more 
 and more with DMD and the results are good.
Nice. But why does it now return true on failure and false on success? Isn't this exacly the bad re-definition of boolean you advised us not to use?
Mar 04
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/4/2024 12:06 AM, Dom DiSc wrote:
 But why does it now return true on failure and false on success?
 Isn't this exacly the bad re-definition of boolean you advised us not to use?
It means I don't have to use ! in: if (foo()) { error(); return; }
Mar 04
next sibling parent reply Dom DiSc <dominikus scherkl.de> writes:
On Monday, 4 March 2024 at 09:53:17 UTC, Walter Bright wrote:
 On 3/4/2024 12:06 AM, Dom DiSc wrote:
 Isn't this exacly the bad re-definition of boolean you advised 
 us not to use?
It means I don't have to use ! in: if (foo()) { error(); return; }
That's a very weak argument. Normally if one calls a function, the if-part is where the result is worked with (the main path) and the else part is for error-handling. This is especially true for ReadFile(). That in this specific case only an error handling part exists is the exception, not the rule.
Mar 04
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/4/2024 3:40 AM, Dom DiSc wrote:
 That's a very weak argument.
 Normally if one calls a function, the if-part is where the result is worked
with 
 (the main path) and the else part is for error-handling. This is especially
true 
 for ReadFile().
 That in this specific case only an error handling part exists is the
exception, 
 not the rule.
Don't think I haven't struggled with this question. Consider also that the convention for system calls is 0 is success and anything else is an error.
Mar 04
parent reply Dom DiSc <dominikus scherkl.de> writes:
On Tuesday, 5 March 2024 at 03:26:22 UTC, Walter Bright wrote:
 Don't think I haven't struggled with this question.

 Consider also that the convention for system calls is 0 is 
 success and anything else is an error.
I know, and it is odd enough. But here it is boolean. "Anything else" is just one value: true. And "true" should never be the error value. Use any other type, and say 1 means "error code 1" instead of "true" and then it's ok. 0 is a neutral value, false is not. This is also one major reason to not automatically convert from int to bool or vice versa. Because then false becomes 0 which changes the meaning heavily.
Mar 05
parent Adam Wilson <flyboynw gmail.com> writes:
On Tuesday, 5 March 2024 at 09:33:35 UTC, Dom DiSc wrote:
 On Tuesday, 5 March 2024 at 03:26:22 UTC, Walter Bright wrote:
 Don't think I haven't struggled with this question.

 Consider also that the convention for system calls is 0 is 
 success and anything else is an error.
I know, and it is odd enough. But here it is boolean. "Anything else" is just one value: true. And "true" should never be the error value. Use any other type, and say 1 means "error code 1" instead of "true" and then it's ok. 0 is a neutral value, false is not. This is also one major reason to not automatically convert from int to bool or vice versa. Because then false becomes 0 which changes the meaning heavily.
I have an idea, since you all have such boundless energy for nitpicking the most arcane of trivial minutia, could some of you all direct this clear abundance of energy to JMD's Range Redesign thread here: https://forum.dlang.org/thread/mailman.1075.1709587824.3719.digitalmars-d puremagic.com Or maybe any of the Discussions here? https://github.com/LightBender/PhobosV3-Design/discussions We're gearing up to redesigns ranges as we start pulling things into Phobos V3 and we could use some of this energy over there.
Mar 05
prev sibling next sibling parent Dennis <dkorpel gmail.com> writes:
On Monday, 4 March 2024 at 09:53:17 UTC, Walter Bright wrote:
 It means I don't have to use ! in:

     if (foo())
     {
         error();
         return;
     }
It's confusing how sometimes 0 is used for success, and other times 0 is used for failure. For a boolean it makes more sense for `true` to be success, so the Windows API uses it, as you can see in the PR: ``` if (!CloseHandle(h)) return Failure; ``` This reads as "if I could not close the handle, return failure". There's often only 1 success state and many error states however. In that case you might want to return an int with multiple error codes, but there's only one 0. This code could also make sense: ``` if (auto errorCode = CloseHandle(h)) return errorCode; ``` Now the error case is 'truthy'. Unfortunately, I don't think D can help differentiate between the two cases to prevent mistakes when using APIs returning success / error states.
Mar 04
prev sibling next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 04/03/2024 10:53 PM, Walter Bright wrote:
 On 3/4/2024 12:06 AM, Dom DiSc wrote:
 But why does it now return true on failure and false on success?
 Isn't this exacly the bad re-definition of boolean you advised us not 
 to use?
It means I don't have to use ! in:     if (foo())     {         error();         return;     }
As others have suggested, the truthiness here kinda matters and very much goes against the grain of pretty much what everyone does. It is going to cause readers a problem (and yourself!) in the future.
Mar 04
parent Daniel N <no public.email> writes:
On Monday, 4 March 2024 at 14:16:17 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 On 04/03/2024 10:53 PM, Walter Bright wrote:
 On 3/4/2024 12:06 AM, Dom DiSc wrote:
 But why does it now return true on failure and false on 
 success?
 Isn't this exacly the bad re-definition of boolean you 
 advised us not to use?
It means I don't have to use ! in:     if (foo())     {         error();         return;     }
As others have suggested, the truthiness here kinda matters and very much goes against the grain of pretty much what everyone does. It is going to cause readers a problem (and yourself!) in the future.
Had you used another type, like int, then it would follow standard practise much better that 0 is okay, but for bool... sorry despite the rest of your patch being great, I don't love unintuitive bools.
Mar 04
prev sibling next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Monday, 4 March 2024 at 09:53:17 UTC, Walter Bright wrote:
 It means I don't have to use ! in:

     if (foo())
     {
         error();
         return;
     }
FWIW when I was new to the DMD codebase, I found it very confusing to read this kind of code. And it doesn't help that DMD is internally inconsistent about its use of bool. For example, you have this: // true means success if (f.isPure()) // it's pure else // it's impure ...but also this: // true means failure if (f.checkPurity(loc, sc)) // it's impure else // it's pure ...but also this: // true means success if (checkSymbolAccess(sc, sym)) // it's accessible else // it's not accessible ...but also this: // true means failure if (checkAccess(loc, sc, e, sym)) // it's not accessible else // it's accessible
Mar 04
next sibling parent Meta <jared771 gmail.com> writes:
On Monday, 4 March 2024 at 20:38:05 UTC, Paul Backus wrote:
 On Monday, 4 March 2024 at 09:53:17 UTC, Walter Bright wrote:
 It means I don't have to use ! in:

     if (foo())
     {
         error();
         return;
     }
FWIW when I was new to the DMD codebase, I found it very confusing to read this kind of code. And it doesn't help that DMD is internally inconsistent about its use of bool. For example, you have this: // true means success if (f.isPure()) // it's pure else // it's impure ...but also this: // true means failure if (f.checkPurity(loc, sc)) // it's impure else // it's pure ...but also this: // true means success if (checkSymbolAccess(sc, sym)) // it's accessible else // it's not accessible ...but also this: // true means failure if (checkAccess(loc, sc, e, sym)) // it's not accessible else // it's accessible
Lol, if I were reviewing code that did this from one of my team members at work, their PR would definitely NOT be getting approved.
Mar 04
prev sibling next sibling parent reply kdevel <kdevel vogtner.de> writes:
On Monday, 4 March 2024 at 20:38:05 UTC, Paul Backus wrote:
 FWIW when I was new to the DMD codebase, I found it very 
 confusing to read this kind of code. And it doesn't help that 
 DMD is internally inconsistent about its use of bool.

 For example, you have this:

     // true means success
     if (f.isPure())
         // it's pure
     else
         // it's impure

 ...but also this:

     // true means failure
     if (f.checkPurity(loc, sc))
"Safe 'check' for chess" [1]
         // it's impure
     else
         // it's pure

 ...but also this:

     // true means success
     if (checkSymbolAccess(sc, sym))
         // it's accessible
     else
         // it's not accessible

 ...but also this:

     // true means failure
     if (checkAccess(loc, sc, e, sym))
         // it's not accessible
     else
         // it's accessible
And yesterday I found a post where an "is" function does not return a bool [2]: https://github.com/dlang/dmd/pull/16280/files package CppOperator isCppOperator(const scope Identifier id) [1] https://jhall.io/archive/2021/09/29/save-check-for-chess/ [2] https://forum.dlang.org/post/us0248$1ttt$1 digitalmars.com
Mar 04
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/4/2024 2:57 PM, kdevel wrote:
 And yesterday I found a post where an "is" function does not return
 a bool [2]:
 
 https://github.com/dlang/dmd/pull/16280/files
 package CppOperator isCppOperator(const scope Identifier id)
Correct, but it isn't that bad. The "is", when treated as a bool, gives a result that correctly answers the question.
Mar 04
parent kdevel <kdevel vogtner.de> writes:
On Tuesday, 5 March 2024 at 03:31:28 UTC, Walter Bright wrote:
 On 3/4/2024 2:57 PM, kdevel wrote:
 And yesterday I found a post where an "is" function does not 
 return
 a bool [2]:
 
 https://github.com/dlang/dmd/pull/16280/files
 package CppOperator isCppOperator(const scope Identifier id)
Correct, but it isn't that bad. The "is", when treated as a bool, gives a result that correctly answers the question.
Sure, but on the one hand that function is nowhere used as a predicate. These are the only two invocations I found (in dmd 2.105.3): cppmangle.d: 1216 // test for special symbols 1217 CppOperator whichOp = isCppOperator(ti.name); 1218 final switch (whichOp) cppmanglewin.d: 1164 auto whichOp = isCppOperator(ti.name); 1165 final switch (whichOp) whichOp is not used in boolean context either. On the other hand after your rewrite of isCppOperator there are different values which map to false: old: enum CppOperator { Cast, Assign, Eq, Index, Call, Unary, Binary, OpAssign, Unknown } new: enum CppOperator { Unknown, Cast, Assign, Eq, Index, Call, Unary, Binary, OpAssign }
Mar 05
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/4/2024 12:38 PM, Paul Backus wrote:
 For example, you have this:
 
      // true means success
      if (f.isPure())
          // it's pure
      else
          // it's impure
 
 ...but also this:
 
      // true means failure
      if (f.checkPurity(loc, sc))
          // it's impure
      else
          // it's pure
I know there are inconsistencies in the DMD code base. It shows the effects of many people working on it over decades. However, "isPure" asks a question. "checkPurity" does not, and so it isn't implicit how the logic should go.
Mar 04
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 05/03/2024 4:29 PM, Walter Bright wrote:
 On 3/4/2024 12:38 PM, Paul Backus wrote:
 For example, you have this:

      // true means success
      if (f.isPure())
          // it's pure
      else
          // it's impure

 ...but also this:

      // true means failure
      if (f.checkPurity(loc, sc))
          // it's impure
      else
          // it's pure
I know there are inconsistencies in the DMD code base. It shows the effects of many people working on it over decades. However, "isPure" asks a question. "checkPurity" does not, and so it isn't implicit how the logic should go.
s/checkPurity/isFunctionCallableWrtPurity/ A much longer name, but now the purpose is very clear what it does. True for success, false for failure. Based upon my understanding of its body it looks like this is a valid name/behavior. https://github.com/dlang/dmd/blob/95ba36a3fdd46850666aaebf2db31dd7c5dc9012/compiler/src/dmd/expressionsem.d#L1860
Mar 04
next sibling parent reply ShadoLight <ettienne.gilbert gmail.com> writes:
On Tuesday, 5 March 2024 at 03:39:41 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 On 05/03/2024 4:29 PM, Walter Bright wrote:
 On 3/4/2024 12:38 PM, Paul Backus wrote:
 For example, you have this:
...
      // true means failure
      if (f.checkPurity(loc, sc))
          // it's impure
      else
          // it's pure
I know there are inconsistencies in the DMD code base. It shows the effects of many people working on it over decades. However, "isPure" asks a question. "checkPurity" does not, and so it isn't implicit how the logic should go.
s/checkPurity/isFunctionCallableWrtPurity/ A much longer name, but now the purpose is very clear what it does. True for success, false for failure.
Very clear but wordy... s/checkPurity/canCallAsPure/ ?
Mar 05
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 05/03/2024 11:31 PM, ShadoLight wrote:
     s/checkPurity/isFunctionCallableWrtPurity/
 
     A much longer name, but now the purpose is very clear what it does.
 
     True for success, false for failure.
 
 Very clear but wordy...
 
 s/checkPurity/canCallAsPure/ ?
Close enough that I wouldn't mention it in a PR, to any code base that I'm involved with. All that matters is it is asking a question, not stating that it is performing an action like validation.
Mar 05
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 3/4/2024 7:39 PM, Richard (Rikki) Andrew Cattermole wrote:
 However, "isPure" asks a question. "checkPurity" does not, and so it isn't 
 implicit how the logic should go.
s/checkPurity/isFunctionCallableWrtPurity/ A much longer name, but now the purpose is very clear what it does. True for success, false for failure. Based upon my understanding of its body it looks like this is a valid name/behavior. https://github.com/dlang/dmd/blob/95ba36a3fdd46850666aaebf2db31dd7c5dc9012/compiler/src/dmd/expressionsem.d#L1860
check* functions do more than just return status - they print error messages, too. and is* function should only answer the question.
Mar 05
prev sibling next sibling parent Ogi <ogion.art gmail.com> writes:
On Monday, 4 March 2024 at 09:53:17 UTC, Walter Bright wrote:
 On 3/4/2024 12:06 AM, Dom DiSc wrote:
 But why does it now return true on failure and false on 
 success?
 Isn't this exacly the bad re-definition of boolean you advised 
 us not to use?
It means I don't have to use ! in: if (foo()) { error(); return; }
We really need to come up with one, standard way of reporting failure/success.
Mar 04
prev sibling parent reply cc <cc nevernet.com> writes:
On Monday, 4 March 2024 at 09:53:17 UTC, Walter Bright wrote:
 It means I don't have to use ! in:

     if (foo())
     {
         error();
         return;
     }
Can you add a comment that says "the use of a true bool return here as an error is favored as checking `if (!foo())` results in a significant measurable performance decrease" so that when we're all dead and buried future generations will know why the backwards logic was necessary
Mar 08
parent reply Walter Bright <newshound2 digitalmars.com> writes:
It's not about performance, it's about competing notions of clarity.
Mar 08
next sibling parent reply Daniel N <no public.email> writes:
On Saturday, 9 March 2024 at 00:09:38 UTC, Walter Bright wrote:
 It's not about performance, it's about competing notions of 
 clarity.
Sounds like you want the guard statement... https://docs.swift.org/swift-book/documentation/the-swift-programming-language/statements/#Guard-Statement https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Force-Unwrapping
Mar 09
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 09/03/2024 9:19 PM, Daniel N wrote:
 On Saturday, 9 March 2024 at 00:09:38 UTC, Walter Bright wrote:
 It's not about performance, it's about competing notions of clarity.
Sounds like you want the guard statement... https://docs.swift.org/swift-book/documentation/the-swift-programming-language/statements/#Guard-Statement https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Force-Unwrapping
So basically an if statement but without the true block. I don't see why the parser couldn't support that! Its probably even a removal of an if statement ;)
Mar 09
prev sibling parent claptrap <clap trap.com> writes:
On Saturday, 9 March 2024 at 00:09:38 UTC, Walter Bright wrote:
 It's not about performance, it's about competing notions of 
 clarity.
If you see the sentence "If file read", it reads like "if the file has been read". That's the clarity you want. The fact that you felt the need for a comment "//failed" on the next line belies the fact that on some level you understand that the preceding if statement is not obvious at first sight. The simple and straight forward solution is if (File.read(name, buf) == false) return null;
Mar 09
prev sibling parent reply Hipreme <msnmancini hotmail.com> writes:
On Monday, 4 March 2024 at 07:35:52 UTC, Walter Bright wrote:
 https://github.com/dlang/dmd/pull/16291

 I had talked about this in the last DConf. Here's another 
 example of how memory allocation can be user-controlled rather 
 than selected by the algorithm. I've been turning to this more 
 and more with DMD and the results are good.
Good refactor, this also may open a big door to easier optimizations as you get better isolation. Beyond that, I think it may be first step towards having parallelizable compiler
Mar 04
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 3/4/2024 2:31 AM, Hipreme wrote:
 Good refactor, this also may open a big door to easier optimizations as you
get 
 better isolation. Beyond that, I think it may be first step towards having 
 parallelizable compiler
That observation hasn't escaped me :-) I've made many recent refactorings that eliminate global state.
Mar 04
prev sibling parent Guillaume Piolat <first.name gmail.com> writes:
On Monday, 4 March 2024 at 10:31:01 UTC, Hipreme wrote:
 Good refactor, this also may open a big door to easier 
 optimizations as you get better isolation. Beyond that, I think 
 it may be first step towards having parallelizable compiler
Yes, buffer reuse almost always beats allocation whatever the mechanism.
Mar 05