uint overflow behaviour
Please confirm that if the addition of two uint variables produces a result larger than can be held in a uint: 1. This is a D-legal operation (however inadvisable!), with the D-defined result of wraparound; 2. Emphasing 1. above: the result is not undefined, or an error (by the rules of D), or simply implementation-dependant (whether by compiler or chip). Best regards
Re: uint overflow behaviour
https://dlang.org/spec/expression.html#add_expressions "7. If both operands are of integral types and an overflow or underflow occurs in the computation, wrapping will happen. For example, uint.max + 1 == uint.min, uint.min - 1 == uint.max, int.max + 1 == int.min, and int.min - 1 == int.max."
Re: uint overflow behaviour
On Wednesday, 15 September 2021 at 10:08:13 UTC, DLearner wrote: Please confirm that if the addition of two uint variables produces a result larger than can be held in a uint: 1. This is a D-legal operation (however inadvisable!), with the D-defined result of wraparound; Definition under point 7 here : https://dlang.org/spec/expression.html#add_expressions And I wouldn’t say inadvisable. It’s defined and if you have a good reason to allow that, then you can do that. 2. Emphasing 1. above: the result is not undefined, or an error (by the rules of D), or simply implementation-dependant (whether by compiler or chip). Yes -Steve
Was this supposed to be allowed?
```D float[2] somevalue = somefloat3value[] + cast(Unqual!float[2]) [somesharedfloatarray1[i],somesharedfloatarray2[ii]]; ``` Older LDC/DMD releases never complained but now that i upgraded DMD, DMD-compiled builds suffer from runtime assert error `core.internal.array.operations.arrayOp!(float[], float[], float[], "+", "=").arrayOp at .\src\druntime\import\core\internal\array\operations.d(45) : Mismatched array lengths for vector operation ` Explicitly specifying `somefloat3value[0..2]` now works, and it seems that this assert check is an addition to a recent DMD version's `druntime`, does it means that this was a recent change in the language+runtime or just a retroactive enforcement of language rules that didn't use to be enforced? Big thanks.
Re: uint overflow behaviour
Thanks for the responses.
Re: Was this supposed to be allowed?
On Wednesday, 15 September 2021 at 13:52:40 UTC, z wrote: ```D float[2] somevalue = somefloat3value[] + cast(Unqual!float[2]) [somesharedfloatarray1[i],somesharedfloatarray2[ii]]; ``` Older LDC/DMD releases never complained but now that i upgraded DMD, DMD-compiled builds suffer from runtime assert error `core.internal.array.operations.arrayOp!(float[], float[], float[], "+", "=").arrayOp at .\src\druntime\import\core\internal\array\operations.d(45) : Mismatched array lengths for vector operation ` Explicitly specifying `somefloat3value[0..2]` now works, and it seems that this assert check is an addition to a recent DMD version's `druntime`, does it means that this was a recent change in the language+runtime or just a retroactive enforcement of language rules that didn't use to be enforced? Big thanks. The history is roughly as follows: * between dmd 2.065 and 2.076 (including), this used to fail at runtime with message "Array lengths don't match for vector operation: 2 != 3" * dmd 2.077 included [druntime PR 1891][1] which was a ground-up re-implementation of the way array operations are implemented and in general a very welcome improvement. Unfortunately that PR didn't include checks to ensure that all arrays have equal length (or perhaps it had insufficient checks, I didn't dig into the details). * 2020-08-04 The issue was reported: https://issues.dlang.org/show_bug.cgi?id=21110 * 2021-08-09 A PR that fixes the issue was merged: https://github.com/dlang/druntime/pull/3267 * 2021-08-09 The fix was released in 2.097.2 In summary, the validation was always supposed to be there, but between 2.077.0 and 2.097.1 it wasn't. [1]: https://github.com/dlang/druntime/pull/1891
How can we view source code that has been generated (say via "static foreach") ?
Dear All, In attempting to learn and use code generation, it would be useful to be able to view the source code that gets generated. However, with various combinations of templates, UDAs, and mixins it has not been easy. Is there some standard way this is done? Optimal would be to print out the entire generated source code to allow inspection. Best Regards, James
Return complete multi-dimensional array after appending
Howdy everyone. :) Today I came across a small problem (I mean, I could solve it by writing a function that solves my problem, but maybe there is something in std that can help me here). Let's say we have the following code: ```d void main() { int[][] a = [[],[]]; (a[0] ~ 5).writeln; // => [5] } ``` it's quite obvious that `[5]` is printed. Because I am a fan of one-liners (we do small code challenges, and I want to show what's possible with fold) and ridiculous stuff I tried to do something like this: ```d [1,0,3,4,0,5] .fold!((a, e) => e != 0 ? a[0] ~ e : a[1] ~ e)(cast(int[][]) [[],[]]) .flatten .writeln ``` This should sort all non 0s into the `a[0]` array and all 0s into the `a[1]` array. But it won't work because the `~` does not return the whole array (which is probably better for most of the cases). So the question, is there a way to do this kind of append, but getting the whole array back as a result in std? And another question, is there a way to tell `fold` about the initial value of an empty list without having to cast a `void[]` into the list of the desired type? Thanks in advance. :) eXodiquas
Re: Return complete multi-dimensional array after appending
On Wednesday, 15 September 2021 at 20:32:12 UTC, eXodiquas wrote: ```d [1,0,3,4,0,5] .fold!((a, e) => e != 0 ? a[0] ~ e : a[1] ~ e)(cast(int[][]) [[],[]]) .flatten .writeln ``` This should sort all non 0s into the `a[0]` array and all 0s into the `a[1]` array. But it won't work because the `~` does not return the whole array (which is probably better for most of the cases). So the question, is there a way to do this kind of append, but getting the whole array back as a result in std? You need to use `~=` instead of `~` to mutate an existing array: ```d import std; void main() { [1, 0, 3, 4, 0, 5] .fold!((a, e) { e != 0 ? (a[0] ~= e) : (a[1] ~= e); return a; })(cast(int[][]) [[], []]) .joiner .writeln; } ``` Of course, a more idiomatic solution would be to use `std.algorithm.partition`: ```d import std; void main() { auto arr = [1, 0, 3, 4, 0, 5]; arr.partition!(e => e != 0); // in-place arr.writeln; } ```
Re: Return complete multi-dimensional array after appending
On Wednesday, 15 September 2021 at 21:02:29 UTC, Paul Backus wrote: On Wednesday, 15 September 2021 at 20:32:12 UTC, eXodiquas wrote: ```d [1,0,3,4,0,5] .fold!((a, e) => e != 0 ? a[0] ~ e : a[1] ~ e)(cast(int[][]) [[],[]]) .flatten .writeln ``` This should sort all non 0s into the `a[0]` array and all 0s into the `a[1]` array. But it won't work because the `~` does not return the whole array (which is probably better for most of the cases). So the question, is there a way to do this kind of append, but getting the whole array back as a result in std? You need to use `~=` instead of `~` to mutate an existing array: ```d import std; void main() { [1, 0, 3, 4, 0, 5] .fold!((a, e) { e != 0 ? (a[0] ~= e) : (a[1] ~= e); return a; })(cast(int[][]) [[], []]) .joiner .writeln; } ``` Of course, a more idiomatic solution would be to use `std.algorithm.partition`: ```d import std; void main() { auto arr = [1, 0, 3, 4, 0, 5]; arr.partition!(e => e != 0); // in-place arr.writeln; } ``` Oooh, I totally forgot you can open blocks like this in anonymous functions. Now I look a bit stupid. Thanks. :) `partition` is also very nice. D std is so huge, I should sketch out a roadmap or something. That's why I asked the question in the first place because deep inside I knew there is a function in std that solves the problem. Thanks for the answer. :)
Re: Program crash: GC destroys an object unexpectedly
On Tuesday, 14 September 2021 at 20:59:14 UTC, Ali Çehreli wrote: On 9/14/21 9:56 AM, eugene wrote: > On Tuesday, 14 September 2021 at 16:43:50 UTC, jfondren wrote: >> The misaligned pointer and the >> reference-containing struct that vanishes on the return of your >> corresponding function are both problems for this. > > where did you find 'misaligned pointer'?... I think it's the align(1) for EpollEvent. I was able to reproduce the segmentation fault and was seemingly able to fix it by making the EventSource class references alive by adding a constructor: align (1) struct EpollEvent { align(1): uint event_mask; EventSource es; this(uint event_mask, EventSource es) { this.event_mask = event_mask; this.es = es; living ~= es; // <-- Introduced this constructor for this line } /* just do not want to use that union, epoll_data_t */ } // Here is the array that keeps EventSource alive: EventSource[] living; If that really is the fix, of course the references must be taken out of that container when possible. Ali Yep. This patch is sufficient to prevent the segfault: ``` diff --git a/engine/ecap.d b/engine/ecap.d index 71cb646..d57829c 100644 --- a/engine/ecap.d +++ b/engine/ecap.d @@ -32,6 +32,7 @@ final class EventQueue { private int id; private bool done; private MessageQueue mq; +private EventSource[] sources; private this() { id = epoll_create1(0); @@ -52,6 +53,7 @@ final class EventQueue { void registerEventSource(EventSource es) { auto e = EpollEvent(0, es); +sources ~= es; int r = epoll_ctl(id, EPOLL_CTL_ADD, es.id, &e); assert(r == 0, "epoll_ctl(ADD) failed"); } @@ -63,7 +65,10 @@ final class EventQueue { } void deregisterEventSource(EventSource es) { +import std.algorithm : countUntil, remove; + auto e = EpollEvent(0, es); +sources = sources.remove(sources.countUntil(es)); int r = epoll_ctl(id, EPOLL_CTL_DEL, es.id, &e); assert(r == 0, "epoll_ctl(DEL) failed"); } ``` Going through the project and adding @safe: to the top of everything results in these errors: https://gist.github.com/jrfondren/c7f7b47be057273830d6a31372895895 some I/O, some @system functions, some weird C APIs ... and misaligned assignments to EpollEvent.es. So debugging with @safe isn't bad, but I'd still like rustc-style error codes: ``` engine/ecap.d(89): Error E415: field `EpollEvent.es` cannot assign to misaligned pointers in `@safe` code $ dmd --explain E415 Yeah see, the garbage collector only looks for pointers at pointer-aligned addresses. ```
Re: How can we view source code that has been generated (say via "static foreach") ?
On Wednesday, 15 September 2021 at 19:59:43 UTC, james.p.leblanc wrote: Dear All, In attempting to learn and use code generation, it would be useful to be able to view the source code that gets generated. However, with various combinations of templates, UDAs, and mixins it has not been easy. Is there some standard way this is done? Optimal would be to print out the entire generated source code to allow inspection. Best Regards, James Use the `mixin` compiler flag `dmd -mixin= file.d` Beware, this will also include **all** the mixin code from standard library and runtime. But it's manageable, reflecting on my experience.
Re: How can we view source code that has been generated (say via "static foreach") ?
On Thursday, 16 September 2021 at 03:26:46 UTC, Tejas wrote: On Wednesday, 15 September 2021 at 19:59:43 UTC, james.p.leblanc wrote: s Use the `mixin` compiler flag `dmd -mixin= file.d` Beware, this will also include **all** the mixin code from standard library and runtime. But it's manageable, reflecting on my experience. Tejas, Thank you for your kind response. Wow, at first the large output file from a small test program was a bit surprising .., but actually it is manageable to dig through to find the interesting bits. So, this is quite useful! Thanks again, now I am off to do some digging... Best Regards, James