digitalmars.D.announce - Battle-plan for CTFE
- Stefan Koch (21/21) May 09 2016 Hi Guys,
- Rory McGuire via Digitalmars-d-announce (10/22) May 09 2016 phobos! (depending on the exact codePath it may or may not compile...)
- David Nadlinger (13/19) May 09 2016 I think you guys talked about it at the conference, but be sure
- Stefan Koch (10/30) May 09 2016 The current implementation stores persistent state for every ctfe
- Robert burner Schadek (1/1) May 09 2016 awesome news :-) thanks you
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/4) May 09 2016 I very much agree.
- Walter Bright (5/6) May 09 2016 The memory consumption problem, at least, can be resolved by using stack...
- Stefan Koch (10/17) May 09 2016 Thanks, your advice is most helpful and a good first stop-gap.
- Jonathan M Davis via Digitalmars-d-announce (10/16) May 09 2016 Previously, Don stated that he thought that simply making it so that CTF...
- Andrej Mitrovic via Digitalmars-d-announce (6/8) May 09 2016 I seem to remember having to implement diagnostics in DMD asking for
- Walter Bright (2/10) May 09 2016 The pow stuff should just be done in dmd without reference to the librar...
- H. S. Teoh via Digitalmars-d-announce (7/22) May 10 2016 +1. It makes little sense for a language built-in operator to require
- Stefan Koch (4/22) Jul 07 2016 I just made a PR to fix it for ctfe.
- Stefan Koch (4/7) Jul 07 2016 Clarification now it works on Literals.
- Stefan Koch (5/13) Jul 08 2016 I forgot to mention I posted a short article about the CTFE
- Rene Zwanenburg (8/12) Jul 08 2016 Thanks! Posts like these are always interesting to read. I
- Stefan Koch (4/18) Jul 08 2016 I addressed the spelling mistakes.
- Andrei Alexandrescu (3/21) May 09 2016 Thanks Stefan, that's a good start! (This is probably better for the
- Jacob Carlborg (7/25) May 09 2016 I was listening to a discussion Don and Daniel had about the current
- Rory McGuire via Digitalmars-d-announce (4/10) May 10 2016 Does anyone know whether it would be worth while keeping the LLVM JIT
- Stefan Koch (4/17) May 10 2016 Yes I do know the llvm jit, it is slow as a three legged dog.
- jmh530 (2/5) May 16 2016 What about libjit?
- Martin Nowak (8/13) May 15 2016 No need for a byte-code interpreter, it mostly just adds overhead and
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/11) May 15 2016 If you are going to have fast evaluation of loops/recursion then
- Martin Nowak (5/11) May 15 2016 Why not do something that takes about a month and is much more likely to
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/14) May 15 2016 Well, you can, but it won't bring improvements to the language
- Martin Nowak (40/43) May 15 2016 Maybe you don't know the actual problem of the current interpreter?
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/12) May 15 2016 Well, this looks really bad. But a solver would get you much
- Stefan Koch (3/6) May 15 2016 You want it ?
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (2/4) May 15 2016 I don't «want» anything.
- Daniel Murphy (8/12) May 15 2016 The biggest advantage of bytecode is not the interpreter speed, it's
- Martin Nowak (6/12) May 15 2016 Which is a bad assessment, you can stick variable indexes into
- Daniel Murphy (12/24) May 15 2016 For simple types that's true. For more complicated reference types...
- Martin Nowak (17/26) May 15 2016 So we do need a GC or RC for arrays, structs, classes (anything
- Daniel Murphy (10/36) May 15 2016 The problem is, if index refers to a single variable on the stack, then
- Martin Nowak (17/25) May 15 2016 Taking what I said further down below there would be one union Value
- Kagamin (4/8) May 16 2016 Wasn't it possible to enable GC for entire compiler? There can be
- Martin Nowak (4/7) May 16 2016 Well, I wouldn't use D's GC for that dedicated heap.
- Andrei Alexandrescu (3/10) May 16 2016 A reap would be great there! std.experimental.allocator offers that and
- Martin Nowak (7/10) May 16 2016 Yes indeed, a malloc backed Region Allocator w/ a FreeList or a
- safety0ff (3/5) May 16 2016 Ouch.
- Daniel Murphy (2/9) May 16 2016 Maybe you wouldn't, but you certainly could...
- Don Clugston (44/79) May 17 2016 Exactly. I think the whole idea of trying to avoid a glue layer
- Stefan Koch (6/8) May 17 2016 My point exactly.
- Martin Nowak (14/31) May 17 2016 Yes, this
- Daniel Murphy (12/28) May 18 2016 IMO this is a different problem, that AssignExp is stupidly complex and
- Stefan Koch (15/17) May 18 2016 Indeed.
- Daniel Murphy (13/16) May 19 2016 It's always more difficult to justify merging more complexity. But if
- Martin Nowak (10/23) May 21 2016 As a compat layer between different interpreters or as a compat layer
- Martin Nowak (28/35) May 21 2016 It's simpler to debug an AST interpreter working with a stack of
- Martin Nowak (2/6) May 21 2016 It's also similar to comparing assembly code to C.
- Stefan Koch (4/10) May 27 2016 I am just working on a change that introduces a temporary-Stack
- Daniel Murphy (2/14) May 15 2016 We really should have discussed this last week!
- Stefan Koch (9/10) May 15 2016 I agree.
- Martin Nowak (90/97) May 16 2016 I just don't buy the argument for using BC.
- Martin Nowak (7/12) May 16 2016 Of course missing the increment for copies.
- Martin Nowak (7/9) May 15 2016 I talked about it w/ Stefan, and asked him to volunteer for an
- Stefan Koch (4/18) May 15 2016 Correct. A ByteCode Interpreter will add even more implementation
- Martin Nowak (5/9) May 15 2016 This indeed would be an interesting proposal, interpretable IR that is
- deadalnix (6/20) May 17 2016 +1 . One need to walk the tree anyway to generate bytecode, which
- maik klein (14/35) May 11 2016 What is the current problem with ctfe?
- Jonathan M Davis via Digitalmars-d-announce (17/18) May 13 2016 The biggest problem is that it uses up a _lot_ of memory and is generall...
- Don Clugston (65/91) May 13 2016 Yes. This is because of lowering. Walter said in his DConf talk
- Timon Gehr (6/7) May 13 2016 Here is the one I have hacked together:
- Stefan Koch (9/19) May 13 2016 Thanks for the explanation, and for doing so much work on CTFE.
- Martin Nowak (59/67) May 15 2016 Seems like I've to repeat this once more, b/c everyone including me
- Martin Nowak (7/11) May 15 2016 There is a really old bug report for that [Issue 3749 – cannot evaluat...
- Stefan Koch (11/15) May 27 2016 Update :
- Stefan Koch (3/20) May 28 2016 Big Whoop!
- Taylor Hillegeist (2/24) May 28 2016 but smaller than 2_147_483_647 right :)
- Stefan Koch (6/7) Jun 03 2016 Okay I briefly evaluated the current IR dmd uses for backend
- Stefan Koch (3/11) Jun 07 2016 I have to admit currently I am a bit stuck.
- Stefan Koch (11/11) Jun 29 2016 First small code example compiles!
- Martin Nowak (3/14) Jun 29 2016 The speedup comes from interpreting the IR or fixing the memory
- Stefan Koch (8/27) Jun 29 2016 Both. Actually I could not imagine fixing the memory problem
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/6) Jun 30 2016 I can't wait to see the benchmarks.
- Stefan Koch (17/23) Jun 30 2016 Currently the interpreter is about 10x-15x slower then native
- Martin Nowak (6/14) Jun 30 2016 Looks good and will definitely lead to a proper CTFE interpreter.
- Timon Gehr (2/15) Jun 30 2016 Sorry, I had missed this. I see you were able to make progress.
- Stefan Koch (5/6) Jun 30 2016 It's fine.
- Stefan Koch (5/13) Jul 03 2016 Another update.
- ZombineDev (4/21) Jul 04 2016 Nice work! Any chance that you could also improve AliasSeq
- ZombineDev (3/27) Jul 04 2016 BTW, do you plan to handle stuff like exceptions, virtual calls
- Stefan Koch (8/15) Jul 04 2016 Templates do interact with CTFE.
- ketmar (2/4) Jul 05 2016 on the lower level, it's all just arrays and jumps. ;-)
- deadalnix (4/8) Jul 05 2016 Not that I opposes this, but please keep it focused. Doing a
- ZombineDev (4/12) Jul 05 2016 I was actually wondering if they're orthogonal or some of the
- ketmar (8/8) Jul 05 2016 so, we played a little game with Stefan: i wrote a simple
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (2/4) Jul 05 2016 What is «bug6498»?
- H. S. Teoh via Digitalmars-d-announce (5/10) Jul 05 2016 https://issues.dlang.org/show_bug.cgi?id=6498
- ketmar (7/7) Jul 05 2016 and just to make sure that my approach is working: bytecode
- Rory McGuire via Digitalmars-d-announce (3/9) Jul 05 2016 Are you sharing this code / how you did it with the GSOC intern?
- ketmar (11/13) Jul 05 2016 yes. we are chatting with Stefan in IRC, and the repository is
- Rory McGuire via Digitalmars-d-announce (6/19) Jul 06 2016 Nice! Sounds like fun.
- ketmar (7/9) Jul 06 2016 sure, some ideas flows; mostly very high-level. for example,
- ketmar (3/4) Jul 05 2016 i mean "my code is publicly available, but we aren't sharing any
- ketmar (15/15) Jul 06 2016 just... can't... stop...
- ketmar (3/3) Jul 07 2016 yay. ackemann(3, 7) in 70 milliseconds! and it does TCO.
- Stefan Koch (5/10) Jul 09 2016 I decided to keep a gist updated to represent the current state
- Stefan Koch (3/7) Jul 13 2016 First StringIndexing works now.
- Stefan Koch (6/16) Jul 15 2016 Support for _basic_ support for structs has just landed in my
- Stefan Koch (11/14) Jul 17 2016 Internal changes to the bytecode engine make the manipulation of
- Rory McGuire via Digitalmars-d-announce (4/19) Jul 17 2016 Nice! how are you keeping track of changes? Are you tagging / branching
- Stefan Koch (5/7) Jul 17 2016 I just push a new commit.
- Rory McGuire via Digitalmars-d-announce (11/19) Jul 17 2016 A commit does pretty much the same thing. Tags/Branches just make UIs sh...
- Stefan Koch (5/21) Jul 17 2016 If you let me have a look at your jade-impl. I can probably work
- Rory McGuire via Digitalmars-d-announce (10/32) Jul 17 2016 Thanks that would be great, however I think its a while off before it ca...
- Stefan Koch (6/10) Jul 17 2016 pegged uses templates.
- Rory McGuire via Digitalmars-d-announce (5/15) Jul 17 2016 Nice, so I'll be able to see separate improvements in my CTFE stuff vs t...
- Stefan Koch (5/8) Jul 19 2016 Yes.
- Stefan Koch (24/24) Jul 29 2016 Hi,
- Robert burner Schadek (2/3) Jul 29 2016 When is this moving into dmd master?
- Stefan Koch (7/10) Jul 29 2016 As soon as it passes the test-suite.
- Stefan Koch (7/8) Jul 29 2016 This is now solved although quite naively at the cost of
- Stefan Koch (14/14) Jul 31 2016 I am very happy to announce that calls are almost working now.
- Stefan Koch (8/8) Aug 06 2016 Time for an update.
- Rory McGuire via Digitalmars-d-announce (11/18) Aug 06 2016 engine.
- Stefan Koch (8/15) Aug 06 2016 No, not now, but very soon. I want to have _basic_ utf8 support
- Stefan Koch (2/10) Aug 07 2016 Tomorrow this is going to work.
- Johan Engelen (8/13) Aug 08 2016 Hi Stefan,
- Stefan Koch (4/18) Aug 08 2016 Hi Johan,
- Kagamin (8/8) Aug 09 2016 1. You said CTFE engine can be ctfeable itself? But it uses
- Stefan Koch (5/13) Aug 09 2016 1. unions work fine when you use them as discriminated unions.
- Stefan Koch (8/8) Aug 11 2016 I have just committed the changes necessary for (ascii) string
- Stefan Koch (13/13) Aug 13 2016 Hi,
- Rory McGuire via Digitalmars-d-announce (4/17) Aug 14 2016 Nice! thanks! Will be nice to be able to test newCTFE with our "normal"
- Stefan Koch (4/4) Aug 17 2016 Just a small update today.
- Rory McGuire via Digitalmars-d-announce (6/10) Aug 17 2016 Nice tease with the "compile time parsers to run" aside.
- Stefan Koch (3/15) Aug 17 2016 I am using ctfe-bf for a start and others of my own design.
- Stefan Koch (16/16) Aug 28 2016 Hi Guys,
- Dominikus Dittes Scherkl (3/6) Aug 29 2016 The work you are doing is just awesome!
- Rory McGuire via Digitalmars-d-announce (4/12) Aug 29 2016 +1 your work is key for our success as a community.
- Stefan Koch (11/18) Aug 29 2016 Thanks guys.
- Jacob Carlborg (4/14) Aug 29 2016 Wow, absolutely :)
- Johannes Pfau (12/31) Aug 30 2016 There are some nice use cases for this:
- Stefan Koch (4/20) Aug 30 2016 I do not see how this could affect @nogc.
- Rory McGuire via Digitalmars-d-announce (3/6) Aug 30 2016 That will be awesome!
- Johannes Pfau (13/14) Aug 30 2016 @nogc is only meaningful at runtime. So this could work:
- Johannes Pfau (5/14) Aug 30 2016 This should be
- deadalnix (4/24) Aug 30 2016 I would say maybe, but let's keep separate things separate. This
- Stefan Koch (4/7) Aug 30 2016 Yes. It would be confusing. And it is not done with the patch I
- tsbockman (3/12) Aug 30 2016 Yes, please. I've often wished I could use `__ctfe` in a `static
- Stefan Koch (4/19) Aug 31 2016 Sorry. It I overlooked a something rather important. static
- Rory McGuire via Digitalmars-d-announce (26/47) Sep 01 2016 Surely changing the current implementation slightly could still work if ...
- Stefan Koch (7/13) Sep 01 2016 It is not a bug, because there is no way to mark something as
- Rory McGuire via Digitalmars-d-announce (4/18) Sep 01 2016 Ah, right, understood.
- David Nadlinger (8/9) Sep 01 2016 For reference, I've laid out the reasons why this proposal
- Rory McGuire via Digitalmars-d-announce (24/35) Sep 01 2016 On Thu, Sep 1, 2016 at 9:09 PM, David Nadlinger via Digitalmars-d-announ...
- David Nadlinger (5/7) Sep 01 2016 You are mixing up runtime exceptions ("throw …") with compiler
- Rory McGuire via Digitalmars-d-announce (13/18) Sep 01 2016 help somewhat.
- David Nadlinger (4/7) Sep 01 2016 It already does, see above. How is this related to try/catch?
- Rory McGuire via Digitalmars-d-announce (14/23) Sep 01 2016 I was hoping that the error was coming from the CTFE engine as it ran th...
- David Nadlinger (14/18) Sep 01 2016 As a general comment, there is no such thing as a CTFE phase. It
- ag0aep6g (9/15) Sep 01 2016 There is no CTFE error in your example. It doesn't compile in the first
- Rory McGuire via Digitalmars-d-announce (21/39) Sep 01 2016 Yeah, I'm using an enum to force the evaluation during CT, and its dying
- ag0aep6g (19/38) Sep 01 2016 I had missed that detail. Still, the error seems to be independent of
- Stefan Koch (5/5) Sep 05 2016 FunctionCall support is done. (with a lot of room for improvement)
- Rory McGuire via Digitalmars-d-announce (42/47) Sep 05 2016 Great news! Any chance you post the commit link in your announcements?
- Stefan Koch (10/18) Sep 05 2016 At the moment writing a change-log would be tedious busywork
- Stefan Koch (2/2) Sep 08 2016 compiling parts of phobos does no longer crash the new engine.
- Stefan Koch (7/9) Sep 08 2016 I think I have taken care of the incorrect bytecode.
- Rory McGuire via Digitalmars-d-announce (4/14) Sep 08 2016 !! Does this mean I can start testing new ctfe and only some of my CT wi...
- Stefan Koch (4/27) Sep 08 2016 You can start yes.
- Stefan Koch (5/15) Sep 08 2016 I found more incorrect code.
- Stefan Koch (7/24) Sep 19 2016 Compiling all of phobos does not crash my engine anymore!
- Lurker (6/12) Sep 19 2016 Good news anyway! Do you have any preliminary results or goals
- Stefan Koch (12/17) Sep 19 2016 I stated my expectations earlier I think there will be a 2-6x
- =?UTF-8?B?Tm9yZGzDtnc=?= (2/3) Sep 19 2016 Great work! Keep up still!
- Stefan Koch (14/17) Sep 25 2016 I am proud to announce,
- Rory McGuire via Digitalmars-d-announce (4/23) Sep 25 2016 t.
- Stefan Koch (19/20) Sep 25 2016 I appreciate it.
- Rory McGuire via Digitalmars-d-announce (8/29) Oct 05 2016 No worries, I've been watching this space for over a decade. I really
- Uplink_Coder (7/14) Oct 15 2016 Little update here:
- Dmitry Olshansky (5/20) Oct 16 2016 That LLVM thing is surely nice to have but I highly doubt it will be
- Uplink_Coder (5/9) Oct 16 2016 LLVM is purely optional.
- Uplink_Coder (4/15) Oct 16 2016 If anyone want to take a look the lastest llvm_backend
- Uplink_Coder (4/7) Oct 17 2016 The time llvm takes to build it's IR and execute the JITed code
- =?UTF-8?B?Tm9yZGzDtnc=?= (2/5) Oct 17 2016 Great work.
- Stefam Koch (7/13) Oct 23 2016 Hey Guys,
- Stefam Koch (5/19) Oct 23 2016 However at the D Meetup in Berlin, I have gotten some positive
- Rory McGuire via Digitalmars-d-announce (5/29) Oct 23 2016 So true of computer programming. Particularly if the documentation for t...
- Stefam Koch (7/8) Oct 25 2016 I have take care of the blocker for now.
- Stefam Koch (24/32) Oct 25 2016 First perf data is in
- Wyatt (5/9) Oct 25 2016 I think 20,000% is a pretty good speedup! ;) Great stuff.
- Stefam Koch (12/22) Oct 25 2016 Yes I have already started on solidifying struct, string and
- Jacob Carlborg (4/27) Oct 25 2016 Very impressive :)
- Stefam Koch (24/25) Oct 25 2016 Thanks.
- Andrea Fontana (2/29) Oct 26 2016 Why did you cast size_t to uint in this example?
- Stefan Koch (4/41) Oct 26 2016 Currently I am limited to 32bit Arithmetic.
- Stefam Koch (21/21) Oct 26 2016 Who can guess what this code does ?
- Kagamin (2/3) Oct 26 2016 Reads past the end of b if b is shorter than a.
- Stefam Koch (3/7) Oct 26 2016 you are right.
- MakersF (9/34) Oct 26 2016 actually be
- Stefam Koch (6/44) Oct 26 2016 Ah the default paramters are never touched.
- Stefan Koch (10/10) Oct 28 2016 Another update on CTFE.
- Stefan Koch (4/14) Oct 29 2016 I just made progress on another fundamental feature,
- Stefan Koch (13/16) Oct 30 2016 The following just compiled :
- Stefan Koch (5/22) Oct 30 2016 Oh shoot!
- Dicebot (36/41) Oct 31 2016 protected-headers="v1"
- =?UTF-8?B?Tm9yZGzDtnc=?= (2/5) Oct 19 2016 Have you benchmarked CTFE-heavy projects like Pegged?
- Stefan Koch (3/9) Oct 19 2016 It is not yet able to handle pegged.
- Rory McGuire via Digitalmars-d-announce (4/16) Oct 19 2016 the newCTFE branch, sometime in October.
- Stefan Koch (6/9) Sep 01 2016 I have something that will help with that a little bit.
- David Nadlinger (9/13) Sep 01 2016 More crucially, it also allows you to print runtime values during
- Stefan Koch (4/7) Sep 01 2016 Oh yeah.
- H. S. Teoh via Digitalmars-d-announce (31/42) Sep 01 2016 [...]
- David Nadlinger (10/29) Sep 01 2016 This doesn't do what you think it does in more than one way. If
- =?UTF-8?B?Tm9yZGzDtnc=?= (3/4) Aug 29 2016 Incredible work! Keep up!
- Martin Nowak (2/5) Aug 07 2016 That's indeed very useful, also for testing purposes.
- Edwin van Leeuwen (2/3) Jul 29 2016 Is there any improvement in memory usage?
- Stefan Koch (4/7) Jul 29 2016 Yes!
Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. Unfortunately It is a pretty big mess to untangle. Code responsible for CTFE is in at least 3 files. [dinterpret.d, ctfeexpr.d, constfold.d] I was shocked to discover that the PowExpression actually depends on phobos! (depending on the exact codePath it may or may not compile...) which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org] My Plan is as follows. Add a new file for my ctfe-interpreter and update it gradually to take more and more of the cases the code in the files mentioned above was used for. Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not. Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution. I will post more details as soon as I dive deeper into the code.
May 09 2016
On 09 May 2016 19:01, "Stefan Koch via Digitalmars-d-announce" < digitalmars-d-announce puremagic.com> wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. Unfortunately It is a pretty big mess to untangle. Code responsible for CTFE is in at least 3 files. [dinterpret.d, ctfeexpr.d, constfold.d] I was shocked to discover that the PowExpression actually depends onphobos! (depending on the exact codePath it may or may not compile...)which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org]My Plan is as follows. Add a new file for my ctfe-interpreter and update it gradually to takemore and more of the cases the code in the files mentioned above was used for.Do Dataflow analysis on the code that is to be ctfe'd so we can tellbeforehand if we need to store state in the ctfe stack or not.Or baring proper data-flow analysis: RefCouting the variables on thectfe-stack could also be a solution.I will post more details as soon as I dive deeper into the code.Will be awesome. Particularly if you document the workings of ctfe, might make a great set of articles for a blog.
May 09 2016
Hi Stefan, On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:My Plan is as follows.I think you guys talked about it at the conference, but be sure to coordinate with Timon Gehr. You'll want to steal all the best ideas from the various implementations anyway. ;)Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not. Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution.I presume by "store state" you mean persisting objects beyond the bounds of a single CTFE invocation? My first inclination here would simply be to make all allocations from a new arena each time CTFE is entered (can also re-use memory from prior runs for that), do a deep-copy of the result (converting it to full AST nodes, etc.), and then drop the entire arena. But probably you have thought of (and discarded) this already. — David
May 09 2016
On Monday, 9 May 2016 at 18:19:53 UTC, David Nadlinger wrote:Hi Stefan, On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:The current implementation stores persistent state for every ctfe incovation. While caching nothing. Not even the compiled for of a function body. Because it cannot relax purity. Which is why a simple while-loop from 0 to 100_000_00 can crash dmd if executed at ctfe. Your advice is a good one. I am happy to discuss with others! There is no need to duplicate mental workload.My Plan is as follows.I think you guys talked about it at the conference, but be sure to coordinate with Timon Gehr. You'll want to steal all the best ideas from the various implementations anyway. ;)Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not. Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution.I presume by "store state" you mean persisting objects beyond the bounds of a single CTFE invocation? My first inclination here would simply be to make all allocations from a new arena each time CTFE is entered (can also re-use memory from prior runs for that), do a deep-copy of the result (converting it to full AST nodes, etc.), and then drop the entire arena. But probably you have thought of (and discarded) this already. — David
May 09 2016
On Monday, 9 May 2016 at 18:20:46 UTC, Robert burner Schadek wrote:awesome news :-) thanks youI very much agree.
May 09 2016
On 5/9/2016 9:57 AM, Stefan Koch wrote:[...]The memory consumption problem, at least, can be resolved by using stack temporaries instead of allocating new nodes. This was already done in constfold.d, but not in the rest of the interpreter. Doing that will (I predict) also double its speed right there.
May 09 2016
On Monday, 9 May 2016 at 20:24:56 UTC, Walter Bright wrote:On 5/9/2016 9:57 AM, Stefan Koch wrote:Thanks, your advice is most helpful and a good first stop-gap. Still the current state of CTFE is almost not maintainable and I would really prefer a clean-slate approach. SDC benefits extremely from the extra level of indirection, however I do understand that SDC and DMD have diffrent goals regarding compile-speed. Also I feel that good code has found it's most beautiful shape when it's simplicity makes it inevitable, at least the Ctfe-Mechanism has not reached this point yet, imo.[...]The memory consumption problem, at least, can be resolved by using stack temporaries instead of allocating new nodes. This was already done in constfold.d, but not in the rest of the interpreter. Doing that will (I predict) also double its speed right there.
May 09 2016
On Monday, May 09, 2016 13:24:56 Walter Bright via Digitalmars-d-announce wrote:On 5/9/2016 9:57 AM, Stefan Koch wrote:Previously, Don stated that he thought that simply making it so that CTFE didn't allocate a new integer every time it mutated it would be a _huge_ speed-up by itself (which presumably is what you're talking about with regards to allocating new nodes). Unfortunately, he got too busy to actually do that work and no one else stepped in to do. But if Stefan is going to step up and improve CTFE, that's fantastic. It's one of D's best features, but it's also one of its most problematic. Fixng that would be huge. - Jonathan M Davis[...]The memory consumption problem, at least, can be resolved by using stack temporaries instead of allocating new nodes. This was already done in constfold.d, but not in the rest of the interpreter. Doing that will (I predict) also double its speed right there.
May 09 2016
On 5/9/16, Stefan Koch via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:I was shocked to discover that the PowExpression actually depends on phobos!I seem to remember having to implement diagnostics in DMD asking for the user to import std.math. I'm fairly confident it had something to do with power expressions. Yah, it's a mess. :)
May 09 2016
On 5/9/2016 2:32 PM, Andrej Mitrovic via Digitalmars-d-announce wrote:On 5/9/16, Stefan Koch via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:The pow stuff should just be done in dmd without reference to the library.I was shocked to discover that the PowExpression actually depends on phobos!I seem to remember having to implement diagnostics in DMD asking for the user to import std.math. I'm fairly confident it had something to do with power expressions. Yah, it's a mess. :)
May 09 2016
On Mon, May 09, 2016 at 05:36:21PM -0700, Walter Bright via Digitalmars-d-announce wrote:On 5/9/2016 2:32 PM, Andrej Mitrovic via Digitalmars-d-announce wrote:+1. It makes little sense for a language built-in operator to require std.math, when the whole point behind the druntime/phobos split is to make it possible for implementations *not* to implement Phobos. T -- Some days you win; most days you lose.On 5/9/16, Stefan Koch via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:The pow stuff should just be done in dmd without reference to the library.I was shocked to discover that the PowExpression actually depends on phobos!I seem to remember having to implement diagnostics in DMD asking for the user to import std.math. I'm fairly confident it had something to do with power expressions. Yah, it's a mess. :)
May 10 2016
On Tuesday, 10 May 2016 at 00:36:21 UTC, Walter Bright wrote:On 5/9/2016 2:32 PM, Andrej Mitrovic via Digitalmars-d-announce wrote:I just made a PR to fix it for ctfe. It's a hack but then again ... The whole handling of PowExp is a hack.On 5/9/16, Stefan Koch via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:The pow stuff should just be done in dmd without reference to the library.I was shocked to discover that the PowExpression actually depends on phobos!I seem to remember having to implement diagnostics in DMD asking for the user to import std.math. I'm fairly confident it had something to do with power expressions. Yah, it's a mess. :)
Jul 07 2016
On Thursday, 7 July 2016 at 13:55:44 UTC, Stefan Koch wrote:I just made a PR to fix it for ctfe. It's a hack but then again ... The whole handling of PowExp is a hack.Clarification now it works on Literals. It is still not available at ctfe and the full non-hackish fix will take a while.
Jul 07 2016
On Thursday, 7 July 2016 at 17:47:28 UTC, Stefan Koch wrote:On Thursday, 7 July 2016 at 13:55:44 UTC, Stefan Koch wrote:I forgot to mention I posted a short article about the CTFE design on my blog. https://codesoldier.blogspot.com Feel free to comment or give suggestions.I just made a PR to fix it for ctfe. It's a hack but then again ... The whole handling of PowExp is a hack.Clarification now it works on Literals. It is still not available at ctfe and the full non-hackish fix will take a while.
Jul 08 2016
On Friday, 8 July 2016 at 11:32:10 UTC, Stefan Koch wrote:I forgot to mention I posted a short article about the CTFE design on my blog. https://codesoldier.blogspot.com Feel free to comment or give suggestions.Thanks! Posts like these are always interesting to read. I noticed a few mistakes: I have been working a rewrite -> I have been working on a rewrite complicated corer-case -> complicated corner-case that have to handled correctly -> that have to be handled correctly a cononical from -> a canonical from
Jul 08 2016
On Friday, 8 July 2016 at 12:17:29 UTC, Rene Zwanenburg wrote:On Friday, 8 July 2016 at 11:32:10 UTC, Stefan Koch wrote:I addressed the spelling mistakes. Thanks for pointed them out. Also more complex SwitchStatements work now.I forgot to mention I posted a short article about the CTFE design on my blog. https://codesoldier.blogspot.com Feel free to comment or give suggestions.Thanks! Posts like these are always interesting to read. I noticed a few mistakes: I have been working a rewrite -> I have been working on a rewrite complicated corer-case -> complicated corner-case that have to handled correctly -> that have to be handled correctly a cononical from -> a canonical from
Jul 08 2016
On Friday, 8 July 2016 at 23:31:38 UTC, Stefan Koch wrote: and mine is segfaulting in some bizarre ways (i failed my basic ++ and -- math, and so the stack ;-). still, it is almost working, with support for both compiled and interpreted function calls, almost full range of integer math and some string ops. druntime still compiles and passes unittests, but phobos segfaulted somewhere deep in my CTFE engine. i really need to re-check all added opcodes and codegen. writing that was surprisingly easy. and sometimes simply surprisingly: "how did you came to me with this, DMD?! eh? aha, i see now, thank you, grep." ;-) some stats: virtual machine is <30KB of code now. compiler is ~70KB, but there is alot of copypasta in there (you know, it happens when the code grows organically). if someone is interested in interop between frontend and backend, writing engine like this is a nice way to make yourself familiar, as CTFE interpreter effectively gets already semanticed AST, with most things correctly lowered and so on. so you only have to copy dummy CtfeCompiler from dinterpret.d (it only count vars there, otherwise doing nothing), and start extending it. even when we'll get new shiny engine from Stefan, i still recommend to anyone who wish to understand how compiled and processed code looks inside the frontend at least try to implement some simple bytecode compiler. with some care seeing that you are effectively replacing compiler parts, and it is still able to compile complex unittests is... yeah, go find the word. ;-)
Jul 08 2016
p.s. it is, btw, completely possible to add at least something like "ctfe tracer" (something like old basic "trace on" command), or even some kind of gdb-like debugger to ctfe engine. it won't, of course, find it's way into mainline, but may still be a fun project to do.
Jul 08 2016
On 5/9/16 7:57 PM, Stefan Koch wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. Unfortunately It is a pretty big mess to untangle. Code responsible for CTFE is in at least 3 files. [dinterpret.d, ctfeexpr.d, constfold.d] I was shocked to discover that the PowExpression actually depends on phobos! (depending on the exact codePath it may or may not compile...) which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org] My Plan is as follows. Add a new file for my ctfe-interpreter and update it gradually to take more and more of the cases the code in the files mentioned above was used for. Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not. Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution. I will post more details as soon as I dive deeper into the code.Thanks Stefan, that's a good start! (This is probably better for the general forum.) -- Andrei
May 09 2016
On 2016-05-09 18:57, Stefan Koch wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. Unfortunately It is a pretty big mess to untangle. Code responsible for CTFE is in at least 3 files. [dinterpret.d, ctfeexpr.d, constfold.d] I was shocked to discover that the PowExpression actually depends on phobos! (depending on the exact codePath it may or may not compile...) which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org] My Plan is as follows. Add a new file for my ctfe-interpreter and update it gradually to take more and more of the cases the code in the files mentioned above was used for. Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not. Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution. I will post more details as soon as I dive deeper into the code.I was listening to a discussion Don and Daniel had about the current implementation of CTFE. They talked about using a byte code interpreter. Even implementing a really crappy byte code interpreter would be a huge improvement. -- /Jacob Carlborg
May 09 2016
On Tue, May 10, 2016 at 8:45 AM, Jacob Carlborg via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:I was listening to a discussion Don and Daniel had about the current implementation of CTFE. They talked about using a byte code interpreter. Even implementing a really crappy byte code interpreter would be a huge improvement. -- /Jacob CarlborgDoes anyone know whether it would be worth while keeping the LLVM JIT in mind when writing this new CTFE engine?
May 10 2016
On Tuesday, 10 May 2016 at 07:44:54 UTC, Rory McGuire wrote:On Tue, May 10, 2016 at 8:45 AM, Jacob Carlborg via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:Yes I do know the llvm jit, it is slow as a three legged dog. But I do plan for a way of plugging it in. This is not a main priority however.I was listening to a discussion Don and Daniel had about the current implementation of CTFE. They talked about using a byte code interpreter. Even implementing a really crappy byte code interpreter would be a huge improvement. -- /Jacob CarlborgDoes anyone know whether it would be worth while keeping the LLVM JIT in mind when writing this new CTFE engine?
May 10 2016
On Tuesday, 10 May 2016 at 11:31:33 UTC, Stefan Koch wrote:Yes I do know the llvm jit, it is slow as a three legged dog. But I do plan for a way of plugging it in. This is not a main priority however.What about libjit?
May 16 2016
On 05/10/2016 08:45 AM, Jacob Carlborg wrote:I was listening to a discussion Don and Daniel had about the current implementation of CTFE. They talked about using a byte code interpreter. Even implementing a really crappy byte code interpreter would be a huge improvement.No need for a byte-code interpreter, it mostly just adds overhead and complexity over an AST interpreter. If you want to go really fast you need some sort of JIT anyhow, but a proper interpreter will be orders of mangnitude faster than the current implementation. I might refer you to http://dconf.org/2013/talks/chevalier_boisvert.pdf page 59 ff.
May 15 2016
On Sunday, 15 May 2016 at 10:29:21 UTC, Martin Nowak wrote:On 05/10/2016 08:45 AM, Jacob Carlborg wrote: overhead and complexity over an AST interpreter. If you want to go really fast you need some sort of JIT anyhow, but a proper interpreter will be orders of mangnitude faster than the current implementation.If you are going to have fast evaluation of loops/recursion then you need to use a solver. And well, doing worse than O(log N) at compile time is a very bad idea. Why not start with the most difficult case first? Then the simple cases will resolve themselves for free, most likely.
May 15 2016
On 05/15/2016 01:55 PM, Ola Fosheim Grøstad wrote:If you are going to have fast evaluation of loops/recursion then you need to use a solver. And well, doing worse than O(log N) at compile time is a very bad idea. Why not start with the most difficult case first? Then the simple cases will resolve themselves for free, most likely.Why not do something that takes about a month and is much more likely to succeed? If someone has more time and needs an even faster interpreter she can write a new one, or add optimizations or JIT to the simple interpreter.
May 15 2016
On Sunday, 15 May 2016 at 12:00:43 UTC, Martin Nowak wrote:On 05/15/2016 01:55 PM, Ola Fosheim Grøstad wrote:Well, you can, but it won't bring improvements to the language down the line. If typical CTFE can be rewritten as simple tail recursion then you probably can find existing libraries that will do it for you.If you are going to have fast evaluation of loops/recursion then you need to use a solver. And well, doing worse than O(log N) at compile time is a very bad idea. Why not start with the most difficult case first? Then the simple cases will resolve themselves for free, most likely.Why not do something that takes about a month and is much more likely to succeed?
May 15 2016
On 05/15/2016 02:13 PM, Ola Fosheim Grøstad wrote:Well, you can, but it won't bring improvements to the language down the line.Maybe you don't know the actual problem of the current interpreter? I leaks memory like hell b/c it allocates new AST nodes for almost every expression evaluation. Even an interpreter that is as slow as ruby will fly during compile time in comparision to the current one. Let me illustrate the point. --- import std.algorithm, std.array, std.random, std.range; enum count = 2 ^^ 10; enum sorted = { auto gen = Random(123); return generate!(() => uniform(byte.min, byte.max, gen)).take(count).array.sort().release; }(); pragma(msg, sorted.length); --- count = 2 ** 10 nums = Enumerator.new do |yielder| prng = Random.new(123) loop do yielder.yield prng.rand(-128 .. 127) end end.take(count).sort print nums.length --- N | CTFE | Ruby | Time | Mem | Time | Mem -------|-------|------|-------|------ 2^^10 | 0.16s | 82M | 0.11s | 9.3M 2^^11 | 0.22s | 110M | 0.12s | 9.3M 2^^12 | 0.4s | 190M | 0.12s | 9.4M 2^^13 | 0.7s | 450M | 0.12s | 9.5M 2^^14 | 1.5s | 1.4G | 0.12s | 9.7M 2^^15 | 3.7s | 4.8G | 0.13s | 10.0M 2^^16 | 5:30m | 15G | 0.13s | 10.8M D's CTFE grows O(N^2) b/c it leaks for almost every operation. We don't currently need a superfast interpreter, even the simplest possible interpreter will allow so much more that we're more likely limited by the lack of I/O before we need a faster interpreter.
May 15 2016
On Sunday, 15 May 2016 at 13:44:45 UTC, Martin Nowak wrote:2^^15 | 3.7s | 4.8G | 0.13s | 10.0M 2^^16 | 5:30m | 15G | 0.13s | 10.8M D's CTFE grows O(N^2) b/c it leaks for almost every operation. We don't currently need a superfast interpreter, even the simplest possible interpreter will allow so much more that we're more likely limited by the lack of I/O before we need a faster interpreter.Well, this looks really bad. But a solver would get you much more than an interpreter. E.g. proving that asserts always hold etc.
May 15 2016
On Sunday, 15 May 2016 at 14:56:02 UTC, Ola Fosheim Grøstad wrote:Well, this looks really bad. But a solver would get you much more than an interpreter. E.g. proving that asserts always hold etc.You want it ? Write it.
May 15 2016
On Sunday, 15 May 2016 at 15:09:17 UTC, Stefan Koch wrote:You want it ? Write it.I don't «want» anything.
May 15 2016
On 15/05/2016 8:29 PM, Martin Nowak wrote:No need for a byte-code interpreter, it mostly just adds overhead and complexity over an AST interpreter. If you want to go really fast you need some sort of JIT anyhow, but a proper interpreter will be orders of mangnitude faster than the current implementation.The biggest advantage of bytecode is not the interpreter speed, it's that by lowering you can substitute VarExps etc with actual references to memory without modifying the AST. By working with something lower level than the AST, you should end up with something much less complex and with fewer special cases. The current goal is not a full JIT, just something that manages memory in a less insane way.
May 15 2016
On 05/15/2016 01:58 PM, Daniel Murphy wrote:The biggest advantage of bytecode is not the interpreter speed, it's that by lowering you can substitute VarExps etc with actual references to memory without modifying the AST. By working with something lower level than the AST, you should end up with something much less complex and with fewer special cases.Which is a bad assessment, you can stick variable indexes into VarDeclaration (we already do that) and thereby access them in O(1). Converting control flow and references into byte code is far from trivial, we're talking about another s2ir and e2ir here. -Martin
May 15 2016
On 15/05/2016 9:57 PM, Martin Nowak wrote:On 05/15/2016 01:58 PM, Daniel Murphy wrote:For simple types that's true. For more complicated reference types... Variable indexes are not enough, you also need heap memory, but slices and pointers (and references) can refer to values either on the heap or the stack, and you can have a slice of a member static array of a class on the stack, etc. Then there are closures... Neither e2ir or s2ir are actually that complex. A lot of the mess there comes from the backend IR interface being rather difficult to work with. We can already save a big chunk of complexity by not having to translate the frontend types. E.g. implementing the logic in the interpreter to correctly unwind through destructors is unlikely to be simpler than lowering to an IR.The biggest advantage of bytecode is not the interpreter speed, it's that by lowering you can substitute VarExps etc with actual references to memory without modifying the AST. By working with something lower level than the AST, you should end up with something much less complex and with fewer special cases.Which is a bad assessment, you can stick variable indexes into VarDeclaration (we already do that) and thereby access them in O(1). Converting control flow and references into byte code is far from trivial, we're talking about another s2ir and e2ir here. -Martin
May 15 2016
On 05/15/2016 02:17 PM, Daniel Murphy wrote:For simple types that's true. For more complicated reference types... Variable indexes are not enough, you also need heap memory, but slices and pointers (and references) can refer to values either on the heap or the stack, and you can have a slice of a member static array of a class on the stack, etc. Then there are closures...So we do need a GC or RC for arrays, structs, classes (anything heapish). Values for those could be allocated by a simple bump/region allocator or a dedicated allocator that support individual freeing (via RC or GC). In any case struct Pointer { int index; /* 2B positive values for stack, 2B negative for heap*/ } wouldn't be much more complicated than a raw pointer (and a bit simpler to garbage collect).Neither e2ir or s2ir are actually that complex. A lot of the mess there comes from the backend IR interface being rather difficult to work with.Think of a simple switch statement where you even need to introduce relocations (or keep a list of fixup addresses) b/c you don't know the jump addresses in advance. In a visitor you simply test the cases and execute the first case body. Not to mention that we can reuse existing solutions from the current interpreter (e.g. for gotos see https://github.com/dlang/dmd/blob/0757504342e48e272372b7ac52cda5a333b2a2bc/src/dinterpret.d#L1014 and https://github.com/dlang/dmd/blob/0757504342e48e272372b7ac52cda5a333b2a2bc/src/dinterpret.d#L1094).
May 15 2016
On 15/05/2016 11:25 PM, Martin Nowak wrote:On 05/15/2016 02:17 PM, Daniel Murphy wrote:The problem is, if index refers to a single variable on the stack, then it's insufficient to refer to a variable inside an aggregate on the stack. Then you need to start building constructs for member of struct in array of struct pointers and it gets fairly messy... It's all solvable, I'm not sure the simplicity would survive.For simple types that's true. For more complicated reference types... Variable indexes are not enough, you also need heap memory, but slices and pointers (and references) can refer to values either on the heap or the stack, and you can have a slice of a member static array of a class on the stack, etc. Then there are closures...So we do need a GC or RC for arrays, structs, classes (anything heapish). Values for those could be allocated by a simple bump/region allocator or a dedicated allocator that support individual freeing (via RC or GC). In any case struct Pointer { int index; /* 2B positive values for stack, 2B negative for heap*/ } wouldn't be much more complicated than a raw pointer (and a bit simpler to garbage collect).This is not exactly difficult to do.Neither e2ir or s2ir are actually that complex. A lot of the mess there comes from the backend IR interface being rather difficult to work with.Think of a simple switch statement where you even need to introduce relocations (or keep a list of fixup addresses) b/c you don't know the jump addresses in advance.In a visitor you simply test the cases and execute the first case body. Not to mention that we can reuse existing solutions from the current interpreter (e.g. for gotos see https://github.com/dlang/dmd/blob/0757504342e48e272372b7ac52cda5a333b2a2bc/src/dinterpret.d#L1014 and https://github.com/dlang/dmd/blob/0757504342e48e272372b7ac52cda5a333b2a2bc/src/dinterpret.d#L1094).Flow control is really not where the complexity lies IMO. The weird ways in which different types of reference types can combine leads to either very complicated or very low level descriptions of memory.
May 15 2016
On 05/15/2016 04:00 PM, Daniel Murphy wrote:The problem is, if index refers to a single variable on the stack, then it's insufficient to refer to a variable inside an aggregate on the stack. Then you need to start building constructs for member of struct in array of struct pointers and it gets fairly messy... It's all solvable, I'm not sure the simplicity would survive.Taking what I said further down below there would be one union Value type (untagged b/c the compiler knows what it is). Then an Array could be implementd as HeapValueRef[], a hash table as HeapValueRef[ValueRef], a struct/class as HeapValueRef[] (with HeapValueRef being a pointer or int to a heap allocated Value and ValueRef being a pointer or int to either a stack value or a heap value). A D Pointer/Ref would just be a ValueRef in the interpreter and the aforementioned int (2B + for stack, 2B - for heap) encoding should still work for that. Depending on how much pointer arithmetic we support, Pointer must contain a ValueRef to the outermost aggregate and needs to store the type of that an additional byte offset. The type and offset could then be used to compute the actual pointee. While that sounds a bit complex, it's merely just https://en.wikipedia.org/wiki/Offsetof.Flow control is really not where the complexity lies IMO. The weird ways in which different types of reference types can combine leads to either very complicated or very low level descriptions of memory.Maybe you're right, but it'll be hard to figure out w/o an actual implementation. And the AST still looks like a lot less to code and execute.
May 15 2016
On Sunday, 15 May 2016 at 13:25:42 UTC, Martin Nowak wrote:So we do need a GC or RC for arrays, structs, classes (anything heapish). Values for those could be allocated by a simple bump/region allocator or a dedicated allocator that support individual freeing (via RC or GC).Wasn't it possible to enable GC for entire compiler? There can be hybrid approach: 1) first allocate from bump heap 2) when it reaches, say, 200MB, switch to GC.
May 16 2016
On Monday, 16 May 2016 at 10:01:47 UTC, Kagamin wrote:Wasn't it possible to enable GC for entire compiler? There can be hybrid approach: 1) first allocate from bump heap 2) when it reaches, say, 200MB, switch to GC.Well, I wouldn't use D's GC for that dedicated heap. Allocation of CTFE values are completely independent and call be freed once the evaluation is finished.
May 16 2016
On 5/16/16 7:20 AM, Martin Nowak wrote:On Monday, 16 May 2016 at 10:01:47 UTC, Kagamin wrote:A reap would be great there! std.experimental.allocator offers that and a variety of others. -- AndreiWasn't it possible to enable GC for entire compiler? There can be hybrid approach: 1) first allocate from bump heap 2) when it reaches, say, 200MB, switch to GC.Well, I wouldn't use D's GC for that dedicated heap. Allocation of CTFE values are completely independent and call be freed once the evaluation is finished.
May 16 2016
On 05/16/2016 01:36 PM, Andrei Alexandrescu wrote:A reap would be great there! std.experimental.allocator offers that and a variety of others. -- AndreiYes indeed, a malloc backed Region Allocator w/ a FreeList or a BitmappedBlock would be a good starting point. That might finally be a compelling enough case to start using phobos in dmd. Last time people forced me to spend several hours on reimplementing and debugging a BitArray implementation [¹]. [¹]: https://github.com/dlang/dmd/pull/5426#discussion_r52833955
May 16 2016
On Monday, 16 May 2016 at 12:13:14 UTC, Martin Nowak wrote:Last time people forced me to spend several hours on reimplementing and debugging a BitArray implementationOuch. src/tk/vec.(h|c) already contained an implementation.
May 16 2016
On 16/05/2016 9:20 PM, Martin Nowak wrote:On Monday, 16 May 2016 at 10:01:47 UTC, Kagamin wrote:Maybe you wouldn't, but you certainly could...Wasn't it possible to enable GC for entire compiler? There can be hybrid approach: 1) first allocate from bump heap 2) when it reaches, say, 200MB, switch to GC.Well, I wouldn't use D's GC for that dedicated heap. Allocation of CTFE values are completely independent and call be freed once the evaluation is finished.
May 16 2016
On Sunday, 15 May 2016 at 12:17:30 UTC, Daniel Murphy wrote:On 15/05/2016 9:57 PM, Martin Nowak wrote:Exactly. I think the whole idea of trying to avoid a glue layer is a mistake. CTFE is a backend. It really is. And it should be treated as one. A very simple one, of course. Once you do this, you'll find all sorts of commonalities with the existing glue layers. We should end up with at least 4 backends: DMD, GCD, LDC, and CTFE. Many people here are acting like this is something complicated, and making dangerous suggestions like using Phobos inside the compiler. (I think everyone who has fixed a compiler bug that was discovered in Phobos, will know what a nightmare that would be. The last thing compiler development needs is another level of complexity in the compiler). As I've tried to explain, the problems with CTFE historically were never with the CTFE engine itself. They were always with the interface between CTFE and the remainder of the compiler -- finding every case where CTFE can be called, finding all the bizarre cases (tuple variables, variables without a stack because they are local variables declared in comma expressions in global scope, local 'ref' variables, etc), finding all the cases where the syntax trees were invalid... There's no need for grandiose plans, as if there is some almost-insurmountable problem to be solved. THIS IS NOT DIFFICULT. With the interface cleaned up, it is the well-studied problem of creating an interpreter. Everyone knows how to do this, it's been done thousands of times. The complete test suite is there for you. Someone just needs to do it. I think I took the approach of using syntax trees about as far as it can go. It's possible, but it's really vile. Look at the code for doing assignments. Bleagh. The only thing in its favour is that originally it was the only implementation that was possible at all. Even the first, minimal step towards creating a ctfe backend -- introducing a syntax-tree-validation step -- simplified parts of the code immensely. You might imagine that it's easier to work with syntax trees than to start from scratch but I'm certain that's not true. I'm pretty sure that the simplest approach is to use the simplest possible machine-independent bytecode that you can come up with. I had got to the point of starting that, but I just couldn't face doing it in C++. TL;DR: CTFE is actually a backend, so don't be afraid of creating a glue layer for it.On 05/15/2016 01:58 PM, Daniel Murphy wrote:For simple types that's true. For more complicated reference types... Variable indexes are not enough, you also need heap memory, but slices and pointers (and references) can refer to values either on the heap or the stack, and you can have a slice of a member static array of a class on the stack, etc. Then there are closures... Neither e2ir or s2ir are actually that complex. A lot of the mess there comes from the backend IR interface being rather difficult to work with. We can already save a big chunk of complexity by not having to translate the frontend types. E.g. implementing the logic in the interpreter to correctly unwind through destructors is unlikely to be simpler than lowering to an IR.The biggest advantage of bytecode is not the interpreter speed, it's that by lowering you can substitute VarExps etc with actual references to memory without modifying the AST. By working with something lower level than the AST, you should end up with something much less complex and with fewer special cases.Which is a bad assessment, you can stick variable indexes into VarDeclaration (we already do that) and thereby access them in O(1). Converting control flow and references into byte code is far from trivial, we're talking about another s2ir and e2ir here. -Martin
May 17 2016
On Tuesday, 17 May 2016 at 10:42:30 UTC, Don Clugston wrote:TL;DR: CTFE is actually a backend, so don't be afraid of creating a glue layer for it.My point exactly. The AST is not something I want to handle while inside the interpreter. It introduces too much complexity. There needs to be some kind of further lowering.
May 17 2016
On 05/17/2016 12:42 PM, Don Clugston wrote:There's no need for grandiose plans, as if there is some almost-insurmountable problem to be solved. THIS IS NOT DIFFICULT. With the interface cleaned up, it is the well-studied problem of creating an interpreter. Everyone knows how to do this, it's been done thousands of times. The complete test suite is there for you. Someone just needs to do it.Yes, exactly my words.I think I took the approach of using syntax trees about as far as it can go. It's possible, but it's really vile. Look at the code for doing assignments. Bleagh. The only thing in its favour is that originally it was the only implementation that was possible at all. Even the first, minimal step towards creating a ctfe backend -- introducing a syntax-tree-validation step -- simplified parts of the code immensely.Yes, this https://github.com/dlang/dmd/blob/7d00095301c4780b41addcfeb50f4743a9a6c5d4/src/dinterpret.d#L3418 is really ugly and complex, but you won't get rid of this inherent complexity. The e2ir code for AssingExp looks almost the same https://github.com/dlang/dmd/blob/7d00095301c4780b41addcfeb50f4743a9a6c5d4/src/e2ir.c#L2466.You might imagine that it's easier to work with syntax trees than to start from scratch but I'm certain that's not true. I'm pretty sure that the simplest approach is to use the simplest possible machine-independent bytecode that you can come up with. I had got to the point of starting that, but I just couldn't face doing it in C++.All I'm saying is that interpreting the AST to generate bytecode is going to be as complex as interpreting the AST directly, but then you still a bytecode interpreter and later might still want a JIT. Using dedicated value types during interpretation instead of recycling the AST for that will also make the transitions clearer and get rid of some of the lifetime complexities in the current code. -Martin
May 17 2016
On 18/05/2016 9:01 AM, Martin Nowak wrote:Yes, this https://github.com/dlang/dmd/blob/7d00095301c4780b41addcfeb50f4743a9a6c5d4/src/dinterpret.d#L3418 is really ugly and complex, but you won't get rid of this inherent complexity. The e2ir code for AssingExp looks almost the same https://github.com/dlang/dmd/blob/7d00095301c4780b41addcfeb50f4743a9a6c5d4/src/e2ir.c#L2466.IMO this is a different problem, that AssignExp is stupidly complex and needs to be split up.The bytecode generator and bytecode interpreter can be debugged (and tested!) independently. So the total amount of code will increase but the components themselves will be better isolated and easier to work with. I don't think a possible future need for a JIT is a good reason to avoid an bytecode interpreter. A large part of the work of adding a new (JIT) backend is pinning down the semantics, and adding a bytecode interpreter will certainly help to do that.You might imagine that it's easier to work with syntax trees than to start from scratch but I'm certain that's not true. I'm pretty sure that the simplest approach is to use the simplest possible machine-independent bytecode that you can come up with. I had got to the point of starting that, but I just couldn't face doing it in C++.All I'm saying is that interpreting the AST to generate bytecode is going to be as complex as interpreting the AST directly, but then you still a bytecode interpreter and later might still want a JIT.Using dedicated value types during interpretation instead of recycling the AST for that will also make the transitions clearer and get rid of some of the lifetime complexities in the current code.Meh, sure. But this feels just as difficult as switching to a simple bytecode, without all the benefits.
May 18 2016
On Wednesday, 18 May 2016 at 14:59:09 UTC, Daniel Murphy wrote:Meh, sure. But this feels just as difficult as switching to a simple bytecode, without all the benefits.Indeed. I am currently designing an IR to feed into the CTFE Evaluator. I am aware that this could potentially make it harder to get things merged since DMD already has the glue-layer. However I do think that the benefits outweigh the drawbacks by far. Especially when one looks at the possibility to eventually plug llvm or the gcc-jit in. My CTFE needs are rather heavy weight. So I will go for a solution that can support this. I believe the pressure on CTFE performance will increase as soon as the preformance increases. Since this will enable much more things. I.E. running a query optimizer at compile-time.
May 18 2016
On 19/05/2016 3:50 AM, Stefan Koch wrote:I am currently designing an IR to feed into the CTFE Evaluator. I am aware that this could potentially make it harder to get things merged since DMD already has the glue-layer.It's always more difficult to justify merging more complexity. But if you can present a working and superior solution the specific implementation is less important. It is still important that it matches the existing style of the compiler, especially with respect to adding dependencies. Also be aware that even with agreement on the eventual goal, it is still very slow to get big changes approved. eg ddmd took more than twice as long as it should have. This is why I suggested looking for incremental improvements, so you can overlap getting earlier things merged and developing later parts. I would be on the lookout for things that can be justified on their own (untangling AssignExp :) ) and try to push those through first.
May 19 2016
On 05/18/2016 07:50 PM, Stefan Koch wrote:Indeed. I am currently designing an IR to feed into the CTFE Evaluator. I am aware that this could potentially make it harder to get things merged since DMD already has the glue-layer.As a compat layer between different interpreters or as a compat layer between all backends? Adding another translation might not be acceptable, at least for real backends.However I do think that the benefits outweigh the drawbacks by far. Especially when one looks at the possibility to eventually plug llvm or the gcc-jit in.Indeed, but it heavily increases the chance that your project lands on the unfinished D project pile.My CTFE needs are rather heavy weight. So I will go for a solution that can support this. I believe the pressure on CTFE performance will increase as soon as the preformance increases. Since this will enable much more things. I.E. running a query optimizer at compile-time.That might be true, but scripting languages are still fast enough to be used everywhere. You won't need native CTFE performance for it to be an enabling technique. -Martin
May 21 2016
On 05/18/2016 04:59 PM, Daniel Murphy wrote:The bytecode generator and bytecode interpreter can be debugged (and tested!) independently. So the total amount of code will increase but the components themselves will be better isolated and easier to work with.It's simpler to debug an AST interpreter working with a stack of high-level values, than it is to debug a bytecode interpreter where lots of context has been converted to jumping goto code. Just to illustrate my point, here are an AST and a BC interpreter for very simplistic functional language I wrote recently. The later one still missing the actual interpretation. https://github.com/MartinNowak/CC1/commit/ed28b8966de86e7449f93ce4e4cf7aed3082180b https://github.com/MartinNowak/CC1/commit/899e67cf7038050b86eed533c9165bd2ba06e609 There is nothing simpler about a BC interpreter. Instead you have to deal with converting control flow and computing addressing. The debugging metaphor would be comparing a program that only uses pointer arithmetic against one that is memory safe, the former can randomly write everywhere from anywhere, the latter could use the wrong reference.I don't think a possible future need for a JIT is a good reason to avoid an bytecode interpreter.It's a very good reason, b/c once you work on JIT, there is no benefit for BC left, e.g. all the extra work for nothing. That said, I doubt we'll need a JIT anytime soon.A large part of the work of adding a new (JIT) backend is pinning down the semantics, and adding a bytecode interpreter will certainly help to do that.The semantic problem is already solved, in a file called interpret.d by sth. that's an AST interpreter, that just happens to use the wrong value structures and leaks memory. Converting that to BC will be quite difficult, cleaning it up and changing it to use a better stack and deterministic memory management is rather straightforward. Last but not least, don't forget that we have the same situation since over 3 years already. It has always been similarly easy to write a better interpreter, it just never happened b/c the ambitions never matched the available resources. -Martin
May 21 2016
On 05/21/2016 11:18 PM, Martin Nowak wrote:The debugging metaphor would be comparing a program that only uses pointer arithmetic against one that is memory safe, the former can randomly write everywhere from anywhere, the latter could use the wrong reference.It's also similar to comparing assembly code to C.
May 21 2016
On Saturday, 21 May 2016 at 21:20:54 UTC, Martin Nowak wrote:On 05/21/2016 11:18 PM, Martin Nowak wrote:I am just working on a change that introduces a temporary-Stack to the memory management of dmd. So far it crashes :)The debugging metaphor would be comparing a program that only uses pointer arithmetic against one that is memory safe, the former can randomly write everywhere from anywhere, the latter could use the wrong reference.It's also similar to comparing assembly code to C.
May 27 2016
On 15/05/2016 9:57 PM, Martin Nowak wrote:On 05/15/2016 01:58 PM, Daniel Murphy wrote:We really should have discussed this last week!The biggest advantage of bytecode is not the interpreter speed, it's that by lowering you can substitute VarExps etc with actual references to memory without modifying the AST. By working with something lower level than the AST, you should end up with something much less complex and with fewer special cases.Which is a bad assessment, you can stick variable indexes into VarDeclaration (we already do that) and thereby access them in O(1). Converting control flow and references into byte code is far from trivial, we're talking about another s2ir and e2ir here. -Martin
May 15 2016
On Sunday, 15 May 2016 at 12:54:33 UTC, Daniel Murphy wrote:We really should have discussed this last week!I agree. Maybe we can have a skype conference or something in the next days. About the whole to BC or not to BC discussion. As Daniel already outlined, the main purpose it not speed, but having a simple lowered representation to interpret. Many AST interpreters switched to a byte-code because it's much easier to maintain.
May 15 2016
On 05/15/2016 03:55 PM, Stefan Koch wrote:About the whole to BC or not to BC discussion. As Daniel already outlined, the main purpose it not speed, but having a simple lowered representation to interpret. Many AST interpreters switched to a byte-code because it's much easier to maintain.I just don't buy the argument for using BC. In order to generate linearized bytecode you'll have to fully walk (a.k.a. interpret) your AST tree, collect and fixup variable references and jump addresses, precompute frame sizes, and still maintain a dedicated stack and heap for variables (b/c you don't want to use D's GC to maintain the lifetime, and using raw pointers will easily result in time-consuming memory corruptions). This effort might be worthwhile for hot loops if you wanted to generate simple asm code so that the CPU can do the interpretation (2nd step after AST interpreter in [¹]). But at this point this would be a premature optimization. Clearly a BC interpreter is both more complex than an AST interpreter and less optimal than a simple JIT. Sure supporting D's pointer arithmetic in an interpreter will be challenging, but in fact you'll have to solve the same problem for a bytecode interpreter (how to maintain ownership when pointing to a part of a struct). The simple but bad solution, using raw pointers and relying on D's GC, would work for both interpreters. Another simple but RC friendly solution is to compose everything from reference Values, e.g. a struct or array being modeled as RC!Value[], and a hash as RC!Value[RC!Value]. One could even do a hybrid between value and reference type by lazily moving values onto the heap when needed. struct Value { static struct Impl { mixin(bitfields!( uint, "refCount", 31, bool, "onHeap", 1)); union { dinteger_t int_; uinteger_t uint_; real_t real_; String str_; Value[] array; Impl* heap; } } Impl impl; ref Impl get() { return onHeap ? *impl.heap : impl; } alias get this; void moveToHeap() { if (impl.onHeap) return; auto p = heapAllocator.alloc!Impl; *p = impl; p.refCount = 1; impl.heap = p; impl.onHeap = true; } ~this() { if (impl.onHeap && --impl.heap.refCount == 0) heapAllocator.free(impl.heap); } } auto heapAllocator = FreeList!(AllocatorList!( (size_t n) => Region!Mallocator(max(n, 1024 * 1024)) ))(); //... class Interpreter { //... void visit(PtrExp e) { stack.push(interpret(e.e1, istate, ctfeNeedLvalue)); } void visit(IndexExp e) { accept(e1); auto v1 = stack.pop(); accept(e2); auto v2 = stack.pop(); if (ctfeGoal == ctfeNeedLvalue) v1.array[v2.uint_].moveToHeap(); stack.push(v1.array[v2.uint_]); } //... } That way you could benefit from memory efficient value types while still being able to take references from any element. Should be possible to do the same with references/pointers to stack variables, but you want check that refCount == 1 when a stack frame gets cleaned up. [¹]: http://dconf.org/2013/talks/chevalier_boisvert.pdf p. 59 ff
May 16 2016
On 05/16/2016 03:03 PM, Martin Nowak wrote:~this() { if (impl.onHeap && --impl.heap.refCount == 0) heapAllocator.free(impl.heap); }Of course missing the increment for copies. this(this) { if (impl.onHeap) ++impl.heap.refCount; }
May 16 2016
On 05/15/2016 02:54 PM, Daniel Murphy wrote:We really should have discussed this last week!I talked about it w/ Stefan, and asked him to volunteer for an implementation, that's why we have this thread ;). In any case I'm convinced that the simple-first strategy has a much higher chance to be implemented this year, whereas the bug report [¹] for slow CTFE is already 5 years old. [¹]: https://issues.dlang.org/show_bug.cgi?id=6498
May 15 2016
On Sunday, 15 May 2016 at 10:29:21 UTC, Martin Nowak wrote:On 05/10/2016 08:45 AM, Jacob Carlborg wrote:Correct. A ByteCode Interpreter will add even more implementation overhead, and the benefit is only realizable if the ByteCode is a standard format that can be read other backends such as a jit.I was listening to a discussion Don and Daniel had about the current implementation of CTFE. They talked about using a byte code interpreter. Even implementing a really crappy byte code interpreter would be a huge improvement.No need for a byte-code interpreter, it mostly just adds overhead and complexity over an AST interpreter. If you want to go really fast you need some sort of JIT anyhow, but a proper interpreter will be orders of mangnitude faster than the current implementation. I might refer you to http://dconf.org/2013/talks/chevalier_boisvert.pdf page 59 ff.
May 15 2016
On 05/15/2016 02:02 PM, Stefan Koch wrote:Correct. A ByteCode Interpreter will add even more implementation overhead, and the benefit is only realizable if the ByteCode is a standard format that can be read other backends such as a jit.This indeed would be an interesting proposal, interpretable IR that is portable between the backends. But I guess we won't find such IR or at least need to lower it into RealIR for dmd/gcc/llvm. Sounds like an interesting candidate for the next GSoC.
May 15 2016
On Sunday, 15 May 2016 at 10:29:21 UTC, Martin Nowak wrote:On 05/10/2016 08:45 AM, Jacob Carlborg wrote:+1 . One need to walk the tree anyway to generate bytecode, which makes it impossible to make it faster for a one time execution. For frequent executions, then a JIT is preferable, which let the bytecode the favorite choice for more than one, but not too many executions.I was listening to a discussion Don and Daniel had about the current implementation of CTFE. They talked about using a byte code interpreter. Even implementing a really crappy byte code interpreter would be a huge improvement.No need for a byte-code interpreter, it mostly just adds overhead and complexity over an AST interpreter. If you want to go really fast you need some sort of JIT anyhow, but a proper interpreter will be orders of mangnitude faster than the current implementation. I might refer you to http://dconf.org/2013/talks/chevalier_boisvert.pdf page 59 ff.
May 17 2016
On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. Unfortunately It is a pretty big mess to untangle. Code responsible for CTFE is in at least 3 files. [dinterpret.d, ctfeexpr.d, constfold.d] I was shocked to discover that the PowExpression actually depends on phobos! (depending on the exact codePath it may or may not compile...) which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org] My Plan is as follows. Add a new file for my ctfe-interpreter and update it gradually to take more and more of the cases the code in the files mentioned above was used for. Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not. Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution. I will post more details as soon as I dive deeper into the code.What is the current problem with ctfe? Before I switched from C++ to D a few months ago I was heavily using boost hana in C++. I tried to emulate hana in D which worked quite well but the compile time performance was absolutely horrific https://maikklein.github.io/2016/03/01/metaprogramming-typeobject/ After that I tried a few other things and I compared the compile times with https://github.com/boostorg/hana/tree/master/benchmark which I could never beat. The fastest thing, if I remember correctly, was string mixins but they used up too much memory. But I have to say that I don't know much about the D internals and therefore don't know how I would optimize ct code execution.
May 11 2016
On Wednesday, May 11, 2016 07:06:59 maik klein via Digitalmars-d-announce wrote:What is the current problem with ctfe?The biggest problem is that it uses up a _lot_ of memory and is generally slow. For instance, as I understand it, every time it mutates a variable, it actually allocates a new one to hold the new state. This combined with the fact that the compiler doesn't actually ever free memory (since it's normally more efficient for it to work that way), and you risk running out of memory while compiling. CTFE is a fantastic feature, but it evolved over time rather than being designed up front, and it's suffered a lot because of that. Don did a _lot_ of work to improve it, but he wasn't able to continue working on it, and until now, no one has ever really stepped up to finish the job. Don's post gives a good background on why CTFE is the way it is and some of what he did to make it as solid as it is now: http://forum.dlang.org/post/jmvsbhdpsjgeykpukoxf forum.dlang.org But having someone like Stefan reimplement will be _huge_, and the D community will be _very_ grateful. - Jonathan M Davis
May 13 2016
On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. Unfortunately It is a pretty big mess to untangle. Code responsible for CTFE is in at least 3 files. [dinterpret.d, ctfeexpr.d, constfold.d] I was shocked to discover that the PowExpression actually depends on phobos! (depending on the exact codePath it may or may not compile...)Yes. This is because of lowering. Walter said in his DConf talk that lowering was a success; actually, it's a quick-and-dirty hack that inevitably leads to a disaster. Lowering always needs to be reverted.which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org] My Plan is as follows. Add a new file for my ctfe-interpreter and update it gradually to take more and more of the cases the code in the files mentioned above was used for. Do Dataflow analysis on the code that is to be ctfe'd so we can tell beforehand if we need to store state in the ctfe stack or not.You don't need dataflow analysis. The CtfeCompile pass over the semantic tree was intended to determine how many variables are required by each function.Or baring proper data-flow analysis: RefCouting the variables on the ctfe-stack could also be a solution. I will post more details as soon as I dive deeper into the code.The current implementation stores persistent state for every ctfe incovation. While caching nothing. Not even the compiled for of a function body. Because it cannot relax purity.No. Purity is not why it doesn't save the state. It's because of history. I think I need to explain the history of CTFE. Originally, we had constant-folding. Then constant-folding was extended to do things like slicing a string at compile time. Constant folding leaks memory like the Exxon Valdez leaks oil, but that's OK because it only ever happens once. Then, the constant folding was extended to include function calls, for loops, etc. All using the existing constant-folding code. Now the crappy memory usage is a problem. But it's OK because the CTFE code was kind of proof-of-concept thing anyway. Now, everyone asks, why doesn't it use some kind of byte-code interpreter or something? Well, the reason is, it just wasn't possible. There was actually no single CTFE entry point. Instead, it was a complete mess. For example, with template arguments, the compiler would first try to run CTFE on the argument, with error messages suppressed. If that succeeded, it was a template value argument. If it generated errors, it would then see if was a type. If that failed as well, it assumed it was a template alias argument. The other big problem was that CTFE was also often called on a function which had semantic errors. So, here is what I did with CTFE: (1) Implement all the functionality, so that CTFE code can be developed. The valuable legacy of this, which I am immensely proud of, is the file "interpret3.d" in the test suite. It is very comprehensive. If an CTFE implementation passes the test suite, it's good to go. The CTFE implementation itself is practically worthless. It's value was to get the test suite developed. (2) Created a single entry point for CTFE. This involved working out rules for every place that CTFE is actually required, removing the horrid speculative execution of CTFE. It made sure that functions had actually been semantically analyzed before they were executed (there were really horrific cases where the function had its semantic tree modified while it was being executed!!) Getting to this point involved about 60 pull requests and six months of nearly full-time work. Finally it was possible to consider a byte-code interpreter or JITer. We reached this point around Nov 2012. (3) Added a 'ctfeCompile' step which runs over the semantic tree the first time the function is executed at compile time. Right now it does nothing much except that check that the semantic tree is valid. This detected many errors in the rest of the compiler. We reached this point around March 2013. My intention was to extend the cfteCompile step to a byte-code generator. But then I had to stop working on it and concentrate on looking after my family. Looking at the code without knowing the history, you'll think, the obvious way to do this would be with a byte-code generator or JITer, and wonder why the implementation is so horrible. But for most of the history, that kind of implementation was just not possible. People come up with all these elaborate schemes to speed up CTFE. It's totally not necessary. All that's needed is a very simple bytecode interpreter.
May 13 2016
On 13.05.2016 15:59, Don Clugston wrote:All that's needed is a very simple bytecode interpreter.Here is the one I have hacked together: https://github.com/tgehr/d-compiler/blob/master/interpret.d This file does both constant folding and byte-code interpretation for most of the language. I still need to implement exception handling. I'll let you know when it passes interpret3.d. :)
May 13 2016
On Friday, 13 May 2016 at 13:59:57 UTC, Don Clugston wrote:I think I need to explain the history of CTFE. Originally, we had constant-folding. Then constant-folding was extended to do things like slicing a string at compile time. Constant folding leaks memory like the Exxon Valdez leaks oil, but that's OK because it only ever happens once. Then, the constant folding was extended to include function calls, for loops, etc. All using the existing constant-folding code. Now the crappy memory usage is a problem. But it's OK because the CTFE code was kind of proof-of-concept thing anyway. [...]Thanks for the explanation, and for doing so much work on CTFE. I would like to work on a solution that does scale. The Problem is not making a byteCode-interpreter. That part is relatively easy. Currently I am trying to get a detailed understanding of dmd and it's data-structures. (mainly it's AST.) Generating the byte-code seems to be non-trivial. I wonder in how far the glue layer can be of help...
May 13 2016
On 05/13/2016 06:32 PM, Stefan Koch wrote:I would like to work on a solution that does scale. The Problem is not making a byteCode-interpreter. That part is relatively easy. Currently I am trying to get a detailed understanding of dmd and it's data-structures. (mainly it's AST.) Generating the byte-code seems to be non-trivial. I wonder in how far the glue layer can be of help...Seems like I've to repeat this once more, b/c everyone including me didn't got it in the first place. We don't need a bytecode interpreter, it mostly adds overhead and a complicated second layer between walking the AST and interpreting it (think of transforming a for loop with goto into linear bytecode, almost as complicated as in the glue layer). What we basically need is a stack of values, a stack of frames (for function calls and variables in scopes), and an AST visitor that does the interpretation. It would be most helpful for the success of this to follow common CS examples like [¹], [²], or [³]. With realistic expectations we might have a working implementation in a month or so. With more requirements like bytecode, using dmd's backend, or JIT we end up with a long newsgroup discussion ;). Tricky things for a CTFE interpreter include: - enumerating VarDeclarations (they already have a ctfeAdrOnStack field) in each scope, and referring to outer variables from nested scopes At best just use a continuous stack and just set the stack pointer to the last frame pointer when leaving a scope. - getting function calls right Push arguments, on return shift top of stack under arguments and pop them (caller cleanup). If possible detect and support tail recursion. - converting AST values to and from Interpreter Values. Literals and constant VarExp from the AST need to be converted to an interpreter Value before being pushed on the stack. The result of interpretation (top of stack) needs to be converted back to an AST literal. Using separate data types (instead of creating AST values in the interpreter) will be a major performance improvement over using AST values (e.g. 16 vs. ~100 bytes). It also creates a clear boundary between Interpreter and AST values. Currently quite some complexity is thrown at cleaning interpreter generated AST values, and distinguishing interpreter owned from normal AST values (which allows some optimizations) [⁴]. We don't need a tagged union b/c the AST already contains the type information, but a tag could be helpful for debugging [⁵]. Values can be deleted when popped from stack (no ref counting needed I think). - Implementing more complex data structures (arrays, strings, hash tables, aggregates) Use Value[], Value[Value], and a dedicated String (char[]/wchar[]/dchar[]). For structs/classes field indexes are known => use fix-sized Value[]. Value.class_ needs to hold a reference to the actual class instance for vtable calls. Last time I was working on this (also on a bytecode interpreter) the entry point was fairly clear [⁶] (thanks to Don). -Martin [¹]: [The Interpreter In An Undergraduate Compilers Course ](http://arxiv.org/pdf/1412.0426.pdf) [²]: [L8: Interpreters & Visitors](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-005-elements-of-software-construction-fall-2011/lecture-notes/MIT6_005F11_lec08.pdf) [³]: [PA 2: Interpreter](https://sites.google.com/a/bodik.org/cs164/projects/pa2) [⁴]: https://github.com/dlang/dmd/search?q=ownedByCtfe [⁵]: https://github.com/MartinNowak/dmd/blob/28ffb0ab4fa6950f60c085f33f8a2ce23df7c0cd/src/interpret.c#L73 [⁶]: https://github.com/MartinNowak/dmd/blob/28ffb0ab4fa6950f60c085f33f8a2ce23df7c0cd/src/interpret.c#L693
May 15 2016
On 05/09/2016 06:57 PM, Stefan Koch wrote:I was shocked to discover that the PowExpression actually depends on phobos! (depending on the exact codePath it may or may not compile...) which let to me prematurely stating that it worked at ctfe [http://forum.dlang.org/thread/ukcoibejffinknrbzktv forum.dlang.org]There is a really old bug report for that [Issue 3749 – cannot evaluate yl2x (log) and exp functions at compile time](https://issues.dlang.org/show_bug.cgi?id=3749). The lack of exp is really limiting for many nice table precomputation use-cases in scientific contexts. -Martin
May 15 2016
On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE.I will post more details as soon as I dive deeper into the code.Update : int bug6498(int x) { int n = 0; while (n < x) ++n; return n; } static assert(bug6498(10_000_000)==10_000_000); This compiles now for me. Although it still takes 10 seconds ;)
May 27 2016
On Friday, 27 May 2016 at 23:31:24 UTC, Stefan Koch wrote:On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:Big Whoop! Just make the number slightly lager and it fails again.Hi Guys, I have been looking into the DMD now to see what I can do about CTFE.I will post more details as soon as I dive deeper into the code.Update : int bug6498(int x) { int n = 0; while (n < x) ++n; return n; } static assert(bug6498(10_000_000)==10_000_000); This compiles now for me. Although it still takes 10 seconds ;)
May 28 2016
On Saturday, 28 May 2016 at 12:27:26 UTC, Stefan Koch wrote:On Friday, 27 May 2016 at 23:31:24 UTC, Stefan Koch wrote:but smaller than 2_147_483_647 right :)On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:Big Whoop! Just make the number slightly lager and it fails again.Hi Guys, I have been looking into the DMD now to see what I can do about CTFE.I will post more details as soon as I dive deeper into the code.Update : int bug6498(int x) { int n = 0; while (n < x) ++n; return n; } static assert(bug6498(10_000_000)==10_000_000); This compiles now for me. Although it still takes 10 seconds ;)
May 28 2016
On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:I will post more details as soon as I dive deeper into the code.Okay I briefly evaluated the current IR dmd uses for backend communication, and it seems usable for the purposes of a CTFE-Interpreter/JIT. The Memory-Management issue is mostly orthogonal to CTFE. But nonetheless very important.
Jun 03 2016
On Friday, 3 June 2016 at 15:46:27 UTC, Stefan Koch wrote:On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:I have to admit currently I am a bit stuck. Timon Gehr cooperation would be highly appreciated.I will post more details as soon as I dive deeper into the code.Okay I briefly evaluated the current IR dmd uses for backend communication, and it seems usable for the purposes of a CTFE-Interpreter/JIT. The Memory-Management issue is mostly orthogonal to CTFE. But nonetheless very important.
Jun 07 2016
First small code example compiles! int bug6498(int x) { int n = 0; while (n < x) { n++; } return n; } evaluation of bug6498(100_000_00) took 226 msecs. evaluation of bug6498(100_000_000) took 2228 msecs. The memory allocated by the Evaluator is exactly 12 bytes.
Jun 29 2016
On Thursday, 30 June 2016 at 01:20:08 UTC, Stefan Koch wrote:First small code example compiles! int bug6498(int x) { int n = 0; while (n < x) { n++; } return n; } evaluation of bug6498(100_000_00) took 226 msecs. evaluation of bug6498(100_000_000) took 2228 msecs. The memory allocated by the Evaluator is exactly 12 bytes.The speedup comes from interpreting the IR or fixing the memory leaking?
Jun 29 2016
On Thursday, 30 June 2016 at 01:32:47 UTC, Martin Nowak wrote:On Thursday, 30 June 2016 at 01:20:08 UTC, Stefan Koch wrote:Both. Actually I could not imagine fixing the memory problem without doing IR interpretation. I will tackle compiling more difficult code later today. As soon as I can run my compiletime brainfuck I will open a PR. Until then you can see my progress at https://github.com/UplinkCoder/dmd/tree/newCTFE I will try to always keep the branch in a healthy state.First small code example compiles! int bug6498(int x) { int n = 0; while (n < x) { n++; } return n; } evaluation of bug6498(100_000_00) took 226 msecs. evaluation of bug6498(100_000_000) took 2228 msecs. The memory allocated by the Evaluator is exactly 12 bytes.The speedup comes from interpreting the IR or fixing the memory leaking?
Jun 29 2016
On Thursday, 30 June 2016 at 03:17:38 UTC, Stefan Koch wrote:Until then you can see my progress at https://github.com/UplinkCoder/dmd/tree/newCTFE I will try to always keep the branch in a healthy state.I can't wait to see the benchmarks. Keep up the good work!
Jun 30 2016
On Thursday, 30 June 2016 at 07:15:30 UTC, Nordlöw wrote:On Thursday, 30 June 2016 at 03:17:38 UTC, Stefan Koch wrote:Currently the interpreter is about 10x-15x slower then native execution. and about 2x-4000x faster then the old Interpreter :) code I can currently compile : uint test2(int x) { uint r = 0; const uint end = 9; for(int i = 0;i < end;++i) { for(int j = 0;j < 9;++j) { r += j; r += i; } } return r; } dmd's interpreter and mine return the same value :)Until then you can see my progress at https://github.com/UplinkCoder/dmd/tree/newCTFE I will try to always keep the branch in a healthy state.I can't wait to see the benchmarks. Keep up the good work!
Jun 30 2016
On 06/30/2016 05:17 AM, Stefan Koch wrote:Both. Actually I could not imagine fixing the memory problem without doing IR interpretation. I will tackle compiling more difficult code later today. As soon as I can run my compiletime brainfuck I will open a PR. Until then you can see my progress at https://github.com/UplinkCoder/dmd/tree/newCTFE I will try to always keep the branch in a healthy state.Looks good and will definitely lead to a proper CTFE interpreter. You might want to go back and look at https://github.com/MartinNowak/dmd/blob/28ffb0ab4fa6950f60c085f33f8a2ce23df7c0cd/src/interpret.c, it could already do a few more things than your interpreter atm. [¹]: https://github.com/MartinNowak/dmd/commits/ctfe
Jun 30 2016
On 08.06.2016 03:20, Stefan Koch wrote:On Friday, 3 June 2016 at 15:46:27 UTC, Stefan Koch wrote:Sorry, I had missed this. I see you were able to make progress.On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:I have to admit currently I am a bit stuck. Timon Gehr cooperation would be highly appreciated.I will post more details as soon as I dive deeper into the code.Okay I briefly evaluated the current IR dmd uses for backend communication, and it seems usable for the purposes of a CTFE-Interpreter/JIT. The Memory-Management issue is mostly orthogonal to CTFE. But nonetheless very important.
Jun 30 2016
On Thursday, 30 June 2016 at 14:17:30 UTC, Timon Gehr wrote:Sorry, I had missed this. I see you were able to make progress.It's fine. Honestly the hardest thing was to actually get started. Once I see something working the excitement carries me forward :) I would appreciate a critical opinion, anytime!
Jun 30 2016
On Thursday, 30 June 2016 at 14:26:29 UTC, Stefan Koch wrote:On Thursday, 30 June 2016 at 14:17:30 UTC, Timon Gehr wrote:Another update. _very_ Basic SwtichStatements work now :) I expect a simple project like a compile-time bf interpreter to work by the end of next week.Sorry, I had missed this. I see you were able to make progress.It's fine. Honestly the hardest thing was to actually get started. Once I see something working the excitement carries me forward :) I would appreciate a critical opinion, anytime!
Jul 03 2016
On Monday, 4 July 2016 at 01:54:29 UTC, Stefan Koch wrote:On Thursday, 30 June 2016 at 14:26:29 UTC, Stefan Koch wrote:Nice work! Any chance that you could also improve AliasSeq algorithms, like those in std.meta to compile faster and use less memory during compilation? Or is that too different from CTFE?On Thursday, 30 June 2016 at 14:17:30 UTC, Timon Gehr wrote:Another update. _very_ Basic SwtichStatements work now :) I expect a simple project like a compile-time bf interpreter to work by the end of next week.Sorry, I had missed this. I see you were able to make progress.It's fine. Honestly the hardest thing was to actually get started. Once I see something working the excitement carries me forward :) I would appreciate a critical opinion, anytime!
Jul 04 2016
On Monday, 4 July 2016 at 07:29:49 UTC, ZombineDev wrote:On Monday, 4 July 2016 at 01:54:29 UTC, Stefan Koch wrote:BTW, do you plan to handle stuff like exceptions, virtual calls and associative arrays and if so how? Sounds quite challenging.On Thursday, 30 June 2016 at 14:26:29 UTC, Stefan Koch wrote:Nice work! Any chance that you could also improve AliasSeq algorithms, like those in std.meta to compile faster and use less memory during compilation? Or is that too different from CTFE?On Thursday, 30 June 2016 at 14:17:30 UTC, Timon Gehr wrote:Another update. _very_ Basic SwtichStatements work now :) I expect a simple project like a compile-time bf interpreter to work by the end of next week.Sorry, I had missed this. I see you were able to make progress.It's fine. Honestly the hardest thing was to actually get started. Once I see something working the excitement carries me forward :) I would appreciate a critical opinion, anytime!
Jul 04 2016
On Monday, 4 July 2016 at 07:33:48 UTC, ZombineDev wrote:On Monday, 4 July 2016 at 07:29:49 UTC, ZombineDev wrote:Templates do interact with CTFE. They will improve as well as a consequence of CTFE being less wasteful. I will do it bit by bit. For now getting a simple parser to work with the new engine is the goal. Everything else comes later.Nice work! Any chance that you could also improve AliasSeq algorithms, like those in std.meta to compile faster and use less memory during compilation? Or is that too different from CTFE?BTW, do you plan to handle stuff like exceptions, virtual calls and associative arrays and if so how? Sounds quite challenging.
Jul 04 2016
On Monday, 4 July 2016 at 07:33:48 UTC, ZombineDev wrote:BTW, do you plan to handle stuff like exceptions, virtual calls and associative arrays and if so how? Sounds quite challenging.on the lower level, it's all just arrays and jumps. ;-)
Jul 05 2016
On Monday, 4 July 2016 at 07:29:49 UTC, ZombineDev wrote:Nice work! Any chance that you could also improve AliasSeq algorithms, like those in std.meta to compile faster and use less memory during compilation? Or is that too different from CTFE?Not that I opposes this, but please keep it focused. Doing a bytecode interpreter is a huge task on its own and this seems largely orthogonal.
Jul 05 2016
On Tuesday, 5 July 2016 at 21:11:39 UTC, deadalnix wrote:On Monday, 4 July 2016 at 07:29:49 UTC, ZombineDev wrote:I was actually wondering if they're orthogonal or some of the CTFE improvements could be reused. I was not saying the he should work on both if they're not related.Nice work! Any chance that you could also improve AliasSeq algorithms, like those in std.meta to compile faster and use less memory during compilation? Or is that too different from CTFE?Not that I opposes this, but please keep it focused. Doing a bytecode interpreter is a huge task on its own and this seems largely orthogonal.
Jul 05 2016
so, we played a little game with Stefan: i wrote a simple stack-based VM implementation for our beloved bug6498, and got 270 msecs with debug build, 140 msecs with release build. can be made even faster with some simple peephole optimizer (it has two hacks to get fair times on 6498, but this is not a good peephole opt ;-). of course, it scales linearly too. don't expect me to join the race, though: i was just curious how well stack-based VM can do.
Jul 05 2016
On Tuesday, 5 July 2016 at 16:40:05 UTC, ketmar wrote:so, we played a little game with Stefan: i wrote a simple stack-based VM implementation for our beloved bug6498, and gotWhat is «bug6498»?
Jul 05 2016
On Tue, Jul 05, 2016 at 05:44:14PM +0000, Ola Fosheim Grstad via Digitalmars-d-announce wrote:On Tuesday, 5 July 2016 at 16:40:05 UTC, ketmar wrote:https://issues.dlang.org/show_bug.cgi?id=6498 T -- Give me some fresh salted fish, please.so, we played a little game with Stefan: i wrote a simple stack-based VM implementation for our beloved bug6498, and gotWhat is bug6498?
Jul 05 2016
and just to make sure that my approach is working: bytecode compiler now compiles simple free functions without args and returning int (yep, there are some in phobos! ;-), while passing everything other to old interpreter. it works, and all phobos unittests are passed (and some functions were actually executed with VM). that's where i should stop, i think, until it comes too far. ;-)
Jul 05 2016
On Tue, Jul 5, 2016 at 11:54 PM, ketmar via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:and just to make sure that my approach is working: bytecode compiler now compiles simple free functions without args and returning int (yep, there are some in phobos! ;-), while passing everything other to old interpreter. it works, and all phobos unittests are passed (and some functions were actually executed with VM). that's where i should stop, i think, until it comes too far. ;-)Are you sharing this code / how you did it with the GSOC intern?
Jul 05 2016
On Wednesday, 6 July 2016 at 05:54:48 UTC, Rory McGuire wrote:Are you sharing this codeyes. we are chatting with Stefan in IRC, and the repository is public (i mean, the link was there ;-). yet it won't compile with "vanilla" dmd anyway -- i require my dmd fork ("aliced"). and i don't really want to make it more public, as i have no intentions to turn that into full-blown engine. also, not only our codebases are completely different, but our designs and approaches are drastically different. we just can't share/reuse the code, those projects are as compatible as WLIV and Z80. ;-)how you did it with the GSOC intern?Stefan in not GSOC intern. ;-)
Jul 05 2016
On Wed, Jul 6, 2016 at 8:09 AM, ketmar via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Wednesday, 6 July 2016 at 05:54:48 UTC, Rory McGuire wrote:Nice! Sounds like fun.Are you sharing this codeyes. we are chatting with Stefan in IRC, and the repository is public (i mean, the link was there ;-). yet it won't compile with "vanilla" dmd anyway -- i require my dmd fork ("aliced"). and i don't really want to make it more public, as i have no intentions to turn that into full-blown engine.also, not only our codebases are completely different, but our designs and approaches are drastically different. we just can't share/reuse the code, those projects are as compatible as WLIV and Z80. ;-)Thought as much, wondered if the ideas about how they work were being shared; often one idea sparks another.how you did it with the GSOC intern?doh! my bad.Stefan in not GSOC intern. ;-)
Jul 06 2016
On Wednesday, 6 July 2016 at 08:16:32 UTC, Rory McGuire wrote:Thought as much, wondered if the ideas about how they work were being shared; often one idea sparks another.sure, some ideas flows; mostly very high-level. for example, proper fallback to the original interpreter was invented by Stefan, but i was faster to make it work. ;-) after all, we aren't competitors. he is still working hard on full implementation, and i am just having some fun, investigating creation of DMD backends by the way.
Jul 06 2016
On Wednesday, 6 July 2016 at 05:54:48 UTC, Rory McGuire wrote:Are you sharing this codei mean "my code is publicly available, but we aren't sharing any code between our projects".
Jul 05 2016
just... can't... stop... some current statistics: druntime total interpreted calls: 27,146 total complied calls : 1,330 phobos total interpreted calls: 6,492,826 total complied calls : 19,975 i can't do function calls from compiled code yet, so number of compiled calls is low, and no speedup can be seen. also, i can do only integer math and string concatenation. yes, phobos has ALOT of CTFE! ;-) this is statistics from "make -f posix.mak unittest" (yes, i can pass all unittests too!) still, not that bad for a toy implementation! ;-)
Jul 06 2016
yay. ackemann(3, 7) in 70 milliseconds! and it does TCO. default interpreter is unable to execute that -- recursion is too deep.
Jul 07 2016
On Monday, 9 May 2016 at 16:57:39 UTC, Stefan Koch wrote:Hi Guys, I have been looking into the DMD now to see what I can do about CTFE. [ .... ] I will post more details as soon as I dive deeper into the code.I decided to keep a gist updated to represent the current state the new engine can handle. https://gist.github.com/UplinkCoder/89faa06311e417aa93ea99bc92934d3e This is the currentState after approx. 50 hours of work
Jul 09 2016
On Saturday, 9 July 2016 at 20:09:14 UTC, Stefan Koch wrote:I decided to keep a gist updated to represent the current state the new engine can handle. https://gist.github.com/UplinkCoder/89faa06311e417aa93ea99bc92934d3e This is the currentState after approx. 50 hours of workFirst StringIndexing works now. The next step is getting structs right,
Jul 13 2016
On Thursday, 14 July 2016 at 00:45:53 UTC, Stefan Koch wrote:On Saturday, 9 July 2016 at 20:09:14 UTC, Stefan Koch wrote:Support for _basic_ support for structs has just landed in my branch. only structs with int or uint members are supported for now. And no arrays. But this is coming soon :)I decided to keep a gist updated to represent the current state the new engine can handle. https://gist.github.com/UplinkCoder/89faa06311e417aa93ea99bc92934d3e This is the currentState after approx. 50 hours of workFirst StringIndexing works now. The next step is getting structs right,
Jul 15 2016
On Friday, 15 July 2016 at 20:36:46 UTC, Stefan Koch wrote:I decided to keep a gist updated to represent the current state the new engine can handle. https://gist.github.com/UplinkCoder/89faa06311e417aa93ea99bc92934d3eInternal changes to the bytecode engine make the manipulation of values on the ctfe stack possible. this allows the following code to properly compile now. struct V3 {int x; int y; int z;} int fn() { auto b = V3(1,2,3); b.y += 19; return b.y; } static assert(fn() == 21);
Jul 17 2016
Nice! how are you keeping track of changes? Are you tagging / branching each time you get something new working? On Sun, Jul 17, 2016 at 12:12 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Friday, 15 July 2016 at 20:36:46 UTC, Stefan Koch wrote:I decided to keep a gist updated to represent the current state the new engine can handle. https://gist.github.com/UplinkCoder/89faa06311e417aa93ea99bc92934d3eInternal changes to the bytecode engine make the manipulation of values on the ctfe stack possible. this allows the following code to properly compile now. struct V3 {int x; int y; int z;} int fn() { auto b = V3(1,2,3); b.y += 19; return b.y; } static assert(fn() == 21);
Jul 17 2016
On Sunday, 17 July 2016 at 12:12:17 UTC, Rory McGuire wrote:Nice! how are you keeping track of changes? Are you tagging / branching each time you get something new working?I just push a new commit. And add code to the gist. Why would I branch ? It all goes towards the same goal.
Jul 17 2016
On Sun, Jul 17, 2016 at 2:41 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Sunday, 17 July 2016 at 12:12:17 UTC, Rory McGuire wrote:A commit does pretty much the same thing. Tags/Branches just make UIs show a "menu" for selecting a change, not important really. I had just wondered if you were marking these milestones. Someone could always branch off of any of your commits, it they wanted to try an alternative approach (or learn from you). Thanks for all the work you are doing. I love CTFE. I have a lot of big vibe (diet) templates, and my own Jade ctfe implementation, really looking forward to faster compile times. RNice! how are you keeping track of changes? Are you tagging / branching each time you get something new working?I just push a new commit. And add code to the gist. Why would I branch ? It all goes towards the same goal.
Jul 17 2016
On Sunday, 17 July 2016 at 13:04:33 UTC, Rory McGuire wrote:On Sun, Jul 17, 2016 at 2:41 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:If you let me have a look at your jade-impl. I can probably work on speeding up it up. Vibed is still going to take a while. I need to figure all this UTF stuff out to make string handling robust.[...]A commit does pretty much the same thing. Tags/Branches just make UIs show a "menu" for selecting a change, not important really. I had just wondered if you were marking these milestones. Someone could always branch off of any of your commits, it they wanted to try an alternative approach (or learn from you). Thanks for all the work you are doing. I love CTFE. I have a lot of big vibe (diet) templates, and my own Jade ctfe implementation, really looking forward to faster compile times. R
Jul 17 2016
On Sun, Jul 17, 2016 at 3:28 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Sunday, 17 July 2016 at 13:04:33 UTC, Rory McGuire wrote:Thanks that would be great, however I think its a while off before it can work on your ctfe implementation. It uses Pegged, so getting the Pegged JSON parser or pegged.peg working would be a first step. If you were just meaning to show me any improvements I could make, the source code is at: https://github.com/rjmcguire/jaded Cheers, ROn Sun, Jul 17, 2016 at 2:41 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote: [...]If you let me have a look at your jade-impl. I can probably work on speeding up it up. Vibed is still going to take a while. I need to figure all this UTF stuff out to make string handling robust.A commit does pretty much the same thing. Tags/Branches just make UIs show a "menu" for selecting a change, not important really. I had just wondered if you were marking these milestones. Someone could always branch off of any of your commits, it they wanted to try an alternative approach (or learn from you). Thanks for all the work you are doing. I love CTFE. I have a lot of big vibe (diet) templates, and my own Jade ctfe implementation, really looking forward to faster compile times. R
Jul 17 2016
On Sunday, 17 July 2016 at 15:57:28 UTC, Rory McGuire wrote:Thanks that would be great, however I think its a while off before it can work on your ctfe implementation. It uses Pegged, so getting the Pegged JSON parser or pegged.peg working would be a first step.pegged uses templates. There is an intersection on which it can profit from CTFE improvments. But for the most part, it's a different sub-system in the compiler. That said, templates are next on my TODO list.
Jul 17 2016
On Sun, Jul 17, 2016 at 6:08 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Sunday, 17 July 2016 at 15:57:28 UTC, Rory McGuire wrote:Nice, so I'll be able to see separate improvements in my CTFE stuff vs the pegged template stuff once structs, classes, etc.. are handled in your new ctfe.Thanks that would be great, however I think its a while off before it can work on your ctfe implementation. It uses Pegged, so getting the Pegged JSON parser or pegged.peg working would be a first step.pegged uses templates. There is an intersection on which it can profit from CTFE improvments. But for the most part, it's a different sub-system in the compiler. That said, templates are next on my TODO list.
Jul 17 2016
On Sunday, 17 July 2016 at 16:43:18 UTC, Rory McGuire wrote:Nice, so I'll be able to see separate improvements in my CTFE stuff vs the pegged template stuff once structs, classes, etc.. are handled in your new ctfe.Yes. Btw while working on printing template-instantiations I discovered that ctfe improvements will most likely have a much higher impact in template heavy code then I fist expected.
Jul 19 2016
Hi, I have fresh performance statistics: The test[1] involved running an empty while loop. Machine 1 Linux : DMD release : Interpreted : 3400 ms || Pseudo-Jited 230 || 50ms Native DMD Debug : Interpreted 4560 || Pseudo-Jited 260ms || Native 230 ms LDC release : Interpreted 2400 ms || Pseudo-Jited 0 ms || Native 0 ms LDC debug : Interpreted 8700 ms || Pseudo-Jited 330 ms || Native 250 ms Machine 2 Windows : DMD release : Interpreted : 5500 ms || Pseudo-Jited 180ms || 40ms Native DMD Debug : Interpreted 5500 || Pseudo-Jited 320ms || Native 180 ms Pay attention to the ratio (~4.5) between (pseudo)jit[2] and native. This slowdown inherent in the VM design I choose. please share your thoughts. [1] https://github.com/UplinkCoder/dmd/blob/newCTFE/bcPerf.d [2] https://github.com/UplinkCoder/dmd/blob/newCTFE/src/bc_c_backend.d
Jul 29 2016
On Friday, 29 July 2016 at 11:30:20 UTC, Stefan Koch wrote:please share your thoughts.When is this moving into dmd master?
Jul 29 2016
On Friday, 29 July 2016 at 12:47:55 UTC, Robert burner Schadek wrote:On Friday, 29 July 2016 at 11:30:20 UTC, Stefan Koch wrote:As soon as it passes the test-suite. And can execute diet-ng on the fast-path. Currently I have issues with chained binary expressions. such as if ((a && b) || (a && c)) {//bla}please share your thoughts.When is this moving into dmd master?
Jul 29 2016
On Friday, 29 July 2016 at 14:28:03 UTC, Stefan Koch wrote:if ((a && b) || (a && c)) {//bla}This is now solved although quite naively at the cost of inserting twice the number of instructions for thoose cases. Then agian we are still much faster then the old interpreter. And I can still optimize this if it should turn out to be a bottleneck. Tomorrow I will fix the regressed string handling.
Jul 29 2016
I am very happy to announce that calls are almost working now. And the code-gen-interface[1] is near finalization. It should be very easy to provide different back-ends such as LLVM or libJIT now. The missing pieces well be added during next week. I invite everyone to comment on the interface and code. Don't be shy and feel free to comment [1] https://github.com/UplinkCoder/dmd/blob/newCTFE/src/bc_common.d#L313 So far the strong decoupling between dmd and the bytecode has worked out pretty well. Being able to debug and test the bytecode component independently from the AST-processing makes for a faster development process and allows insight into the code-gen behavior.
Jul 31 2016
Time for an update. (ASCII)-Strings work reasonably well. I am now working on supporting general Sliceing and Appending. The effort on function calls is also still ongoing. I added a switch to my version of dmd which allows to toggle the ctfe engine. So now I can compare apples to apples when posting perf data. A nice weekend to all of you.
Aug 06 2016
On 06 Aug 2016 16:30, "Stefan Koch via Digitalmars-d-announce" < digitalmars-d-announce puremagic.com> wrote:Time for an update. (ASCII)-Strings work reasonably well. I am now working on supporting general Sliceing and Appending. The effort on function calls is also still ongoing. I added a switch to my version of dmd which allows to toggle the ctfeengine.So now I can compare apples to apples when posting perf data. A nice weekend to all of you.Hi Stefan, Are you saying we can play around with ascii string slicing/appending already? The gist with the current state of ctfe support seems to have last been changed 21 days ago? Am I reading that right? If so where could I find your current tests, if I wanted to run the tests on my machine. Cheers, Rory
Aug 06 2016
On Saturday, 6 August 2016 at 19:07:10 UTC, Rory McGuire wrote:Hi Stefan, Are you saying we can play around with ascii string slicing/appending already?No, not now, but very soon. I want to have _basic_ utf8 support before I am comfortable with enabling string operations.The gist with the current state of ctfe support seems to have last been changed 21 days ago? Am I reading that right? If so where could I find your current tests, if I wanted to run the tests on my machine.That could be right. Many features are half-implemented at the moment and will fail in random and exciting ways. Therefore it is too soon to publish code testing those. If you want particular features the best way is contacting me.
Aug 06 2016
On Saturday, 6 August 2016 at 23:04:48 UTC, Stefan Koch wrote:On Saturday, 6 August 2016 at 19:07:10 UTC, Rory McGuire wrote:Tomorrow this is going to work.Hi Stefan, Are you saying we can play around with ascii string slicing/appending already?No, not now, but very soon. I want to have _basic_ utf8 support before I am comfortable with enabling string operations.
Aug 07 2016
On Sunday, 7 August 2016 at 16:52:28 UTC, Stefan Koch wrote:On Saturday, 6 August 2016 at 23:04:48 UTC, Stefan Koch wrote:Hi Stefan, How much effort will it be to integrate your work into LDC? I'd like to test it on some Weka code. Definitely let us know once you can CTFE something like std.traits.ParameterStorageClassTuple. cheers, JohanNo, not now, but very soon. I want to have _basic_ utf8 support before I am comfortable with enabling string operations.Tomorrow this is going to work.
Aug 08 2016
On Monday, 8 August 2016 at 09:51:03 UTC, Johan Engelen wrote:On Sunday, 7 August 2016 at 16:52:28 UTC, Stefan Koch wrote:Hi Johan, It won't be too much effort. Since it was designed with that in mind.On Saturday, 6 August 2016 at 23:04:48 UTC, Stefan Koch wrote:Hi Stefan, How much effort will it be to integrate your work into LDC? I'd like to test it on some Weka code. Definitely let us know once you can CTFE something like std.traits.ParameterStorageClassTuple. cheers, JohanNo, not now, but very soon. I want to have _basic_ utf8 support before I am comfortable with enabling string operations.Tomorrow this is going to work.
Aug 08 2016
1. You said CTFE engine can be ctfeable itself? But it uses unions in BCValue - it's not going to work in CTFE, is it? Just wondering myself what's the way to have polymorphism at compile time. 2. The byte code generator interface has no mean to declare functions? In case of LLVM jit one would want to declare functions so that jit can use registers to pass parameters for a bit more extra speed, though it's probably not worth it.
Aug 09 2016
On Tuesday, 9 August 2016 at 12:30:18 UTC, Kagamin wrote:1. You said CTFE engine can be ctfeable itself? But it uses unions in BCValue - it's not going to work in CTFE, is it? Just wondering myself what's the way to have polymorphism at compile time. 2. The byte code generator interface has no mean to declare functions? In case of LLVM jit one would want to declare functions so that jit can use registers to pass parameters for a bit more extra speed, though it's probably not worth it.1. unions work fine when you use them as discriminated unions. 2. The BCGen does not have to declare functions. Since every-time it is created it will implicitly define a function. It will all make more sense once the function-call system works.
Aug 09 2016
I have just committed the changes necessary for (ascii) string indexing and (ascii) string-foreach. Currently working on UTF8 => UTF32 auto-re-encoding and StringConcat and Slice-Support. Completion of Slice support will also fix the interplay between structs and arrays. Cheers, Stefan
Aug 11 2016
Hi, I took a break from work on string operations and focused instead of improving the robustness of the engine. I.E. for it not to halt the compiler on unsupported expressions. right now, I can compile druntime without failures. Phobos should be working by the end of next week. Have a nice Sunday, Stefan PS. String foreach regressed. And Struct-handling regressed. Due to a change of memory-layout. I will fix this as soon as the engine does no longer abort.
Aug 13 2016
On Sun, Aug 14, 2016 at 5:21 AM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:Hi, I took a break from work on string operations and focused instead of improving the robustness of the engine. I.E. for it not to halt the compiler on unsupported expressions. right now, I can compile druntime without failures. Phobos should be working by the end of next week. Have a nice Sunday, Stefan PS. String foreach regressed. And Struct-handling regressed. Due to a change of memory-layout. I will fix this as soon as the engine does no longer abort.Nice! thanks! Will be nice to be able to test newCTFE with our "normal" code every now and then.
Aug 14 2016
Just a small update today. if(__ctfe) and if(!__ctfe) now get special treatment. Also working on getting compiletime-parsers to run.
Aug 17 2016
On 17 Aug 2016 18:50, "Stefan Koch via Digitalmars-d-announce" < digitalmars-d-announce puremagic.com> wrote:Just a small update today. if(__ctfe) and if(!__ctfe) now get special treatment. Also working on getting compiletime-parsers to run.Nice tease with the "compile time parsers to run" aside. We're salivating here. What exactly did you mean by that? Which compile time parser are you using for testing? PS: thanks for the updates!
Aug 17 2016
On Wednesday, 17 August 2016 at 18:24:37 UTC, Rory McGuire wrote:On 17 Aug 2016 18:50, "Stefan Koch via Digitalmars-d-announce" < digitalmars-d-announce puremagic.com> wrote:I am using ctfe-bf for a start and others of my own design. Of course pegged is also on the menu.Just a small update today. if(__ctfe) and if(!__ctfe) now get special treatment. Also working on getting compiletime-parsers to run.Nice tease with the "compile time parsers to run" aside. We're salivating here. What exactly did you mean by that? Which compile time parser are you using for testing? PS: thanks for the updates!
Aug 17 2016
Hi Guys, First of all, parsers will not make it before September. I am sorry about that. Currently I am fixing issues with the design, that for example prevent slices of slices to work. Also I am writing analysis and debugging code to (such as generating a call-graph and primitive DFA) that will hopefully make function-calls work reliably. The DMD-AST does not make it easy to track things like variables originating from a parent-scope. I feel that this can have a positive impact on the whole of dmd, since that will allow better frontend-optimisations. I am happy for all comments or suggestions. Cheers, Stefan
Aug 28 2016
On Monday, 29 August 2016 at 00:24:01 UTC, Stefan Koch wrote:I feel that this can have a positive impact on the whole of dmd, since that will allow better frontend-optimisations. I am happy for all comments or suggestions.The work you are doing is just awesome! Many thanks.
Aug 29 2016
On Mon, Aug 29, 2016 at 9:51 AM, Dominikus Dittes Scherkl via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:On Monday, 29 August 2016 at 00:24:01 UTC, Stefan Koch wrote:+1 your work is key for our success as a community. RI feel that this can have a positive impact on the whole of dmd, since that will allow better frontend-optimisations. I am happy for all comments or suggestions.The work you are doing is just awesome! Many thanks.
Aug 29 2016
On Monday, 29 August 2016 at 08:05:10 UTC, Rory McGuire wrote:On Mon, Aug 29, 2016 at 9:51 AM, Dominikus Dittes Scherkl viaThanks guys. I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?The work you are doing is just awesome! Many thanks.+1 your work is key for our success as a community. R
Aug 29 2016
On 2016-08-29 10:39, Stefan Koch wrote:Thanks guys. I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?Wow, absolutely :) -- /Jacob Carlborg
Aug 29 2016
Am Tue, 30 Aug 2016 08:57:25 +0200 schrieb Jacob Carlborg <doob me.com>:On 2016-08-29 10:39, Stefan Koch wrote:There are some nice use cases for this: * Do not enforce nogc for CTFE only functions, so you can mark a complete module nogc: and CTFE only functions will get ignored * Do not emit code for CTFE only functions. This is useful for bare metal programming: The CTFE only function can depend on druntime functions not available in the bare metal runtime. These are common problems when using string mixins: The functions to generate the mixed in code use string manipulation which is usually not nogc and might require runtime functions. But the code generation function is exclusively used in CTFE.Thanks guys. I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?Wow, absolutely :)
Aug 30 2016
On Tuesday, 30 August 2016 at 08:18:47 UTC, Johannes Pfau wrote:There are some nice use cases for this: * Do not enforce nogc for CTFE only functions, so you can mark a complete module nogc: and CTFE only functions will get ignored * Do not emit code for CTFE only functions. This is useful for bare metal programming: The CTFE only function can depend on druntime functions not available in the bare metal runtime. These are common problems when using string mixins: The functions to generate the mixed in code use string manipulation which is usually not nogc and might require runtime functions. But the code generation function is exclusively used in CTFE.I do not see how this could affect nogc. But yes you can circumvent the code-generation and pulling in the druntime dependency using a static if.
Aug 30 2016
On Tue, Aug 30, 2016 at 10:35 AM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:[snip] But yes you can circumvent the code-generation and pulling in the druntime dependency using a static if.That will be awesome!
Aug 30 2016
Am Tue, 30 Aug 2016 08:35:20 +0000 schrieb Stefan Koch <uplink.coder googlemail.com>:I do not see how this could affect nogc.nogc is only meaningful at runtime. So this could work: module foo; nogc: [...] string ctfeOnly(string name) { static assert(!__ctfe); // error: cannot use operator ~ in nogc function return "int " ~ name ~ ";"; } mixin(ctfeOnly("foo"));
Aug 30 2016
Am Tue, 30 Aug 2016 12:42:35 +0200 schrieb Johannes Pfau <nospam example.com>:nogc is only meaningful at runtime. So this could work: module foo; nogc: [...] string ctfeOnly(string name) { static assert(!__ctfe);This should be static assert(__ctfe); of course.
Aug 30 2016
On Monday, 29 August 2016 at 08:39:56 UTC, Stefan Koch wrote:On Monday, 29 August 2016 at 08:05:10 UTC, Rory McGuire wrote:I would say maybe, but let's keep separate things separate. This is a language change. I would not include it in the same series of patch that change CTFE behavior.On Mon, Aug 29, 2016 at 9:51 AM, Dominikus Dittes Scherkl viaThanks guys. I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?The work you are doing is just awesome! Many thanks.+1 your work is key for our success as a community. R
Aug 30 2016
On Tuesday, 30 August 2016 at 17:29:19 UTC, deadalnix wrote: worth trying to get it into master ?I would say maybe, but let's keep separate things separate. This is a language change. I would not include it in the same series of patch that change CTFE behavior.Yes. It would be confusing. And it is not done with the patch I mentioned.
Aug 30 2016
On Monday, 29 August 2016 at 08:39:56 UTC, Stefan Koch wrote:I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?Yes, please. I've often wished I could use `__ctfe` in a `static if`.
Aug 30 2016
On Tuesday, 30 August 2016 at 22:01:45 UTC, tsbockman wrote:On Monday, 29 August 2016 at 08:39:56 UTC, Stefan Koch wrote:Sorry. It I overlooked a something rather important. static __ctfe is currently not possible and it's rather expensive to make it possible.I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?Yes, please. I've often wished I could use `__ctfe` in a `static if`.
Aug 31 2016
On Wed, Aug 31, 2016 at 10:43 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Tuesday, 30 August 2016 at 22:01:45 UTC, tsbockman wrote:Surely changing the current implementation slightly could still work if we made a library implementation like: ======== // ? module std.exception.enforce_ctfe; void main() { ctfefunc(); } string ctfefunc() { static if (assertCTFE!true) { throw new Exception("asdf"); } return `import std.stdio; writeln("ctfe generated this");`; } template assertCTFE(bool b) { enum assertCTFE = __traits(compiles, _checkCTFE()); } void _checkCTFE() { import std.uuid; enum id = new UUID("8AB3060E-2cba-4f23-b74c-b52db3bdfb46"); } the _checkCTFE() function is just a function that does something we're not allowed to do at CTFE, but current implementation does not respect __traits(compiles, ....); As far as I can tell that is a bug. Thoughts?On Monday, 29 August 2016 at 08:39:56 UTC, Stefan Koch wrote:Sorry. It I overlooked a something rather important. static __ctfe is currently not possible and it's rather expensive to make it possible.I just came up with a nifty little patch that makes it possible to ensure that a function is _only_ used at ctfe. Or the opposite. static assert(__ctfe, "This function is not supposed to be called outside of ctfe"); and static assert(!__ctfe, "This function is not supposed to be called during ctfe"); similarly you can use static if (__ctfe). Is it worth trying to get it into master ?Yes, please. I've often wished I could use `__ctfe` in a `static if`.
Sep 01 2016
On Thursday, 1 September 2016 at 13:18:18 UTC, Rory McGuire wrote:the _checkCTFE() function is just a function that does something we're not allowed to do at CTFE, but current implementation does not respect __traits(compiles, ....); As far as I can tell that is a bug. Thoughts?It is not a bug, because there is no way to mark something as CTFE-only. static ifs are not visible at the time where ctfe sees the function, they have already been resolved. getting a static if (__ctfe) to work would require significant changes to the semantic-analysis path for functions.
Sep 01 2016
On Thu, Sep 1, 2016 at 6:29 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Thursday, 1 September 2016 at 13:18:18 UTC, Rory McGuire wrote:Ah, right, understood. is that in one of the "semantic" passes the compiler has?the _checkCTFE() function is just a function that does something we're not allowed to do at CTFE, but current implementation does not respect __traits(compiles, ....); As far as I can tell that is a bug. Thoughts?It is not a bug, because there is no way to mark something as CTFE-only. static ifs are not visible at the time where ctfe sees the function, they have already been resolved. getting a static if (__ctfe) to work would require significant changes to the semantic-analysis path for functions.
Sep 01 2016
On Thursday, 1 September 2016 at 16:43:53 UTC, Rory McGuire wrote:is that in one of the "semantic" passes the compiler has?For reference, I've laid out the reasons why this proposal couldn't work to Stefan here: https://github.com/dlang/dmd/pull/6098#issuecomment-243375543 The real reason is not so much in the pass structure of the compiler as in the fact that CTFE by definition executes the same function body that is also emitted to the runtime binary. — David
Sep 01 2016
On Thu, Sep 1, 2016 at 9:09 PM, David Nadlinger via Digitalmars-d-announce = < digitalmars-d-announce puremagic.com> wrote:On Thursday, 1 September 2016 at 16:43:53 UTC, Rory McGuire wrote:nis that in one of the "semantic" passes the compiler has?For reference, I've laid out the reasons why this proposal couldn't work to Stefan here: https://github.com/dlang/dmd/p ull/6098#issuecomment-243375543 The real reason is not so much in the pass structure of the compiler as i=the fact that CTFE by definition executes the same function body that is also emitted to the runtime binary. =E2=80=94 Davidokay thanks, I'll take a look at the link. Question: if the function runs the same, why can't I catch the exception?From what Stefan said even if I could catch the exception static if stillwouldn't compile different code. bool _checkCTFE() { try { import std.uuid; enum id =3D new UUID("8AB3060E-2cba-4f23-b74c-b52db3bdfb46"); return false; } catch (Throwable t) { return true; } } The above still fails during CTFE, compiler just exists with: enforceCTFE.d(20): Error: variable enforceCTFE._checkCTFE.id : Unable to initialize enum with class or pointer to struct. Use static const variable instead. So why can't we even catch the Error during CTFE, that would at least help somewhat. At the moment I just have a verbose logging mode with pragma(msg) for my CTFE stuff.
Sep 01 2016
On Thursday, 1 September 2016 at 19:27:17 UTC, Rory McGuire wrote:So why can't we even catch the Error during CTFE, that would at least help somewhat.You are mixing up runtime exceptions ("throw …") with compiler errors (missing a semicolon). dm.D.learn should be able to help clear that up. — David
Sep 01 2016
On 01 Sep 2016 21:36, "David Nadlinger via Digitalmars-d-announce" < digitalmars-d-announce puremagic.com> wrote:On Thursday, 1 September 2016 at 19:27:17 UTC, Rory McGuire wrote:help somewhat.So why can't we even catch the Error during CTFE, that would at leastYou are mixing up runtime exceptions ("throw =E2=80=A6") with compiler er=rors (missing a semicolon). dm.D.learn should be able to help clear that up.=E2=80=94 DavidI'm actually asking why we can't catch the ctfe error. It's quite obvious that it is a temporary limitation of ctfe, there have been many limitations removed over the years. Surely the ctfe engine could be changed to catch unsupported code errors. (Not invalid, just unsupported at CT). The ctfe engine would have to "go past" the try anyway, right? This is the part I don't understand. Is it because ctfe actually hasn't started yet and some other analysis is freaking out?
Sep 01 2016
On Thursday, 1 September 2016 at 21:01:46 UTC, Rory McGuire wrote:I'm actually asking why we can't catch the ctfe error.You can, by using __traits(compiles, …).Surely the ctfe engine could be changed to catch unsupported code errors. (Not invalid, just unsupported at CT).It already does, see above. How is this related to try/catch? — David
Sep 01 2016
On Thu, Sep 1, 2016 at 11:05 PM, David Nadlinger via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> wrote:On Thursday, 1 September 2016 at 21:01:46 UTC, Rory McGuire wrote:I was hoping that the error was coming from the CTFE engine as it ran the code, but it comes up before ctfe execution I guess. __traits(compiles, _some_function_that_calls_), thinks that the invalid code compiles even when it doesn't compile, e.g.: template assertCTFE(bool b) { enum assertCTFE =3D __traits(compiles, _checkCTFE1()); } void _checkCTFE1() { static if (__ctfe) { // this still stops compilation (probably because this is checked before __traits(compiled ...) is evaluated } }I'm actually asking why we can't catch the ctfe error.You can, by using __traits(compiles, =E2=80=A6). Surely the ctfe engine could be changed to catch unsupported code errors.(Not invalid, just unsupported at CT).It already does, see above. How is this related to try/catch? =E2=80=94 David
Sep 01 2016
On Thursday, 1 September 2016 at 21:48:41 UTC, Rory McGuire wrote:I was hoping that the error was coming from the CTFE engine as it ran the code, but it comes up before ctfe execution I guess.As a general comment, there is no such thing as a CTFE phase. It is performed in-line with other semantic analysis as required.__traits(compiles, _some_function_that_calls_), thinks that the invalid code compiles even when it doesn't compile […]No, you are missing the point. This: --- void foo() { } --- will always cause a compiler error, regardless of whether there is a `__traits(compiles, foo())` somewhere else in the module. __traits(compiles, …) only applies to its argument and doesn't magically cause errors in code somewhere else to be ignored. — David
Sep 01 2016
On 09/01/2016 11:01 PM, Rory McGuire via Digitalmars-d-announce wrote:I'm actually asking why we can't catch the ctfe error.There is no CTFE error in your example. It doesn't compile in the first place, even without attempting any CTFE. [...]Surely the ctfe engine could be changed to catch unsupported code errors. (Not invalid, just unsupported at CT).Maybe. It isn't obvious to me that it would be a good idea, but it's not obviously terrible either.The ctfe engine would have to "go past" the try anyway, right? This is the part I don't understand. Is it because ctfe actually hasn't started yet and some other analysis is freaking out?It's just a compiler error. The snippet on its own fails compilation and there is no CTFE in there. Something like `static assert(_checkCTFE());` would involve CTFE. But that's not needed to trigger the error.
Sep 01 2016
On Thu, Sep 1, 2016 at 11:26 PM, ag0aep6g via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On 09/01/2016 11:01 PM, Rory McGuire via Digitalmars-d-announce wrote:Yeah, I'm using an enum to force the evaluation during CT, and its dying before CTFE from what I can tell. Here is another example: void main() { enum ret = ctfefunc(); mixin(ret); } string ctfefunc() { static if (!assertCTFE!true) { throw new Exception("Only during ctfe please..."); } return `import std.stdio; writeln("ctfe generated this");`; } template assertCTFE(bool b) { enum assertCTFE = __traits(compiles, _checkCTFE1()); } void _checkCTFE1() { static if (__ctfe) { } }I'm actually asking why we can't catch the ctfe error.There is no CTFE error in your example. It doesn't compile in the first place, even without attempting any CTFE. [...]Surely the ctfe engine could be changed to catch unsupported code errors. (Not invalid, just unsupported at CT).Maybe. It isn't obvious to me that it would be a good idea, but it's not obviously terrible either. The ctfe engine would have to "go past" the try anyway, right? This isthe part I don't understand. Is it because ctfe actually hasn't started yet and some other analysis is freaking out?It's just a compiler error. The snippet on its own fails compilation and there is no CTFE in there. Something like `static assert(_checkCTFE());` would involve CTFE. But that's not needed to trigger the error.
Sep 01 2016
On 09/01/2016 11:51 PM, Rory McGuire via Digitalmars-d-announce wrote:Yeah, I'm using an enum to force the evaluation during CT,I had missed that detail. Still, the error seems to be independent of any CTFE that's going on. [...]Here is another example: void main() { enum ret = ctfefunc(); mixin(ret); } string ctfefunc() { static if (!assertCTFE!true) { throw new Exception("Only during ctfe please..."); } return `import std.stdio; writeln("ctfe generated this");`; } template assertCTFE(bool b) { enum assertCTFE = __traits(compiles, _checkCTFE1()); } void _checkCTFE1() { static if (__ctfe) { } }It's not clear to me what this example is supposed to show. In particular, how does it relate to catching CTFE errors? Obviously, `static if (__ctfe)` doesn't compile right now, so _checkCTFE1 must be rejected regardless of anything else. And with _checkCTFE1, the whole program goes down. Your code looks like it's supposed to throw an exception when ctfefunc is called during normal run-time instead of CTFE. That can be done: ---- string ctfefunc() { if (!__ctfe) throw new Exception("Only during ctfe please..."); return `import std.stdio; writeln("ctfe generated this");`; } ---- But I feel like that's missing the point of the example.
Sep 01 2016
FunctionCall support is done. (with a lot of room for improvement) you can already return strings. now I just have to finish string-comparison and string-concat support to make it usable. And of course the correct translation of logical-expressions...
Sep 05 2016
On Mon, Sep 5, 2016 at 1:39 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:FunctionCall support is done. (with a lot of room for improvement) you can already return strings. now I just have to finish string-comparison and string-concat support to make it usable. And of course the correct translation of logical-expressions...Great news! Any chance you post the commit link in your announcements? Would be really interested in being able to do a quick scan of what changed. For that latest commit I just see the below. Is this all the changes? :) what does it mean? (you replaced the old ctfe for functions with your new one?) % git show 4ba35de160cdb82bb289ad2860cf5163e1636ab5 commit 4ba35de160cdb82bb289ad2860cf5163e1636ab5 Author: Stefan Koch <Uplink.Coder googlemail.com> Date: Mon Sep 5 13:35:26 2016 +0200 hack in ability to do function calls diff --git a/src/ctfe_bc.d b/src/ctfe_bc.d index 2e9d0fa..a96d37c 100644 --- a/src/ctfe_bc.d +++ b/src/ctfe_bc.d -143,6 +143,7 else static if (UsePrinterBackend) else { import ddmd.ctfe.bc; +import ddmd.dinterpret; alias BCGenT = BCGen; -2252,6 +2253,10 public: IGaveUp = true; return; } + import ddmd.dinterpret; + ctfeInterpret(ce).accept(this); + return ; + /* auto fn = _sharedCtfeState.getFunctionIndex(ce.f); if (!fn) { -2296,6 +2301,8 public: assert(0, "Could not gen Function: " ~ ce.f.toString); IGaveUp = true; } + */ + } override void visit(ReturnStatement rs) BTW: thanks for all the work!
Sep 05 2016
On Monday, 5 September 2016 at 13:13:03 UTC, Rory McGuire wrote:Great news! Any chance you post the commit link in your announcements? Would be really interested in being able to do a quick scan of what changed.At the moment writing a change-log would be tedious busywork since everything changes all the time.For that latest commit I just see the below. Is this all the changes? :) what does it mean? (you replaced the old ctfe for functions with your new one?)Yes and no, I did not replace the old ctfe I merely placed myself in front of it. Therefore I can leverage the existing mechanism for calls. And replace a function call by the expression it yields. For certain kind of function-calls (Those that change visible state) This is going to fail or produce incorrect code. But I am working on it :)
Sep 05 2016
compiling parts of phobos does no longer crash the new engine. However it still produces incorrect byte-code :)
Sep 08 2016
On Thursday, 8 September 2016 at 10:44:55 UTC, Stefan Koch wrote:compiling parts of phobos does no longer crash the new engine. However it still produces incorrect byte-code :)I think I have taken care of the incorrect bytecode. It was not an issue with the engine itself but rather with the way I plugged it in. The new engine is not supposed being called if the old one has already started to interpret the function, because the two do not and should not share state.
Sep 08 2016
On Thu, Sep 8, 2016 at 3:11 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Thursday, 8 September 2016 at 10:44:55 UTC, Stefan Koch wrote:!! Does this mean I can start testing new ctfe and only some of my CT will be faster?compiling parts of phobos does no longer crash the new engine. However it still produces incorrect byte-code :)I think I have taken care of the incorrect bytecode. It was not an issue with the engine itself but rather with the way I plugged it in. The new engine is not supposed being called if the old one has already started to interpret the function, because the two do not and should not share state.
Sep 08 2016
On Thursday, 8 September 2016 at 14:48:25 UTC, Rory McGuire wrote:On Thu, Sep 8, 2016 at 3:11 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:You can start yes. However it is very limited right now I would expect it to slow you down by a little bit.On Thursday, 8 September 2016 at 10:44:55 UTC, Stefan Koch wrote:!! Does this mean I can start testing new ctfe and only some of my CT will be faster?compiling parts of phobos does no longer crash the new engine. However it still produces incorrect byte-code :)I think I have taken care of the incorrect bytecode. It was not an issue with the engine itself but rather with the way I plugged it in. The new engine is not supposed being called if the old one has already started to interpret the function, because the two do not and should not share state.
Sep 08 2016
On Thursday, 8 September 2016 at 13:11:23 UTC, Stefan Koch wrote:On Thursday, 8 September 2016 at 10:44:55 UTC, Stefan Koch wrote:I found more incorrect code. this time it's located more deeply in the engine. I am investigating the cause. It seems to be related closures somehow.compiling parts of phobos does no longer crash the new engine. However it still produces incorrect byte-code :)I think I have taken care of the incorrect bytecode. It was not an issue with the engine itself but rather with the way I plugged it in. The new engine is not supposed being called if the old one has already started to interpret the function, because the two do not and should not share state.
Sep 08 2016
On Thursday, 8 September 2016 at 18:54:52 UTC, Stefan Koch wrote:On Thursday, 8 September 2016 at 13:11:23 UTC, Stefan Koch wrote:Compiling all of phobos does not crash my engine anymore! However running the unittests does show incorrect results :( This is concerning since I am mostly bailing out. I think this too seems to be related to closures produced in templates. Really nasty stuff.On Thursday, 8 September 2016 at 10:44:55 UTC, Stefan Koch wrote:I found more incorrect code. this time it's located more deeply in the engine. I am investigating the cause. It seems to be related closures somehow.compiling parts of phobos does no longer crash the new engine. However it still produces incorrect byte-code :)I think I have taken care of the incorrect bytecode. It was not an issue with the engine itself but rather with the way I plugged it in. The new engine is not supposed being called if the old one has already started to interpret the function, because the two do not and should not share state.
Sep 19 2016
On Monday, 19 September 2016 at 10:07:06 UTC, Stefan Koch wrote:Compiling all of phobos does not crash my engine anymore! However running the unittests does show incorrect results :( This is concerning since I am mostly bailing out. I think this too seems to be related to closures produced in templates. Really nasty stuff.Good news anyway! Do you have any preliminary results or goals and expectations that you are going to achieve with your rework? Is it mostly perf/memory improvements, are there any new features that this rework will unlock? Thanks for your hard work!
Sep 19 2016
On Monday, 19 September 2016 at 18:05:34 UTC, Lurker wrote:Good news anyway! Do you have any preliminary results or goals and expectations that you are going to achieve with your rework? Is it mostly perf/memory improvements, are there any new features that this rework will unlock? Thanks for your hard work!I stated my expectations earlier I think there will be a 2-6x performance increase in the non-jited version and around 10-14x for the jit. My preliminary results do support that claim. As for new features I do not plan on doing language-changes as I do not have the ability to anticipate the outcome of doing so. My work will probably have side-effects on the rest of dmd, for example the AST is hard to work with in some cases. I would to add like some support for frontend-optimisations as well. I will also improve documentation in some areas and hope to lower the entry-barrier for dmd-development.
Sep 19 2016
On Monday, 19 September 2016 at 10:07:06 UTC, Stefan Koch wrote:Compiling all of phobos does not crash my engine anymore!Great work! Keep up still!
Sep 19 2016
On Tuesday, 20 September 2016 at 05:06:57 UTC, Nordlöw wrote:On Monday, 19 September 2016 at 10:07:06 UTC, Stefan Koch wrote:I am proud to announce, (and slightly embarssed because it took to long) that the following code can now be executed using the new CTFE engine : string fn(bool b) { return b ? "true" : "false"; } static assert(fn(true) == "true"); static assert(fn(false) == "false"); although this seems trivial it took me about 3 months to get to this point. I believe from here on the road will be less steep.Compiling all of phobos does not crash my engine anymore!Great work! Keep up still!
Sep 25 2016
On Sun, Sep 25, 2016 at 4:47 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Tuesday, 20 September 2016 at 05:06:57 UTC, Nordl=C3=B6w wrote:t.On Monday, 19 September 2016 at 10:07:06 UTC, Stefan Koch wrote:I am proud to announce, (and slightly embarssed because it took to long) that the following code can now be executed using the new CTFE engine : string fn(bool b) { return b ? "true" : "false"; } static assert(fn(true) =3D=3D "true"); static assert(fn(false) =3D=3D "false"); although this seems trivial it took me about 3 months to get to this poin=Compiling all of phobos does not crash my engine anymore!Great work! Keep up still!I believe from here on the road will be less steep.:D congrats!
Sep 25 2016
On Sunday, 25 September 2016 at 18:21:27 UTC, Rory McGuire wrote::D congrats!I appreciate it. If all goes well there will be a separate nightly release build from the newCTFE branch, sometime in October. I hope to get alpha bug reports that way. Also I am now starting experimentation with actual JIT to make sure my API and ABI definitions are not bogus. (For the record an earlier design made slices impossible) Luckily I spotted this before I went to far with it. Unfortunately many basic features are still very brittle or completely dysfunctional. (Such as function calls or structs.) Again I apologize for the delay. My adventures in template-land, were quite time consuming. Although arguably with interesting results. If you have any questions regarding my work with the DMD, please ask away. Greetings, Stefan
Sep 25 2016
On Sun, Sep 25, 2016 at 10:47 PM, Stefan Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Sunday, 25 September 2016 at 18:21:27 UTC, Rory McGuire wrote:No worries, I've been watching this space for over a decade. I really believe you are working on one of the most important parts of IT for the next decade. I am planning/making a library that uses CTFE extensively and feel much more confident about it purely because of your work on getting CTFE performance to be a non-issue. R:D congrats!I appreciate it. If all goes well there will be a separate nightly release build from the newCTFE branch, sometime in October. I hope to get alpha bug reports that way. Also I am now starting experimentation with actual JIT to make sure my API and ABI definitions are not bogus. (For the record an earlier design made slices impossible) Luckily I spotted this before I went to far with it. Unfortunately many basic features are still very brittle or completely dysfunctional. (Such as function calls or structs.) Again I apologize for the delay. My adventures in template-land, were quite time consuming. Although arguably with interesting results. If you have any questions regarding my work with the DMD, please ask away. Greetings, Stefan
Oct 05 2016
On Wednesday, 5 October 2016 at 08:34:06 UTC, Rory McGuire wrote:No worries, I've been watching this space for over a decade. I really believe you are working on one of the most important parts of IT for the next decade. I am planning/making a library that uses CTFE extensively and feel much more confident about it purely because of your work on getting CTFE performance to be a non-issue. RLittle update here: The LLVM backend is almost on feature parity. Meaning that that soon the new CTFE engine is a real jit. In the process I discoverd quite a few horrible bugs and inconsistency in the API. I am quite astonished that it ever ran before :)
Oct 15 2016
On 10/16/16 2:27 AM, Uplink_Coder wrote:On Wednesday, 5 October 2016 at 08:34:06 UTC, Rory McGuire wrote:That LLVM thing is surely nice to have but I highly doubt it will be allowed as dependency for DMD. --- Dmitry OlshanskyNo worries, I've been watching this space for over a decade. I really believe you are working on one of the most important parts of IT for the next decade. I am planning/making a library that uses CTFE extensively and feel much more confident about it purely because of your work on getting CTFE performance to be a non-issue. RLittle update here: The LLVM backend is almost on feature parity. Meaning that that soon the new CTFE engine is a real jit. In the process I discoverd quite a few horrible bugs and inconsistency in the API. I am quite astonished that it ever ran before :)
Oct 16 2016
On Sunday, 16 October 2016 at 10:58:57 UTC, Dmitry Olshansky wrote:That LLVM thing is surely nice to have but I highly doubt it will be allowed as dependency for DMD. --- Dmitry OlshanskyLLVM is purely optional. A pure D interpreter exists. LLVM optimises most ctfe btw and returns constants.
Oct 16 2016
On Sunday, 16 October 2016 at 13:51:55 UTC, Uplink_Coder wrote:On Sunday, 16 October 2016 at 10:58:57 UTC, Dmitry Olshansky wrote:If anyone want to take a look the lastest llvm_backend development is happening here : https://github.com/UplinkCoder/dmd/blob/_ctfe/src/bc_llvm_backend.dThat LLVM thing is surely nice to have but I highly doubt it will be allowed as dependency for DMD. --- Dmitry OlshanskyLLVM is purely optional. A pure D interpreter exists. LLVM optimises most ctfe btw and returns constants.
Oct 16 2016
On Monday, 17 October 2016 at 00:56:01 UTC, Uplink_Coder wrote:If anyone want to take a look the lastest llvm_backend development is happening here : https://github.com/UplinkCoder/dmd/blob/_ctfe/src/bc_llvm_backend.dThe time llvm takes to build it's IR and execute the JITed code is absolutely too much! multiple milliseconds! I will write a very simple x86 codegenerator tomorrow.
Oct 17 2016
On Monday, 17 October 2016 at 15:50:37 UTC, Uplink_Coder wrote:The time llvm takes to build it's IR and execute the JITed code is absolutely too much! multiple milliseconds! I will write a very simple x86 codegenerator tomorrow.Great work.
Oct 17 2016
On Sunday, 16 October 2016 at 00:27:50 UTC, Uplink_Coder wrote:Little update here: The LLVM backend is almost on feature parity. Meaning that that soon the new CTFE engine is a real jit. In the process I discoverd quite a few horrible bugs and inconsistency in the API. I am quite astonished that it ever ran before :)Hey Guys, I am still dealing with the many bugs that have surfaced. It is really crazy how something so broken could have worked that well. Originally I planned adding a ton of features, but that can only happen If the fundamental issues are fixed.
Oct 23 2016
On Monday, 24 October 2016 at 05:57:42 UTC, Stefam Koch wrote:On Sunday, 16 October 2016 at 00:27:50 UTC, Uplink_Coder wrote:However at the D Meetup in Berlin, I have gotten some positive feedback concerning my ByteCode-Layer. Once the bugs are fixed and the edges are smoothed over I can see finding it's way into other parts of the compiler.Little update here: The LLVM backend is almost on feature parity. Meaning that that soon the new CTFE engine is a real jit. In the process I discoverd quite a few horrible bugs and inconsistency in the API. I am quite astonished that it ever ran before :)Hey Guys, I am still dealing with the many bugs that have surfaced. It is really crazy how something so broken could have worked that well. Originally I planned adding a ton of features, but that can only happen If the fundamental issues are fixed.
Oct 23 2016
On Mon, Oct 24, 2016 at 8:17 AM, Stefam Koch via Digitalmars-d-announce < digitalmars-d-announce puremagic.com> wrote:On Monday, 24 October 2016 at 05:57:42 UTC, Stefam Koch wrote:So true of computer programming. Particularly if the documentation for the API is awol.On Sunday, 16 October 2016 at 00:27:50 UTC, Uplink_Coder wrote:Little update here: The LLVM backend is almost on feature parity. Meaning that that soon the new CTFE engine is a real jit. In the process I discoverd quite a few horrible bugs and inconsistency in the API. I am quite astonished that it ever ran before :)Hey Guys, I am still dealing with the many bugs that have surfaced. It is really crazy how something so broken could have worked that well.Cool, thanks for the feedback.Originally I planned adding a ton of features, but that can only happen If the fundamental issues are fixed.However at the D Meetup in Berlin, I have gotten some positive feedback concerning my ByteCode-Layer. Once the bugs are fixed and the edges are smoothed over I can see finding it's way into other parts of the compiler.
Oct 23 2016
On Monday, 24 October 2016 at 06:37:12 UTC, Rory McGuire wrote:Cool, thanks for the feedback.I have take care of the blocker for now. I turns out my tests contained wrong code that reused a register for multiple purposes. LLVM does not like that. So it assumed the wrong things while optimising and went into the wrong direction makeing complete bogus out of valid code.
Oct 25 2016
On Tuesday, 25 October 2016 at 09:36:12 UTC, Stefam Koch wrote:On Monday, 24 October 2016 at 06:37:12 UTC, Rory McGuire wrote:First perf data is in The is measured with time src/dmd -c -ctfe-bc old interpreter (without -ctfe-bc) : real 0m6.839s user 0m6.423s sys 0m0.407s new interpreter (-ctfe-bc) real 0m0.549s user 0m0.547s sys 0m0.000s LLVM Backend (-ctfe-bc -version=UseLLVMBackend) : real 0m0.039s user 0m0.027s sys 0m0.010s The compiled code was : int bug6498(int x) { int n = 0; while (n < x) ++n; return n; } static assert(bug6498(10_000_000)==10_000_000);Cool, thanks for the feedback.I have take care of the blocker for now. I turns out my tests contained wrong code that reused a register for multiple purposes. LLVM does not like that. So it assumed the wrong things while optimising and went into the wrong direction makeing complete bogus out of valid code.
Oct 25 2016
On Tuesday, 25 October 2016 at 12:36:56 UTC, Stefam Koch wrote:LLVM Backend (-ctfe-bc -version=UseLLVMBackend) : real 0m0.039s user 0m0.027s sys 0m0.010sI think 20,000% is a pretty good speedup! ;) Great stuff. Now that JIT works, are you returning to focusing on feature coverage? -Wyatt
Oct 25 2016
On Tuesday, 25 October 2016 at 15:57:33 UTC, Wyatt wrote:On Tuesday, 25 October 2016 at 12:36:56 UTC, Stefam Koch wrote:Yes I have already started on solidifying struct, string and slice support. Once this is done, most of the ctfe system is in place. The rest will be costmetics. Make no mistake structs and slices may seem trivial but there are a few complxities hiding involved. Particularly handling of the this pointer and accsess to member-variables. Slices require a proper memory mangament system to be in place. All of this needs to be platform agnostic and representable in bytecode.LLVM Backend (-ctfe-bc -version=UseLLVMBackend) : real 0m0.039s user 0m0.027s sys 0m0.010sI think 20,000% is a pretty good speedup! ;) Great stuff. Now that JIT works, are you returning to focusing on feature coverage? -Wyatt
Oct 25 2016
On 2016-10-25 14:36, Stefam Koch wrote:First perf data is in The is measured with time src/dmd -c -ctfe-bc old interpreter (without -ctfe-bc) : real 0m6.839s user 0m6.423s sys 0m0.407s new interpreter (-ctfe-bc) real 0m0.549s user 0m0.547s sys 0m0.000s LLVM Backend (-ctfe-bc -version=UseLLVMBackend) : real 0m0.039s user 0m0.027s sys 0m0.010s The compiled code was : int bug6498(int x) { int n = 0; while (n < x) ++n; return n; } static assert(bug6498(10_000_000)==10_000_000);Very impressive :) -- /Jacob Carlborg
Oct 25 2016
On Tuesday, 25 October 2016 at 17:19:26 UTC, Jacob Carlborg wrote:Very impressive :)Thanks. I just got the following code to compile and execute correctly. bool strEq(string a, string b) { if (a.length != b.length) { return false; } uint length = cast(uint) a.length; while(length--) { auto c1 = a[length]; auto c2 = b[length]; if (c1 != c2) { return false; } } return true; } static assert(!strEq("Hello","World")); static assert(strEq("World","World")); I used the generated bytecode to make == for strings work.
Oct 25 2016
On Wednesday, 26 October 2016 at 03:58:05 UTC, Stefam Koch wrote:On Tuesday, 25 October 2016 at 17:19:26 UTC, Jacob Carlborg wrote:Why did you cast size_t to uint in this example?Very impressive :)Thanks. I just got the following code to compile and execute correctly. bool strEq(string a, string b) { if (a.length != b.length) { return false; } uint length = cast(uint) a.length; while(length--) { auto c1 = a[length]; auto c2 = b[length]; if (c1 != c2) { return false; } } return true; } static assert(!strEq("Hello","World")); static assert(strEq("World","World")); I used the generated bytecode to make == for strings work.
Oct 26 2016
On Wednesday, 26 October 2016 at 08:19:46 UTC, Andrea Fontana wrote:On Wednesday, 26 October 2016 at 03:58:05 UTC, Stefam Koch wrote:Currently I am limited to 32bit Arithmetic. Changing this is on the Table but I have not gotten to it yet.On Tuesday, 25 October 2016 at 17:19:26 UTC, Jacob Carlborg wrote:Why did you cast size_t to uint in this example?Very impressive :)Thanks. I just got the following code to compile and execute correctly. bool strEq(string a, string b) { if (a.length != b.length) { return false; } uint length = cast(uint) a.length; while(length--) { auto c1 = a[length]; auto c2 = b[length]; if (c1 != c2) { return false; } } return true; } static assert(!strEq("Hello","World")); static assert(strEq("World","World")); I used the generated bytecode to make == for strings work.
Oct 26 2016
Who can guess what this code does ? char[] obfuscatedFn(string a, string b, uint aLength = 0, uint bLength = 0, uint cLength = 0, uint pos = 0, uint bPos = 0, char[] result = []) { aLength = cast(uint)a.length; bLength = cast(uint)a.length; cLength = aLength + bLength; result.length = cLength; while(aLength--) { result[pos] = a[pos]; ++pos; } while(bLength--) { result[pos] = b[bPos++]; ++pos; } return result; }
Oct 26 2016
On Wednesday, 26 October 2016 at 15:02:28 UTC, Stefam Koch wrote:bLength = cast(uint)a.length;Reads past the end of b if b is shorter than a.
Oct 26 2016
On Wednesday, 26 October 2016 at 15:38:30 UTC, Kagamin wrote:On Wednesday, 26 October 2016 at 15:02:28 UTC, Stefam Koch wrote:you are right. Thanks for spotting it :)bLength = cast(uint)a.length;Reads past the end of b if b is shorter than a.
Oct 26 2016
On Wednesday, 26 October 2016 at 15:02:28 UTC, Stefam Koch wrote:Who can guess what this code does ? char[] obfuscatedFn(string a, string b, uint aLength = 0, uint bLength = 0, uint cLength = 0, uint pos = 0, uint bPos = 0, char[] result = []) { aLength = cast(uint)a.length; bLength = cast(uint)a.length; cLength = aLength + bLength; result.length = cLength; while(aLength--) { result[pos] = a[pos]; ++pos; } while(bLength--) { result[pos] = b[bPos++]; ++pos; } return result; }Shouldn'tcLength = aLength + bLength;actually becLength = aLength + bLength + pos;? Otherwise when pos is > 0 it writes past the end of result. Same problem in the first and second loop, where the legths should probably beaLength = cast(uint)a.length - pos; bLength = cast(uint)a.length - bPos;If you fix the a and b Length then cLength is fine. Or am I missing something?
Oct 26 2016
On Wednesday, 26 October 2016 at 16:24:49 UTC, MakersF wrote:On Wednesday, 26 October 2016 at 15:02:28 UTC, Stefam Koch wrote:Ah the default paramters are never touched. The reason they are there is because of the way the ctfe engine lowers parameters. It's easier to create byte-code macros if all used variables are function paramters :)Who can guess what this code does ? char[] obfuscatedFn(string a, string b, uint aLength = 0, uint bLength = 0, uint cLength = 0, uint pos = 0, uint bPos = 0, char[] result = []) { aLength = cast(uint)a.length; bLength = cast(uint)a.length; cLength = aLength + bLength; result.length = cLength; while(aLength--) { result[pos] = a[pos]; ++pos; } while(bLength--) { result[pos] = b[bPos++]; ++pos; } return result; }Shouldn'tcLength = aLength + bLength;actually becLength = aLength + bLength + pos;? Otherwise when pos is > 0 it writes past the end of result. Same problem in the first and second loop, where the legths should probably beaLength = cast(uint)a.length - pos; bLength = cast(uint)a.length - bPos;If you fix the a and b Length then cLength is fine. Or am I missing something?
Oct 26 2016
Another update on CTFE. I have found a few errors in my handling of switch-statments. An efficient solution for this is still pending, Futhermore I have begun to work on ctfe handling refernces. These are a little bit harder to do in bytecode and do pessimise performance if overused. I hope to make another leap at the end of this month. We should have string Concat-support fairly soon. Cheers, stefan
Oct 28 2016
On Friday, 28 October 2016 at 16:52:46 UTC, Stefan Koch wrote:Another update on CTFE. I have found a few errors in my handling of switch-statments. An efficient solution for this is still pending, Futhermore I have begun to work on ctfe handling refernces. These are a little bit harder to do in bytecode and do pessimise performance if overused. I hope to make another leap at the end of this month. We should have string Concat-support fairly soon. Cheers, stefanI just made progress on another fundamental feature, function call support. It's does not work yet, but it shows promise.
Oct 29 2016
On Sunday, 30 October 2016 at 03:07:13 UTC, Stefan Koch wrote:I just made progress on another fundamental feature, function call support. It's does not [fully] work yet, but it shows promise.The following just compiled : int fn(int a) { return a + fn2(2); } int fn2(int a) { return a + 2; } static assert(fn2(4) == 6); static assert(fn(4) == 8); static assert(fn(fn(2)) == 10);
Oct 30 2016
On Sunday, 30 October 2016 at 21:09:19 UTC, Stefan Koch wrote:On Sunday, 30 October 2016 at 03:07:13 UTC, Stefan Koch wrote:Oh shoot! I did not enable the new call system :( This computed by the old interpreter. The new engine fails :(I just made progress on another fundamental feature, function call support. It's does not [fully] work yet, but it shows promise.The following just compiled : int fn(int a) { return a + fn2(2); } int fn2(int a) { return a + 2; } static assert(fn2(4) == 6); static assert(fn(4) == 8); static assert(fn(fn(2)) == 10);
Oct 30 2016
protected-headers="v1" From: Dicebot <public dicebot.lv> Newsgroups: d,i,g,i,t,a,l,m,a,r,s,.,D,.,a,n,n,o,u,n,c,e Subject: Re: Battle-plan for CTFE References: <rnzxxfvmeeytnvkmwcxj forum.dlang.org> <nqa6e7$1fd7$1 digitalmars.com> <mailman.104.1472766720.2965.digitalmars-d-announce puremagic.com> <nqaa8a$1kcd$1 digitalmars.com> <qzdiqnxfdaytulaszppy forum.dlang.org> <mailman.210.1473081196.2965.digitalmars-d-announce puremagic.com> <wjwmowqkdcttntkosept forum.dlang.org> <zolwvouqhqnmmoqpxofo forum.dlang.org> <hmvfsrdobpeuqpwiufdx forum.dlang.org> <lcxgcoxtuvbujbqzqias forum.dlang.org> <yofxponrmwlanyghkjrq forum.dlang.org> <jttaymputcolwmpbgzcv forum.dlang.org> <dfgwdgajygyvjrtzhqcj forum.dlang.org> <mailman.406.1474827700.2994.digitalmars-d-announce puremagic.com> <acmqjjnecwryyzpklgjx forum.dlang.org> <mailman.902.1475656459.2994.digitalmars-d-announce puremagic.com> <uprtsdxodwsbdpoxxkpe forum.dlang.org> <qywmrwidasgvvnqpvfgf forum.dlang.org> <jmtczpvmxgxuaofxphyv forum.dlang.org> <mailman.162.1477291045.3398.digitalmars-d-announce puremagic.com> <hprtrdyiowkxconetmyp forum.dlang.org> <rwvuaudnlfwhkeavwbvu forum.dlang.org> <nuo46u$25rm$1 digitalmars.com> <vcjwcfmaqrievijciouq forum.dlang.org> <gdzaxcoiwzdaxzcrjycl forum.dlang.org> <zgxwctswlhmdbzibwjfr forum.dlang.org> <okfrlchbefeqjvesscrc forum.dlang.org> <kkfteaolhhihmkrmozcm forum.dlang.org> <eneqlnfnhcpubcbyxrdb forum.dlang.org> <caqoqagchdwiienjrwve forum.dlang.org> <ejtexhsgtzcqlijnvxuw forum.dlang.org> <citszaxzagriezhtjgrd forum.dlang.org> <sasytwhgedikcnzigvvi forum.dlang.org> In-Reply-To: <sasytwhgedikcnzigvvi forum.dlang.org> --omJ5HxNF3lN2qBjXTBoLAxqVL4WIgcBTr Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 10/30/2016 11:19 PM, Stefan Koch wrote:Oh shoot! I did not enable the new call system :( This computed by the old interpreter. =20 The new engine fails :(Stefan, would you mind creating a dedicated topic in main D newsgroup to report your development progress? Bumping the thread in announce NG like that is rather distracting, we should aim for posting only most important/relevant info there. --omJ5HxNF3lN2qBjXTBoLAxqVL4WIgcBTr--
Oct 31 2016
On Sunday, 25 September 2016 at 20:47:41 UTC, Stefan Koch wrote:If all goes well there will be a separate nightly release build from the newCTFE branch, sometime in October. I hope to get alpha bug reports that way.Have you benchmarked CTFE-heavy projects like Pegged?
Oct 19 2016
On Wednesday, 19 October 2016 at 07:11:24 UTC, Nordlöw wrote:On Sunday, 25 September 2016 at 20:47:41 UTC, Stefan Koch wrote:It is not yet able to handle pegged. And I suspect alot of slowness is caused by templates not by CTFE.If all goes well there will be a separate nightly release build from the newCTFE branch, sometime in October. I hope to get alpha bug reports that way.Have you benchmarked CTFE-heavy projects like Pegged?
Oct 19 2016
On 19 Oct 2016 17:46, "Stefan Koch via Digitalmars-d-announce" < digitalmars-d-announce puremagic.com> wrote:On Wednesday, 19 October 2016 at 07:11:24 UTC, Nordl=C3=B6w wrote:the newCTFE branch, sometime in October.On Sunday, 25 September 2016 at 20:47:41 UTC, Stefan Koch wrote:If all goes well there will be a separate nightly release build fromdiet-ng is probably a better "complex" benchmark.It is not yet able to handle pegged. And I suspect alot of slowness is caused by templates not by CTFE.I hope to get alpha bug reports that way.Have you benchmarked CTFE-heavy projects like Pegged?
Oct 19 2016
On Thursday, 1 September 2016 at 19:27:17 UTC, Rory McGuire wrote:At the moment I just have a verbose logging mode with pragma(msg) for my CTFE stuff.I have something that will help with that a little bit. https://github.com/UplinkCoder/dmd/tree/__ctfeWriteln when you apply this patch __ctfeWriteln() will output every compiletime avilable string to the console. It's a little bit nicer then using pragma(msg);
Sep 01 2016
On Thursday, 1 September 2016 at 19:38:13 UTC, Stefan Koch wrote:I have something that will help with that a little bit. https://github.com/UplinkCoder/dmd/tree/__ctfeWriteln when you apply this patch __ctfeWriteln() will output every compiletime avilable string to the console.More crucially, it also allows you to print runtime values during CTFE. pragma(msg, …) suffices to print compile-time constants. Very few people seem to have the correct mental model for the the interaction between compile-time features and CTFE, hence I think using precise terminology is an important first step. See also: https://github.com/dlang/dmd/pull/692 – it's about time we finally got __ctfeWrite() merged. — David
Sep 01 2016
On Thursday, 1 September 2016 at 20:43:16 UTC, David Nadlinger wrote:See also: https://github.com/dlang/dmd/pull/692 – it's about time we finally got __ctfeWrite() merged. — DavidOh yeah. Let me get this into PR shape.
Sep 01 2016
On Thu, Sep 01, 2016 at 08:43:16PM +0000, David Nadlinger via Digitalmars-d-announce wrote:On Thursday, 1 September 2016 at 19:38:13 UTC, Stefan Koch wrote:[...] Part of the problem is that the term "compile-time" is ambiguous. In the compilation of a D program, there are (at least) 2 distinct phases that may be termed "compile-time": (1) expansion of templates and evaluation of static-if, and (2) CTFE. Phase (1) conceptually happens before the AST is finalized, and hence at this stage it makes no sense to refer to variables and such: variables don't even exist yet because the syntax tree of the program is still being manipulated. Phase (2) happens just as the compiler is ready to emit object code: the AST has been finalized, symbols have been resolved, statements have been analysed / lowered, etc.. At this stage, static-if no longer makes any sense because the AST can no longer be manipulated at this point. Of course, the above is a simplified picture of what actually happens. In a complex D program, you *can* have phase (2) precede phase (1), e.g., using static-if on the result of a CTFE function. The important thing to note here, though, is that the CTFE function's body must already be in phase (2), because otherwise CTFE is impossible. So another part of the code can depend on the result of the CTFE function, but the function itself is already past phase (1) and you can't change its AST anymore. So you can have different parts of the program be in different phases, and they can have interdependencies, but the same piece of code can only progress from phase (1) to phase (2), and never the other way around. Referring to both phases as "compile-time" is ambiguous and causes confusion to people who are not familiar with how the compilation process actually works. T -- Windows: the ultimate triumph of marketing over technology. -- Adrian von BidderI have something that will help with that a little bit. https://github.com/UplinkCoder/dmd/tree/__ctfeWriteln when you apply this patch __ctfeWriteln() will output every compiletime avilable string to the console.More crucially, it also allows you to print runtime values during CTFE. pragma(msg, …) suffices to print compile-time constants. Very few people seem to have the correct mental model for the the interaction between compile-time features and CTFE, hence I think using precise terminology is an important first step.
Sep 01 2016
On Thursday, 1 September 2016 at 13:18:18 UTC, Rory McGuire wrote:void main() { ctfefunc(); } string ctfefunc() { static if (assertCTFE!true) { throw new Exception("asdf"); } return `import std.stdio; writeln("ctfe generated this");`; } template assertCTFE(bool b) { enum assertCTFE = __traits(compiles, _checkCTFE()); } void _checkCTFE() { import std.uuid; enum id = new UUID("8AB3060E-2cba-4f23-b74c-b52db3bdfb46"); } […] current implementation does not respect __traits(compiles, ....); As far as I can tell that is a bug. Thoughts?This doesn't do what you think it does in more than one way. If you laid out how you think it should work, I'd be happy to walk you through where it goes wrong in particular. However, as it is, the whole program would certainly fail to compile if __traits(compiles, …) were false (which it indeed is) because the module-level function _checkCTFE() couldn't then be compiled either. It's just a top-level function. There is no __traits(compiles, ....) involved in that. — David
Sep 01 2016
On Monday, 29 August 2016 at 00:24:01 UTC, Stefan Koch wrote: I feel that this can have a positiveI am happy for all comments or suggestions.Incredible work! Keep up!
Aug 29 2016
On Saturday, 6 August 2016 at 14:26:00 UTC, Stefan Koch wrote:I added a switch to my version of dmd which allows to toggle the ctfe engine. So now I can compare apples to apples when posting perf data.That's indeed very useful, also for testing purposes.
Aug 07 2016
On Friday, 29 July 2016 at 11:30:20 UTC, Stefan Koch wrote:I have fresh performance statistics:Is there any improvement in memory usage?
Jul 29 2016
On Friday, 29 July 2016 at 13:07:12 UTC, Edwin van Leeuwen wrote:On Friday, 29 July 2016 at 11:30:20 UTC, Stefan Koch wrote:Yes! There memory usage is the same as run-time execution. plus about 16k for the interpreter state.I have fresh performance statistics:Is there any improvement in memory usage?
Jul 29 2016