digitalmars.D - Static foreach pull request
- Timon Gehr (12/12) May 08 2017 Code: https://github.com/dlang/dmd/pull/6760
- Timon Gehr (3/6) May 08 2017 Better link:
- Daniel N (7/19) May 09 2017 I was wondering, would it be possible to move this to a separate
- Timon Gehr (4/25) May 09 2017 Well, there was a hackaton, and I needed to do _something_. :)
- Timon Gehr (2/12) May 09 2017 Moved: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforea...
- Jack Stouffer (3/4) May 08 2017 I'm going to save you some time and tell you that Andrei and
- rikki cattermole (2/6) May 08 2017 http://forum.dlang.org/thread/oenjmm$lds$1@digitalmars.com
- Timon Gehr (3/10) May 09 2017 Also, the DIP has existed for three years, it's just not very polished:
- Andrei Alexandrescu (4/16) May 09 2017 Cool! Now that you also have a proof of concept implementation, could
- Corey (3/5) May 09 2017 First time dealing with the frontend? Heck, two days sounds fast
- Vladimir Panteleev (4/9) May 09 2017 I guess having written your own D frontend from scratch must have
- Guillaume Boucher (43/46) May 09 2017 Code:
- Timon Gehr (6/26) May 09 2017 Thanks! (It's a known issue though:
- Andrei Alexandrescu (2/9) May 09 2017 Ignorant thought: guard the static foreach with a static if? -- Andrei
- Andrei Alexandrescu (2/12) May 09 2017 (as a lowering that is)
- Timon Gehr (2/11) May 09 2017 https://github.com/dlang/dmd/pull/6760/commits/0ac9556cb3a0e1ea1de02e97e...
- Timon Gehr (8/14) May 10 2017 Actually, yours is a different case with the same outcome (f and
- Stefan Koch (12/29) May 10 2017 So here is the difference between null and []:
- Atila Neves (3/16) May 10 2017 That's not how "regular" D works though.
- Stefan Koch (6/25) May 10 2017 What do you mean ?
- Timon Gehr (4/5) May 10 2017 It doesn't. I have tried to make that point before, unsuccessfully.
- Stefan Koch (7/14) May 10 2017 cat t3.d ----
- Timon Gehr (7/21) May 10 2017 void main(){
- Stefan Koch (5/28) May 10 2017 Oh fudge.
- Steven Schveighoffer (12/38) May 11 2017 [] lowers to a d runtime call (in lifetime, the function to allocate an
Code: https://github.com/dlang/dmd/pull/6760 Some examples: https://github.com/tgehr/dmd/blob/71ab1280c88f9f0922fabf89ab3e7e1164b70e8b/src/test_staticforeach.d This is a complete proof-of-concept implementation of "static foreach". The semantics of the construct are given by merging the ones of static if and runtime foreach. This allows declarations to be generated using an imperative loop. If you are interested in static foreach making it into the language, please play with the implementation and tell me how to break it. It would also be nice to get some code reviews (the implementation is the result of two days of exhausting trial-and-error figuring out how the DMD frontend works).
May 08 2017
On 09.05.2017 05:06, Timon Gehr wrote:... Some examples: https://github.com/tgehr/dmd/blob/71ab1280c88f9f0922fabf89ab3e7e1164b70e8b/src/test_staticforeach.dBetter link: https://github.com/tgehr/dmd/blob/static-foreach/src/test_staticforeach.d
May 08 2017
On Tuesday, 9 May 2017 at 03:42:48 UTC, Timon Gehr wrote:On 09.05.2017 05:06, Timon Gehr wrote:EPIC! Thank you so much for doing this!... Some examples: https://github.com/tgehr/dmd/blob/71ab1280c88f9f0922fabf89ab3e7e1164b70e8b/src/test_staticforeach.dBetter link: https://github.com/tgehr/dmd/blob/static-foreach/src/test_staticforeach.dadds 'enum' and 'alias' on foreach loop variables to force one of the two. (Also works with existing foreach over AliasSeq.)I was wondering, would it be possible to move this to a separate pull request and get it merged before the rest? It would be useful on its own and probably would stand a chance of getting merged much faster... before every detail of static-foreach is agreed upon?
May 09 2017
On 09.05.2017 09:26, Daniel N wrote:On Tuesday, 9 May 2017 at 03:42:48 UTC, Timon Gehr wrote:Well, there was a hackaton, and I needed to do _something_. :) I thought this will have the highest impact.On 09.05.2017 05:06, Timon Gehr wrote:EPIC! Thank you so much for doing this! ...... Some examples: https://github.com/tgehr/dmd/blob/71ab1280c88f9f0922fabf89ab3e7e1164b70e8b/src/test_staticforeach.dBetter link: https://github.com/tgehr/dmd/blob/static-foreach/src/test_staticforeach.dYes, I'll do that.adds 'enum' and 'alias' on foreach loop variables to force one of the two. (Also works with existing foreach over AliasSeq.)I was wondering, would it be possible to move this to a separate pull request and get it merged before the rest? It would be useful on its own and probably would stand a chance of getting merged much faster... before every detail of static-foreach is agreed upon?
May 09 2017
On 09.05.2017 05:42, Timon Gehr wrote:On 09.05.2017 05:06, Timon Gehr wrote:Moved: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d... Some examples: https://github.com/tgehr/dmd/blob/71ab1280c88f9f0922fabf89ab3e7e1164b70e8b/src/test_staticforeach.dBetter link: https://github.com/tgehr/dmd/blob/static-foreach/src/test_staticforeach.d
May 09 2017
On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:...I'm going to save you some time and tell you that Andrei and Walter are going to require a DIP for this.
May 08 2017
On 09/05/2017 7:10 AM, Jack Stouffer wrote:On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:http://forum.dlang.org/thread/oenjmm$lds$1 digitalmars.com...I'm going to save you some time and tell you that Andrei and Walter are going to require a DIP for this.
May 08 2017
On 09.05.2017 08:17, rikki cattermole wrote:On 09/05/2017 7:10 AM, Jack Stouffer wrote:Also, the DIP has existed for three years, it's just not very polished: https://wiki.dlang.org/DIP57On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:http://forum.dlang.org/thread/oenjmm$lds$1 digitalmars.com...I'm going to save you some time and tell you that Andrei and Walter are going to require a DIP for this.
May 09 2017
On 5/9/17 3:46 PM, Timon Gehr wrote:On 09.05.2017 08:17, rikki cattermole wrote:Cool! Now that you also have a proof of concept implementation, could you please flesh that up to make it solid and submit it as a PR? Thanks! -- AndreiOn 09/05/2017 7:10 AM, Jack Stouffer wrote:Also, the DIP has existed for three years, it's just not very polished: https://wiki.dlang.org/DIP57On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:http://forum.dlang.org/thread/oenjmm$lds$1 digitalmars.com...I'm going to save you some time and tell you that Andrei and Walter are going to require a DIP for this.
May 09 2017
On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:(the implementation is the result of two days of exhausting trial-and-error figuring out how the DMD frontend works).First time dealing with the frontend? Heck, two days sounds fast to me.
May 09 2017
On Tuesday, 9 May 2017 at 09:17:06 UTC, Corey wrote:On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:I guess having written your own D frontend from scratch must have helped! https://github.com/tgehr/d-compiler(the implementation is the result of two days of exhausting trial-and-error figuring out how the DMD frontend works).First time dealing with the frontend? Heck, two days sounds fast to me.
May 09 2017
On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:If you are interested in static foreach making it into the language, please play with the implementation and tell me how to break it.Code: void main() { void f() { idonotexist(); } static foreach(j;0..0) { f(); } } Output: test_staticforeach.d(3): Error: undefined identifier 'idonotexist' Statement::blockExit(0x7f38d5cd35e0) static foreach (j; __error) { f(); } core.exception.AssertError ddmd/blockexit.d(90): Assertion failure ---------------- ??:? _d_assertp [0x72e590] ??:? _ZN9blockExit9BlockExit5visitEP9Statement [0x637bd0] ??:? _ZN7Visitor5visitEP22StaticForeachStatement [0x625b45] ??:? _ZN22StaticForeachStatement6acceptEP7Visitor [0x61ebf8] ??:? int ddmd.blockexit.blockExit(ddmd.statement.Statement, ddmd.func.FuncDeclaration, bool) [0x637b69] ??:? _ZN9blockExit9BlockExit5visitEP17CompoundStatement [0x637ef9] ??:? _ZN17CompoundStatement6acceptEP7Visitor [0x61dc61] ??:? int ddmd.blockexit.blockExit(ddmd.statement.Statement, ddmd.func.FuncDeclaration, bool) [0x637b69] ??:? _ZN15FuncDeclaration9semantic3EP5Scope [0x5bba3d] ??:? _ZN6Module9semantic3EP5Scope [0x563f31] ??:? int ddmd.mars.tryMain(ulong, const(char)**) [0x5e2b46] ??:? _Dmain [0x5e3a12] ??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFNlZv [0x7301da] ??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x730124] ??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x730196] ??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x730124] ??:? _d_run_main [0x7300a2] ??:? main [0x5e411f] ??:? __libc_start_main [0xd4999510]
May 09 2017
On 09.05.2017 23:39, Guillaume Boucher wrote:On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.) I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)If you are interested in static foreach making it into the language, please play with the implementation and tell me how to break it.Code: void main() { void f() { idonotexist(); } static foreach(j;0..0) { f(); } } Output: test_staticforeach.d(3): Error: undefined identifier 'idonotexist' Statement::blockExit(0x7f38d5cd35e0) static foreach (j; __error) { f(); } core.exception.AssertError ddmd/blockexit.d(90): Assertion failure ---------------- ...
May 09 2017
On 5/10/17 12:56 AM, Timon Gehr wrote:Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.) I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)Ignorant thought: guard the static foreach with a static if? -- Andrei
May 09 2017
On 5/10/17 1:00 AM, Andrei Alexandrescu wrote:On 5/10/17 12:56 AM, Timon Gehr wrote:(as a lowering that is)Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.) I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)Ignorant thought: guard the static foreach with a static if? -- Andrei
May 09 2017
On 09.05.2017 23:56, Timon Gehr wrote:https://github.com/dlang/dmd/pull/6760/commits/0ac9556cb3a0e1ea1de02e97e7f05e866584de84core.exception.AssertError ddmd/blockexit.d(90): Assertion failure ---------------- ...Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.) I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)
May 09 2017
On 09.05.2017 23:56, Timon Gehr wrote:Actually, yours is a different case with the same outcome (f and idonotexist do not matter at all, the issue exists even for static foreach(j;0..0){}). All static foreach loops over empty (non-AliasSeq) aggregates failed that assertion. The reason was that CTFE can return a null literal from a function that returns T[], but the constant folder cannot actually evaluate null.length for some reason.core.exception.AssertError ddmd/blockexit.d(90): Assertion failure ---------------- ...Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.)
May 10 2017
On Wednesday, 10 May 2017 at 09:42:53 UTC, Timon Gehr wrote:On 09.05.2017 23:56, Timon Gehr wrote:So here is the difference between null and []: null : () { Slice* s; s = null; return s; } [] : () { Slice* s; s = alloca(sizeof(*s)); s.base = null; s.length = 0; return s; } Therefore null.length => (cast(Slice*)null).length; which results in a segfault. and [].length => (cast(Slice*)somevalidSliceDiscriptor).length;Actually, yours is a different case with the same outcome (f and idonotexist do not matter at all, the issue exists even for static foreach(j;0..0){}). All static foreach loops over empty (non-AliasSeq) aggregates failed that assertion. The reason was that CTFE can return a null literal from a function that returns T[], but the constant folder cannot actually evaluate null.length for some reason.core.exception.AssertError ddmd/blockexit.d(90): Assertion failure ---------------- ...Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.)
May 10 2017
On Wednesday, 10 May 2017 at 11:12:06 UTC, Stefan Koch wrote:On Wednesday, 10 May 2017 at 09:42:53 UTC, Timon Gehr wrote:That's not how "regular" D works though. Atila[...]So here is the difference between null and []: null : () { Slice* s; s = null; return s; } [] : () { Slice* s; s = alloca(sizeof(*s)); s.base = null; s.length = 0; return s; } Therefore null.length => (cast(Slice*)null).length; which results in a segfault. and [].length => (cast(Slice*)somevalidSliceDiscriptor).length;
May 10 2017
On Wednesday, 10 May 2017 at 13:11:46 UTC, Atila Neves wrote:On Wednesday, 10 May 2017 at 11:12:06 UTC, Stefan Koch wrote:What do you mean ? Hmm this should be how it works .... They reason why assert([] == null) holds. is because base is implicitly alias thised. if you try assert([] is null), it should fail.null : () { Slice* s; s = null; return s; } [] : () { Slice* s; s = alloca(sizeof(*s)); s.base = null; s.length = 0; return s; } Therefore null.length => (cast(Slice*)null).length; which results in a segfault. and [].length => (cast(Slice*)somevalidSliceDiscriptor).length;That's not how "regular" D works though. Atila
May 10 2017
On 10.05.2017 15:18, Stefan Koch wrote:if you try assert([] is null), it should fail.It doesn't. I have tried to make that point before, unsuccessfully. Empty arrays may or may not be null, but the empty array literal is always null.
May 10 2017
On Wednesday, 10 May 2017 at 14:13:09 UTC, Timon Gehr wrote:On 10.05.2017 15:18, Stefan Koch wrote:cat t3.d ---- static assert([] is null); --- dmd t.d -c --- t3.d(1): Error: static assert ([] is null) is false ----if you try assert([] is null), it should fail.It doesn't. I have tried to make that point before, unsuccessfully. Empty arrays may or may not be null, but the empty array literal is always null.
May 10 2017
On 10.05.2017 16:21, Stefan Koch wrote:On Wednesday, 10 May 2017 at 14:13:09 UTC, Timon Gehr wrote:void main(){ import std.stdio; enum x = [] is null; auto y = [] is null; writeln(x," ",y); // "false true" }On 10.05.2017 15:18, Stefan Koch wrote:cat t3.d ---- static assert([] is null); --- dmd t.d -c --- t3.d(1): Error: static assert ([] is null) is false ----if you try assert([] is null), it should fail.It doesn't. I have tried to make that point before, unsuccessfully. Empty arrays may or may not be null, but the empty array literal is always null.
May 10 2017
On Wednesday, 10 May 2017 at 18:41:30 UTC, Timon Gehr wrote:On 10.05.2017 16:21, Stefan Koch wrote:Oh fudge. Another case where the ctfe-engine goes the right way; And the runtime version does not ... we should fix this one of these days.On Wednesday, 10 May 2017 at 14:13:09 UTC, Timon Gehr wrote:void main(){ import std.stdio; enum x = [] is null; auto y = [] is null; writeln(x," ",y); // "false true" }On 10.05.2017 15:18, Stefan Koch wrote:cat t3.d ---- static assert([] is null); --- dmd t.d -c --- t3.d(1): Error: static assert ([] is null) is false ----if you try assert([] is null), it should fail.It doesn't. I have tried to make that point before, unsuccessfully. Empty arrays may or may not be null, but the empty array literal is always null.
May 10 2017
On 5/10/17 3:45 PM, Stefan Koch wrote:On Wednesday, 10 May 2017 at 18:41:30 UTC, Timon Gehr wrote:[] lowers to a d runtime call (in lifetime, the function to allocate an array) with no elements. The function must return a valid array with 0 length. null is such an array. It's not an error at all, and should not be fixed or changed IMO. You almost never want to use 'is' on an array, as it compares just the pointer and length. Usually you want '=='. For instance, you would never do: [1, 2, 3] is [1, 2, 3] And expect any sane result. It might actually be true on some compiler that's clever enough! -SteveOn 10.05.2017 16:21, Stefan Koch wrote:Oh fudge. Another case where the ctfe-engine goes the right way; And the runtime version does not ... we should fix this one of these days.On Wednesday, 10 May 2017 at 14:13:09 UTC, Timon Gehr wrote:void main(){ import std.stdio; enum x = [] is null; auto y = [] is null; writeln(x," ",y); // "false true" }On 10.05.2017 15:18, Stefan Koch wrote:cat t3.d ---- static assert([] is null); --- dmd t.d -c --- t3.d(1): Error: static assert ([] is null) is false ----if you try assert([] is null), it should fail.It doesn't. I have tried to make that point before, unsuccessfully. Empty arrays may or may not be null, but the empty array literal is always null.
May 11 2017