Invoking the compiler during runtime
D's compile-time-execution is fantastic, but there are some times when I'd like to examine the generated code, or produce code that needs to pass through earlier phases before CTFE, or do AST stuff. Sometimes I simply don't want to generate the code with every compilation, so saving the generated code in a file some would be really neat, if I could then invoke the compiler during runtime to build it. Plus backtraces wouldn't just be "dlang-mixin-397." I'm a big supporter of compiling from source and not using third party binaries, so I don't mind designing software that only works with runtime access to a D compiler. But I'm not sure how best to generate the code, or to invoke the compiler, or how to use what it compiles. In C I write a utility program in awful C to print out C code, have a cmake custom command run that awful C as needed, and assume the existence of that generated source in my main program. So is that the best way to do it? Have a side program that writes D source to a file, and then the main program simply imports the file? Or is there some AST syntax I should be generating instead? Some way to import the compiler itself, instead of calling it in a subprocess? Is there a way in dub to specify that you run a D program contained in X.d during the build process, to build Y.d, that Z.d imports?
Re: How does one run a linux system command from a D main() fcn ?
On Tuesday, 4 August 2020 at 19:52:47 UTC, Andy Balba wrote: i.e. D equivalent to C++ command system("MyExe") Apart from std.process, you can also call the C function in D after importing core.stdc.stdlib: https://dlang.org/library/core/stdc/stdlib/system.html
Re: 2-D array initialization
On Sunday, 2 August 2020 at 19:19:51 UTC, Andy Balba wrote: On Sunday, 2 August 2020 at 06:37:06 UTC, tastyminerals wrote: You haven't said anything about efficiency because if you care and your arrays are rather big, you better go with https://github.com/libmir/mir-algorithm as mentioned above. It might be a little finicky at the start but this post: https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html should get you up to speed. Keep in mind that std.array.staticArray is not efficient for large arrays. If you want to stick to standard D, I would not initialize a 2D array because it is just cumbersome but rather use a 1D array and transform it into 2D view on demand via ".chunks" method. Here is an example. import std.range; import std.array; void main() { int[] arr = 20.iota.array; auto arr2dView = arr.chunks(5); } Should give you ┌ ┐ │ 0 1 2 3 4│ │ 5 6 7 8 9│ │10 11 12 13 14│ │15 16 17 18 19│ └ ┘ whenever you need to access its elements as arr.chunks(5)[1][1 .. 3] --> [6, 7]. @ tastyminerals Thanks for your help on this. These comments, combined with the others, are making my climb of the D learning curve much quicker. I'm not a gitHub fan, but I like the mir functions; and it looks like I have to download mir before using it. mir has quite a few .d files..Is there a quick way to download it ? mir is a D package (akin to Python pip package). You can easily include it into your program by adding at the top of your file the following code: /+ dub.sdl: name "my_script" dependency "mir-algorithm" version="~>3.9.12" +/ And then just run your script with "dub my_script.d", dub will fetch the necessary dependencies, compile and run the file. However, it will not generate compiled versions of your my_script.d for that, you better set a dub project. Here, see to do it: https://tastyminerals.github.io/tasty-blog/dlang/2020/03/01/how_to_use_external_libraries_in_d_project.html
Re: How does one run a linux system command from a D main() fcn ?
On Tuesday, 4 August 2020 at 19:52:47 UTC, Andy Balba wrote: i.e. D equivalent to C++ command system("MyExe") https://dlang.org/library/std/process.html
How does one run a linux system command from a D main() fcn ?
i.e. D equivalent to C++ command system("MyExe")
Re: std.conv.ConvException from double to uint64_t, but only locally in a large project
On Tuesday, 4 August 2020 at 17:49:56 UTC, drathier wrote: Replaced all mentions of uint64_t with ulong, and now it works. Must have an enum called uint64_t defined somewhere in a library I depend on or something? Really wish this was clearer. BTW I believe the reason that `uint64_t` is an enum (which is being imported by "import std" but isn't converting) solely on macOS/iOS is for compatibility with C++ name mangling.
Re: std.conv.ConvException from double to uint64_t, but only locally in a large project
On 8/4/20 2:15 PM, Steven Schveighoffer wrote: I'll file a bug. https://issues.dlang.org/show_bug.cgi?id=21112 -Steve
Re: std.conv.ConvException from double to uint64_t, but only locally in a large project
On 8/4/20 1:36 PM, drathier wrote: I'm getting a crash when I'm converting a double to an uint64_t. ``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (1596) does not match any member value of enum '__c_ulonglong' ``` I've narrowed down the code to this: ``` static import std.conv; double thing = 42.0; std.conv.to!(uint64_t)(thing); ``` which works just fine on https://run.dlang.io/ or in a single-file dmd invocation. When I compile and run it locally on my mac as part of a specific large app using dub, it always crashes like this. Where would I even start debugging this? DMD64 D Compiler v2.093.0 DUB version 1.22.0, built on Jul 9 2020 So a common way to typedef something is to use enum: enum uint64_t : ulong; This gives you a new type that works pretty much just like ulong, but will not implicitly convert from ulong. However, std.conv.to is likely interpreting this as an enumeration type, where it has to match one of the enum members. But since this isn't an enumeration in the standard way, it fails (it has no members!) This code reproduces the problem on run.dlang.io: void main() { import core.stdc.config; import std.conv; auto x = 0.5; auto y = x.to!__c_ulonglong; } Note the code in druntime which defines __c_ulonglong: https://github.com/dlang/druntime/blob/0db2e65bba7cc319309bd32957763882870d5b03/src/core/stdc/config.d#L121 I'll file a bug. -Steve
Re: std.conv.ConvException from double to uint64_t, but only locally in a large project
Replaced all mentions of uint64_t with ulong, and now it works. Must have an enum called uint64_t defined somewhere in a library I depend on or something? Really wish this was clearer.
Re: std.conv.ConvException from double to uint64_t, but only locally in a large project
On Tuesday, 4 August 2020 at 17:37:56 UTC, drathier wrote: ``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (1596) does not match any member value of enum '__c_ulonglong' ``` well, ``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (42) does not match any member value of enum '__c_ulonglong' ``` but the specific value doesn't matter full stack trace: ``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (42) does not match any member value of enum '__c_ulonglong' source/app.d:864 @safe core.stdc.config.__c_ulonglong std.conv.toImpl!(core.stdc.config.__c_ulonglong, double).toImpl(double) [0x10fa540f8] source/app.d:864 @safe core.stdc.config.__c_ulonglong std.conv.to!(core.stdc.config.__c_ulonglong).to!(double).to(double) [0x10fa54072] source/app.d:262 int app.processFromOffset(std.socket.Socket, app.KafkerMode, app.RuntimeState, core.stdc.config.__c_ulonglong, core.stdc.config.__c_ulonglong) [0x10f9d06b5] source/app.d:175 _Dmain [0x10f9cfcae] ```
Re: std.conv.ConvException from double to uint64_t, but only locally in a large project
``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (1596) does not match any member value of enum '__c_ulonglong' ``` well, ``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (42) does not match any member value of enum '__c_ulonglong' ``` but the specific value doesn't matter
Re: D on lm32-CPU: string argument on stack instead of register
On Saturday, 1 August 2020 at 23:08:38 UTC, Chad Joan wrote: Though if the compiler is allowed to split a single uint64_t into two registers, I would expect it to split struct/string into two registers as well. At least, the manual doesn't seem to explicitly mention higher-level constructs like structs. It does suggest a one-to-one relationship between arguments and registers (up to a point), but GCC seems to have decided otherwise for certain uint64_t's. (Looking at Table 3...) It even gives you two registers for a return value: enough for a string or an array. And if the backend/ABI weren't up for it, it would be theoretically possible to have the frontend to lower strings (dynamic arrays) and small structs into their components before function calls and then also insert code on the other side to cast them back into their original form. I'm not sure if anyone would want to write it, though. o.O Right, I think at some point one should fix the backend. C programs would also benefit from it when passing structs as arguments. However in C it is more common to just pass pointers and they go into registers. I guess this is why I never noticed before that struct passing is needlessly expensive. Getting from pointer-length to string might be pretty easy: string foo = ptr[0 .. len]; Ah cool! I did know about array slicing, but wasn't aware that it works on pointers, too. It ended up being a little more complicated than I thought it would be. Hope I didn't ruin the fun. ;) https://pastebin.com/y6e9mxre Thanks :) I'll have to look into that more closely. But this is the kind of stuff that I hope to make use of in the future on the embedded CPU. But for now I cannot use it yet because I don't have phobos and druntime in my toolchain right now... just naked D. Also, that part where you mentioned a 64-bit integer being passed as a pair of registers made me start to wonder if unions could be (ab)used to juke the ABI: https://pastebin.com/eGfZN0SL Thanks for suggesting! I tried, and the union works as well, i.e. the function args are registered. But I noticed another thing about all workarounds so far: Even if calls are inlined and arguments end up on the stack, the linker puts code of the wrapper function in my final binary event if it is never explicitly called. So until I find a way to strip of uncalled functions from the binary (not sure the linker can do it), the workarounds don't solve the size problem. But they still make the code run faster.
std.conv.ConvException from double to uint64_t, but only locally in a large project
I'm getting a crash when I'm converting a double to an uint64_t. ``` std.conv.ConvException@/usr/local/opt/dmd/include/dlang/dmd/std/conv.d(2054): Value (1596) does not match any member value of enum '__c_ulonglong' ``` I've narrowed down the code to this: ``` static import std.conv; double thing = 42.0; std.conv.to!(uint64_t)(thing); ``` which works just fine on https://run.dlang.io/ or in a single-file dmd invocation. When I compile and run it locally on my mac as part of a specific large app using dub, it always crashes like this. Where would I even start debugging this? DMD64 D Compiler v2.093.0 DUB version 1.22.0, built on Jul 9 2020
Re: Template functions inside interface
On 8/4/20 9:39 AM, Adam D. Ruppe wrote: On Tuesday, 4 August 2020 at 13:36:15 UTC, Zans wrote: Is there any way to declare template functions inside interface and then override them in a class? No, the templates in the interface are automatically considered `final`. So the body must be in the interface too to avoid that undefined reference error. You can have them forward to normal methods in the interface though, just there needs to be a fixed number of them with concrete types. I was kind of surprised the compiler didn't complain about override there. Is override ever a valid attribute for a template function? Is there a reason we ignore it for templates? I can imagine a lot of confusion for something like: import std.stdio; interface MyInterface { T doAndReturnSomething(T)(T param){return T.init;} } class MyClass : MyInterface { override T doAndReturnSomething(T)(T param) { return param; } } void main() { MyInterface myClass = new MyClass(); writeln(myClass.doAndReturnSomething("Hello")); } Which compiles, runs, and prints nothing. -Steve
Re: safety and auto vectorization
On Monday, 3 August 2020 at 19:42:51 UTC, Steven Schveighoffer wrote: On 8/3/20 3:22 PM, Bruce Carneal wrote: Thanks Steve (and Chad). Summary: underspecified, varying behavior across versions, buggy. Steve, what's the best way for me to report this? Are spec issues lumped in with the other bugzilla reports? Yep. You can file under dlang.org with the spec keyword. Although this looks like it's not exactly a spec issue. I'd start it as a dmd bug (I don't know the exact interaction with the compiler and the library). It might also be a druntime bug. -Steve FWIW ..using gdc Debian 8.3.0-6, dst[]= generates a range error auto a = [1, 2, 3]; auto b = [4, 5, 6]; int[] dst = new int[4]; // note the extra element dst[] = a[] + b[]; writeln(dst[3]);
Re: Template functions inside interface
On Tuesday, 4 August 2020 at 13:36:15 UTC, Zans wrote: Is there any way to declare template functions inside interface and then override them in a class? No, the templates in the interface are automatically considered `final`. So the body must be in the interface too to avoid that undefined reference error. You can have them forward to normal methods in the interface though, just there needs to be a fixed number of them with concrete types.
Template functions inside interface
Is there any way to declare template functions inside interface and then override them in a class? Trying to compile the following code results in "undefined reference" error: import std.stdio; interface MyInterface { T doAndReturnSomething(T)(T param); } class MyClass : MyInterface { override T doAndReturnSomething(T)(T param) { return param; } } void main() { MyInterface myClass = new MyClass(); writeln(myClass.doAndReturnSomething!(string)("Hello")); } Thanks in advance!