Re: Circular enum member references in UDAs
On Thursday, 15 February 2024 at 20:10:15 UTC, Paul Backus wrote: On Thursday, 15 February 2024 at 18:12:42 UTC, realhet wrote: There was an attempt to fix it, but it looks like the PR author wasn't able to get it working correctly in all cases. That means I will solve this by putting the UDAs into a separate array. With a mixin I can still do it without extra redundancy, while the compiler enforce the logical correctness of the identifiers. Thank You for the info.
Re: Is there a way to tell LDC2 to only check the syntax of the source file?
On Wednesday, 6 December 2023 at 11:53:09 UTC, realhet wrote: Hello, I've found another trick: - prepend "version(none):" in front of the source. - ignore the optional "Error: declaration expected, not `module`" message - Take seriously all the other errors, those are only syntax errors, semantically the whole file equals to 'none'. I can also change the line numbers: with the #line directive. Most of the time I will pass it function bodies, not the whole source file.
Is there a way to tell LDC2 to only check the syntax of the source file?
Hello, I can turn off linking with -c I can turn off compiling with-o- How can I turn it off before the semantic passes? I'm experimenting with a nasty trink: I prepend "__undefinied__ _;" into the tested code. And if I get an error: Error: undefined identifier `__undefinied__` I know it started to do the semantic analysis, but I wonder if there is a prettier way to do this... ``` __undefinied__ _;void removeCard(Card card) { if(card.shortName !in cardMap) return; /+More code here, also the syntax could be broken. I wan't to detect exactly that.+/ } ```
Re: Getting __COLUMN__ of source code location.
On Thursday, 27 July 2023 at 16:17:28 UTC, IchorDev wrote: I'm not aware of any way to do that exact thing. Measuring what column a line is on would be quite subjective. When I compile(LDC2) a something with an error and using the --vcolumns argument I get this: onlineapp.d(14,5): Error: found `}` when expecting `;` following statement The error is on Line 14, Column 5. (I don't care how much it counts the TAB character, as long as it is unique.) So the information is accessible in the compiler. I just can't access from the language. ``` I can access __LINE__ but I can't access something like __COL__. ``` I just hope there is other ways to get this, maybe with an LDC specific traits or something. But you'd have to provide a unique ID manually anyway if, for instance, you create UI elements in a for loop: ```d for(size_t i=0; i<10; i++){ button(); } ``` I'd suggest using something more like Dear ImGui's ID system instead. Thanks for suggesting I've checked. As I see it is using an ID stack. I do something similar with a 32bit hash and using XOR operation to simulate a stack. Also for debugging and critical stuff there is an option to store this id stack in a string with meaningful names. So I can modify the id directly, when I pit the button() in a for loop. All the Controls automatically modifying the id by their type, source module and source line number (just a hash or a meaningful string for debug). ``` line 15:with(player){ if(Btn("Play")) play; if(Btn("Stop")) stop; } ``` So the 2 id's for the buttons will be the same: [Btn,module,15] and [Btn,module,15] <- that's a duplicated id. But if I'd have access to sourcecolumn, that would be so cool: [Btn,module,15,22] and [Btn,module,15,34] Here are the 2 workarounds right now: ``` line 15:with(player){ if(Btn("Play"), genericId(1)) play; if(Btn("Stop"), genericId(1)) stop; } ``` ``` line 15:with(player){ if(Btn("Play")) play; line 16: if(Btn("Stop")) stop; } ``` It's not a critically important feature, it's just helping the UI and the code that generates the UI being in the same visual layout: horizontal in this case.
Getting __COLUMN__ of source code location.
Hi, I can access the special tokens: __MODULE__, __LINE__, but how can I access the column. Is there a way to "hack" it out from LDC2? All the error messages contain column information, also I've found __traits(getLocation, symbol) also reporting the column. But how to get this information for the caller's location? ( Why is this important? - I have an immediate GUI which is using this __MODULE__LINE__ data to generate a unique ID. And I must put every GUI control creation command on a different line or provide a unique ID manually. - Now I'm planning an automated data logging debugging thing and it will sample expressions. The one expression per source code line is also problematic. I can give each PROBE an unique ID by using a preprocessor, but that's not a nice solution, that would be an overcomplication I try to avoid. Example: PROBE!0(somefunction(PROBE!1(expr1), PROBE!2(expr2))); Here are 3 PROBES on the same line, but the PROBE template is unable to distinguish them without the __COLUMN__. ) Thank You for your time.
Simple way to get Source Line Table of a compiled module.
Hi, I'm using LDC2 64bit on Windows. If I ask it to generate a .map file, I can locate the function. But how can I access the Line-code information? Do I need to generate a huge .pdb file with lots of other information (and also I have to understand it and extract the lines), or is there a lightweight solution for this in LDC2? I'd also like to have this information not just in Debug, but in Release mode too. Thank You in advance!
Re: Complicated @property access only works when I write an extra parenthesis "()"
It seems like I managed to solve it. All the chain of properties now capturing a generic value type T. And finally the most inner associative array will handle the implicit cast. Maybe that extra implicit () got confused when the types are same, but the aliases to those types are different. o.O Now both expressions are working. samples[key].mainPicture().width samples[key].mainPicture.width Side effect: The internal chaos behind this also got rediced by 25% as I had to refactor to find the root of the problem :D
Re: Complicated @property access only works when I write an extra parenthesis "()"
On Friday, 26 May 2023 at 21:11:45 UTC, Adam D Ruppe wrote: On Friday, 26 May 2023 at 21:00:20 UTC, realhet wrote: Only the extra () let it compile successfuly. No way to fix it. If the function takes an extra argument you can kinda trick it but for zero arg function pointer return from a property it is just plain broken and has been the whole time. Don't expect it to ever be fixed. At least my 5 hour trying-and-failing session comes to a logical end here :D Thank You!
Re: Complicated @property access only works when I write an extra parenthesis "()"
On Friday, 26 May 2023 at 21:00:20 UTC, realhet wrote: Update: ``` auto x = karcSamples[a.key].lod0; print(x._size); auto y = karcSamples[a.key].lod0(); print(y._size); with(karcSamples[a.key].lod0) print(_size); with(karcSamples[a.key].lod0()) print(_size); ``` When I put it into a temp variable or inside a with(), then both form works ok. Bit when I try to write the whole thing in a single nice expression: No property `_size` for the type `void`. In the documentation I see this: - For the expression typeof(exp) where exp is an @property function, the type is the return type of the function, rather than the type of the function. - For the expression __traits(compiles, exp) where exp is an @property function, a further check is made to see if the function can be called. I think this extra step is not always working and by writing an extra () or by using a temp variable or a with(), I was able to force it. I only hope there is a workaround that I can implement inside my template things, so the business logic could be nice as it can be...
Complicated @property access only works when I write an extra parenthesis "()"
Hello, I tried to narrow the problem and make a small example, but I've failed. I try to describe the syndrome, maybe someone knows about it. (I heard that @properties are not 100% functional, maybe it's because of that, I dunno...) With pragma msg, I verify the time of things: karcSamples This is a class, I create it from a class template, which has a lot of template mixins inside. karcSamples[key] The type of this is a RecordAccessor struct, which is a Voldemort struct inside a function. That function is called by karcSamples.opIndex(key). karcSamples[key].lod0 The type of this is BlobLoader 'lod0' is a mixin generated @property getter. It calls a template function in the karcSamples class: _getBlob!"lod0"(key) this also calls an internal struct called DataLoggerBlobAA which is acting like an associative array. That iternal struct overloads the opBinary!"in" operator and returns a BlobLoader struct. karcSamples[key].lod0._size-> _error_ void has no property ._size But this is weird, because BlobLoader actually HAS a @property called _size. karcSamples[key].lod0() The type of this is also BlobLoader. I have a feeling, that karcSamples[key].lod0 only returns a function pointer (the property function) which is implicitly evaluated, except when I use the ._size thing to evaluate a property. karcSamples[key].lod0()._size And this finally works, but it's ugly. Anyone knows how to eliminate that extra () from there? The typeof() is works good for it, but the actual compilation thinks it's "void", not the BlobLoader struct reported by typeof(). Only the extra () let it compile successfuly.
Re: string to char[4] FourCC conversion
On Friday, 26 May 2023 at 13:18:15 UTC, Steven Schveighoffer wrote: This worked for me: ```d char[4] fourC(string s) { if(s.length >= 4) return s[0 .. 4]; char[4] res = 0; res[0 .. s.length] = s; return res; } ``` Sometimes I forget that the return does an implicit cast. And it looks inside the slice [..] if it constant or not. Lot of things going on under the hood... Thank You!
string to char[4] FourCC conversion
Hello, Is there a way to do it nicer/better/faster/simpler? ``` char[4] fourC(string s) { uint res;//Zero initialized, not 0xff initialized. autocnt = min(s.length, 4), p = cast(char[4]*)(); (*p)[0..cnt] = s[0..cnt]; return *p; } ``` I tried to use staticArray!(char, 4), on s.byChar, but failed. I think I could do this using cast(char[4])(s.take(4).enumerate.map!"cast(uint)(a.value)<<<(a.index*8)".sum), but that seems no so effective. But at least that works in CT. I hope there is a more clever way in the std library I couldn't imagine at the moment... ``` //I also tried an arithmetic version, but it's impossible to convert to char[4] except with using pointer casts... uint fourCC(string s) { return s.take(4).enumerate.map!(a => a.value << cast(uint)a.index*8).sum; } ```
Re: core.simd ubyte16 initialization weirdness.
On Monday, 8 May 2023 at 11:43:33 UTC, Richard (Rikki) Andrew Cattermole wrote: Don't forget to type bad2 which gives the same result as the good one. Otherwise it only has 7 elements in it. Thank You, now that's good too. So here are the weird stuff: Pure arrays produce errors: enum ubyte16 x = [1, 2, 3] -> bad SSE calculation static immutable ubyte16 x = [1, 2, 3] -> calculates good, but pragma msg crashes And there ar 2 possible fixes: * Send the constant array through mixin() * Send the constant array through Phobos: For example .array or .dub will do. I think I will prefer the static immutable ubyte16 way with the simples looking array. The pragma will crash on it, but I can live with that. ``` import std, core.simd, ldc.llvmasm; T pshufb(T, U)(T a, in U b) { return __asm!ubyte16("pshufb $2, $1", "=x,0,x", a, b); } void main() { enum ubyte16 input= mixin(iota(100, 116).array), good = mixin([0, 1, 2, 3, 4, 5, 6, 7]), bad1 = [0, 1, 2, 3, 4, 5, 6, 7]; static immutable ubyte16 good2= iota(8).array, goodButPragmaCrash = [0, 1, 2, 3, 4, 5, 6, 7], goodAndNoPragmaCrash = [0, 1, 2, 3, 4, 5, 6, 7].dup; //pragma(msg, goodButPragmaCrash); pragma(msg, goodAndNoPragmaCrash); void test(string s)(){ mixin(q{ writef!"%s\n%s\n%s\n\n"("$", $, pshufb(input, $)); }.replace("$", s)); } test!"good"; test!"bad1"; test!"good2"; test!"goodButPragmaCrash"; test!"goodAndNoPragmaCrash"; } ```
Re: core.simd ubyte16 initialization weirdness.
On Monday, 8 May 2023 at 08:05:13 UTC, Richard (Rikki) Andrew Cattermole wrote: Yes, there is a pragma msg bug, but there is also a functionality 'bug'. I collected some more info: ``` import std, core.simd, ldc.llvmasm; T pshufb(T, U)(T a, in U b) { return __asm!ubyte16("pshufb $2, $1", "=x,0,x", a, b); } void main() { enum ubyte16 input = mixin(iota(100, 116).array), good = mixin([1, 2, 3, 4, 5, 6, 7]), bad1 = [1, 2, 3, 4, 5, 6, 7]; static immutable bad2 = [1, 2, 3, 4, 5, 6, 7]; //pragma(msg, somewhat_good); <-crash writeln(good); writeln(pshufb(input, good)); writeln; writeln(bad1); writeln(pshufb(input, bad1)); writeln; writeln(bad2); writeln(pshufb(input, bad2)); } [1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0] [101, 102, 103, 104, 105, 106, 107, 100, 100, 100, 100, 100, 100, 100, 100, 100] [1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0] [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100] [1, 2, 3, 4, 5, 6, 7] [107, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100] ``` In the declaration of pshufb I let anything pass through to the __asm statement. Only the enum ubyte16 = mixin(...); variant calculates the correct results, and luckily that can accept iota... calculated inputs as well. But at this point I have to memorize this and be aware when I'm having weird results. After all, this is the best SSE assembler I ever used so far *big thumbs up*. I like that I don't even have to allocate registers manually.
core.simd ubyte16 initialization weirdness.
Hello, ``` import std, core.simd; void main() { enum ubyte16 good1 = mixin([1, 2, 3, 4]), bad = [1, 2, 3, 4]; static immutable ubyte16 good2 = mixin([1, 2, 3, 4]), crash = [1, 2, 3, 4]; pragma(msg, good1); pragma(msg, bad); pragma(msg, good2); pragma(msg, crash); } ``` In the above example I tried 4 ways to initialize ubyte16 constants. I only specify the first 4 values, the remaining is automatically zero. 2 of them are good 2 of them are bad. Egy enum version compiles, but after trying SSE pshufb instruction with them, it seems like the [1, 2, 3, 4, 12 times 0] is distorted to this: [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4] I discovered the mixin() trick when I wanted to give them some calculated series. Is it a bad way to initialize these constants? Is there a better way? cast(immutable(__vector(ubyte[16])))[cast(ubyte)1u, cast(ubyte)2u, cast(ubyte)3u, cast(ubyte)4u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u, cast(ubyte)0u] This is how the compiler dumps it. But it's not so compact, so I rather use the mixin() version, I just don't understand why the int array fails -> [1, 2, 3] It would look so nice.
Re: Terminating the process of a running LDC2 compiler.
On Friday, 3 March 2023 at 14:33:08 UTC, Imperatorn wrote: We don't know what you mean by your definition of safe unfortunately For example killing ldc2.exe while it writes some cached temp files. And when the next time it tries to load those corrupted files, it will crash, or generate wrong output.
Terminating the process of a running LDC2 compiler.
Hello, Is it safe to kill an ongoing LDC2 process on Windows? My situation is this: - I launch 8 LDC2 compilation command lines on 8 DLang source files. - One of them has a compilation error and quits. - At this point I wait the completion of the other threads, but it would be faster to kill all those threads, fix the error, and run the multithreaded compilation again. Is it safe to kill those processes, or would it be unreliable (because of the integrity of environment variables, and/or cached temp files)? Thank You!
Re: Transform static immutable string array to tuple.
Awesome, Thank both of you! ``` enum a = ["A", "B"]; writeln(a); writeln(aliasSeqOf!a); writeln([aliasSeqOf!a]); ```
Transform static immutable string array to tuple.
Hello, Is there a better way to transform a string array to a tuple or to an AliasSeq? ``` mixin(customSyntaxPrefixes.format!`tuple(%(%s,%))`) ``` I'd like to use this as variable length arguments passed to the startsWith() std function (as multiple needles).
Re: Structure initializer VS lambda function
Hi again and thanks for the suggestions. I ended up checking every {} block with the following program: It works on a string where all the nested blocks are reduced to a single symbol. For example: '{', '"', '[' And all the comments and whitespaces are reduced to ' ' space. ``` enum CurlyBlockKind { empty, declarationsOrStatements, list } auto detectCurlyBlock(CodeColumn col_) { auto p = col_.extractThisLevelDString.text; p = p.replace("\n", " "); p = p.replace(" ", " "); p = p.replace(" {", "{"); p = p.replace(" [", "]"); p = p.replace(" (", ")"); //opt: these replaces are slow. p = p.strip; //first start with easy decisions at the end of the block if(p=="") return CurlyBlockKind.empty; if(p.endsWith(';') || p.endsWith(':')) return CurlyBlockKind.declarationsOrStatements; if(p.canFind("{,") || p.canFind(",{")) return CurlyBlockKind.list; if(p.canFind(';')||p.canFind('{')) return CurlyBlockKind.declarationsOrStatements; //give it up: it's not a declaration, neither a statement block return CurlyBlockKind.list; } ``` Since 2.5 months I didn't changed it, and I use it every day, so it seems ok. The only unsure thing in this detector is the empty block. That would require to check what's around the empty block, but I just decided to represent it with it's own category: "empty". The recursive detection of all D statements and declarations become easy: - declarationsOrStatements -> Go inside this block and detect all the statements and declarations. - list -> Discover the nested blocks inside this block, but don't treat this block as declarations or statements, this is a list! - empty -> do nothing
Structure initializer VS lambda function
Hi, I'm writing a DLang parser and got confused of this. What is a good way to distinguish lambda functions and structure initialization blocks. Both of them are {} blocks. I'm thinking of something like this: 1. checking inside (on the first hierarchy level inside {}) , => must be a struct initializer ; => must be a lambda no , and no ; => check it from the outside 2. checking outside (on the same hierarchy level as the {}): () before {} -> lambda => before {} -> lambda () after {}-> lambda //this check feels wrong to me. otherwise -> struct initializer But I think it's logically loose. I have only the syntax tree, I have no access to semantics. I don't know if an identifier is a struct for example. Is there a better way to do this? Thank You in advance!
Re: How is it possible that countUntil() generates a jump-table when the hayStack is a compile time array?
On Saturday, 1 October 2022 at 13:49:12 UTC, H. S. Teoh wrote: On Sat, Oct 01, 2022 at 01:20:08PM +, realhet via Digitalmars-d-learn wrote: It is very good to know. Thank You for the confirmation. Indeed it is really clever. I wrote a parser only to parse the structural elements of Dlang using template string[] parameters to feed tokens for the specialized parser functions recursively(!). And it unrolled everything into jump tables. Insane :D The only successful optimization I made was using PCMPESTRI instruction for skipping 16 bytes of text when there is no match found in a compile time constant 16 element character set. I expected like 10x speedup because of PCMPESTRI. But I only got 2x. I thought I was competing with poor linear searches only, but little I knew...
How is it possible that countUntil() generates a jump-table when the hayStack is a compile time array?
Hello, I just wanted to optimize a byte -> index lookup, by using a 256 element table instead of using [1, 2, 3].countUntil(x) and I was amazed what I've found. My solution lookup[x] was not faster at all, because LDC2 amazingly optimized the linear search to a jump table. Anyone please can tell me, how it is possible? I looked inside the countUntil() template and I see no static ifs for compile time optimizations. Is it true that: The compiler notices that there is a while loop on a static compile time array and it is clever enough to solve all the calculations in compile time and generate a completely unrolled loop? Then the optimizer transforms it to the jump table and do it with "jmp rax" ? If I'm right, this is not just std library magic, it works even with my own template functions. I'm also getting crazy long compile times, so this gotta be the case :D Thank You in advance.
Re: Is it possible to return mutable and const range from a single method?
On Monday, 22 August 2022 at 19:35:11 UTC, Steven Schveighoffer wrote: It is possible to write the same function for both const and mutable overloads by using the `this` template parameter: I guess before the "inout", "this This" was the only way to do this. I must remember this, it's really usefull. I also had lack of knowledge about that is(T==const) expression that Ali mentioned. In my program, I passed isConst as a template parameter with default initialization. It only needed one static if, where the range returns the front. Thank You all! - descendant classes can have parent or not (overload getParent) - allParents, thisAndAllParents: optionally enumerates this before the parents. - it can also filter the class type allParents!CustomContainer - supports const. It's much better than the previous visitor_function_with_a_callback_function_that_returns_false_when_it_wants_to_stop thing. I really beleive that in the end it generates only a while loop that the compiler can optimize well. (Unlike recursion or callbacks) ```d inout(Container) getParent() inout { return null; } void setParent(Container p){} auto thisAndAllParents(Base : Cell = Cell, bool thisToo = true, bool isConst=is(typeof(this)==const))() inout{ struct ParentRange{ private Cell act; private void skip(){ static if(is(Base==Cell)) {} else while(!empty && (cast(Base)act is null)) popFront; } this(const Cell a){ act = cast()a; skip; } @property bool empty() const{ return act is null; } void popFront(){ act = act.getParent; skip; } auto front() { static if(isConst) return cast(const Base)act; else return cast( Base)act; } } return ParentRange(thisToo ? this : getParent); } auto allParents(Base : Cell = Container)() inout{ return thisAndAllParents!(Base, false); } ```
Is it possible to return mutable and const range from a single method?
Hello, I managed to make a universal getParent() function which can preserve constness. I also had success with inout functions that work with this inout getParent method. Is it possible to do something like this but for the allParents input range producer method? In the const range implementation, the internal storage is non-const, it is just implicitly converted to const in the front() property. It gives the protection I was needed but is it possible to make this prettier? ```d import std; class A{ inout(A) getParent() inout{ return null; } this(A p){ } } class B : A{ A parent; override inout(A) getParent() inout{ return parent; } auto allParents(){ struct ParentRange{ A act; @property bool empty() const{ return act is null; } @property A front() { return act; } void popFront(){ act = act.getParent; } } return ParentRange(getParent); } auto allParents()const { struct ConstParentRange{ A act; @property bool empty() const{ return act is null; } @property const(A) front() inout { return act; } void popFront(){ act = act.getParent; } } return ConstParentRange(cast()getParent); } this(A p){ super(p); parent = p; } } auto test(inout A a, void delegate(inout A) fun){ auto p = a.getParent; fun(p); } void main() { auto a = new A(null); auto b = new B(a); const c = b; writeln(c.getParent); c.test((in d){ writeln(d); }); writeln; c.allParents.each!writeln; writeln; b.allParents.each!writeln; } ```
Re: std.algorithm.cmp is conflicting with itself.
On Friday, 12 August 2022 at 02:13:48 UTC, bachmeier wrote: Informative error message I'm making something like an IDE. The text search function in it is able to search across all user modules. I thought about filtering the search results by context. The following contexts are planned already: - inside code - inside comment - inside string literal Now I can add: - inside import declarations - search inside std That would help a lot with this type of error message. I think extending some general std routines is really helpful. This way I can write code in DLang, copy/paste it into GLSL and with minimal changes it can work there as well, and vice verse. The only downside is that when I want to use 3rd party packages: I have to check and modify them to not harm my overload sets with their imports.
Re: std.algorithm.cmp is conflicting with itself.
On Thursday, 11 August 2022 at 19:33:31 UTC, bachmeier wrote: std.string does a public import of std.algorithm.cmp. That was it! Thanks! Conclusion: This is how to overload cmp() ```d //this is the only place from where all other modules can see these std modules public import std.string, std.uni, std.algorithm, std.math; import std.range, std.traits; //create function overload group public import std.algorithm : cmp; public import std.math : cmp; auto cmp(A, B)(in A a, in B b) //the custom cmp() function if(!(isInputRange!A && isInputRange!B) //exclude std.algorithm.cmp && !(isFloatingPoint!A && isFloatingPoint!B)) //exclude std.math.cmp { return a==b ? 0 : a
Re: std.algorithm.cmp is conflicting with itself.
On Thursday, 11 August 2022 at 18:10:31 UTC, Paul Backus wrote: ... If you remove `std.algorithm` from `testcmpmodule2`'s `public import` line, the code compiles successfully. Yes, but in the 40 module project I'm unable to make it work. I doublechecked that the only public import of std.algorithm is in that utility module which is making the overload set. If a third party module uses std.algorithm, it's not public, and I also restrict the import for specific names that it uses. And still I'm not able to cmp("a", "b"), because of the conflict. What I'm thinking of maybe it is some module in the std library that can make a second conflicting overload set? (I public import some std modules, and if there is a public import inside that module to std.algorithm it can happen. I guess it's a possibility.)
std.algorithm.cmp is conflicting with itself.
Hello, I try to make an overload group of cmp() functions in my utility module but everything works well except when I import some 3rd party module that imports std.algorithm. Then I get an error: C:\D\testCmpOverload.d(11,8): Error: function `std.algorithm.comparison.cmp!(string, string).cmp` at c:\D\ldc2\bin\..\import\std\algorithm\comparison.d(625,6) conflicts with function `std.algorithm.comparison.cmp!(string, string).cmp` at c:\D\ldc2\bin\..\import\std\algorithm\comparison.d(625,6) It is conflicting with itself. My question is that how to solve this without choosing a different identifier, other than 'cmp'? Here's the utility module: ```d module testcmpmodule; //publicly output these modules, like I did in my always used 'utils' module. public import std.algorithm, std.math, std.stdio; import std.range, std.traits; //create function overload group public import std.algorithm : cmp; public import std.math : cmp; auto cmp(A, B)(in A a, in B b) if(!(isInputRange!A && isInputRange!B) //exclude std.algorithm.cmp && !(isFloatingPoint!A && isFloatingPoint!B)) //exclude std.math.cmp { return a==b ? 0 : aI have a project with 40K lines. And I don't even have to use public import in the 'second' module, like in this example, the error is happenning because something pulls it in. My not so good solution was this: ```d alias cmp_ = cmp; //so wherever there is a conflict, I only have to put a _ symbol after the cmp, but that's still ugly. To be more precise: I have a het.math module where I implement math routines that are close to opengl. That module does a log of patching of various std functions, mainly enable them to work on vector/matrix. I also have a het.utils module which publicly imports het.math, and also many std modules. And finally when I make an application using the complete framework, I lost the game finding what imports std.algorithm and thus ruining my fragile function overload groups. Also I wonder why there is no cmp() function for integers in the std library? It's easy to code (a-b or a==b?0:astill, I can do mistakes. (And I did: many of my comparisons had bugs :D So I wan't to centralize cmp()) Thank You in advance!
Using LDC2 with --march=amdgcn
Hello, I noticed that the LDC2 compiler has an architecture target called "AMD GCN". Is there an example code which is in D and generates a working binary of a hello world kernel. I tried it, and just failed at the very beginning: How can I specify __kernel and __global in D?
Re: Unable to use map() and array() inside a class-field's initializer.
On Thursday, 14 July 2022 at 14:41:53 UTC, Paul Backus wrote: Explicit type annotation: vvv Thank You! I will remember that in case of weird errors I can try to help the compiler with type inference.
Unable to use map() and array() inside a class-field's initializer.
Hello, Somehow it can't reach map and array inside a class field initializer. If I put that small expression inside a function, it works. If I encapsulate the initializer expression into a lambda and evaluate it right away, it also works. Only the nice form fails. Why is that? ```d import std; enum E{a, b, c} static struct S{ const E e; string otherProperties; } //trying to initialize an array inside static if(1) class D{ //this fails: Error: function `onlineapp.D.map!(E[]).map` need `this` to access member `map` auto x = [EnumMembers!E].map!(e => S(e)).array; } auto initialS(){ return [EnumMembers!E].map!(e => S(e)).array; } class C{ auto x = initialS; //this way it works } void main(){ writeln((new C).x); } ```
Re: static assert("nothing")
On Tuesday, 31 May 2022 at 09:35:30 UTC, Andrea Fontana wrote: On Tuesday, 31 May 2022 at 08:51:45 UTC, realhet wrote: Check if that string is init. assert("", "cool"); assert("ehh", "cool"); assert(string.init, "Not cool"); I feel some "JavaScript equality operator" vibes in this :D Anyways, I will be extra careful with these.
static assert("nothing")
Hi, In my framework I just found a dozen of compile time error handling like: ...else static assert("Invalid type"); This compiles without error. And it was useless for detecting errors because I forgot the first "false" or "0" parameter. I think it is because of the weird case of "every string casted to bool is true". There is an example in Phobos also: https://github.com/dlang/phobos/blob/master/std/uni/package.d at line 8847: static assert("Unknown normalization form "~norm); It is easy to make this mistake, but does static assert(string) has any meaningful use cases?
Re: Creating a custom iota()
On Thursday, 12 May 2022 at 20:12:19 UTC, Ali Çehreli wrote: And I've been thinking 'iota' may not be as suitable as I thought at first. I like the following even more: auto r0 = st .by(Duration(2)) .take(5); So I wrote this by() for my DateTime and then: import quantities.si; auto by(in DateTime begin, in Frequency f){ return begin.by(1/f); } //This let me do: now.by(60*hertz) .until!"a>b"(now+1*second) .each!writeln; My mind is blowing! :D
Re: Creating a custom iota()
On Thursday, 12 May 2022 at 17:06:39 UTC, Ali Çehreli wrote: I don't care whether it is good practice or not. :) The following is what you meant anyway and seems to work. I restricted the parameter types to the ones I wanted to use. And for the standard iota behavior I used a public import. public import std.range : iota; auto iota(in DateTime begin, in DateTime end, in Time step){ //https://forum.dlang.org/post/ivskeghrhbuhpiyte...@forum.dlang.org -> Ali's solution static struct Result{ DateTime current, end; Time step; @property bool empty(){ return current >= end; } @property auto front(){ return current; } void popFront(){ assert(!empty); current += step; } } return Result(begin, end, step); } ... iota(st, en, day).each!writeln; //works iota(1, 10, 0.5).each!writeln; //also works It works perfectly, Thank You very much! Although that general implementation of iota is a bit complex for me, this specialized one is simple. note(0): no cast() was needed here, worked with a const DateTime{ ulong ticks; ... }
Re: Creating a custom iota()
On Thursday, 12 May 2022 at 16:57:35 UTC, H. S. Teoh wrote: Does your DateTime type support the `++` operator? It can't because I only want to use the quantities.si.Time type to do arithmetic with my DateTime. In my previous DateTime, it was a lot of problem that I was doing math on it's raw internal variable (which was a double where 1.0 meant 1 day.) In the new version adding int(1) does a compilation error. I will use 1*second or 1*day or 1*micro(second) instead. I will always state the measurement unit to avoid confusions. But I'm curious, why didn't you use std.datetime? There are many weird reasons: 5 years ago I moved to DLang from Delphi. Since 20 years I always used the old Borland date system whist stards in 1899, is an ieee double, 1 = 1 day. I only did stuff with local times, it was enough. Recently I had to work with Python as well, and there I started to have problems with time synchronizations between the 2 systems. I ended up sending the exact Borland time to the Python program and make my little routines to work with them exactly like I do 20 years ago in Delphi, 5 years ago in DLang. But I know it is not nice. So a week ago I discovered the quantities package and I decided to rewrite my DateTime to use the Time type in that. It solves all my measurement unit madness in a very elegant way. So I also want those measurement units working in all my systems. (I have lengths, frequencies too) For me std.datetime was not an option because that felt so big I scared of it at the first look. It's 1.5MB, the same size as my complete program I'm working on :D I also hade a second based time measurement 'system', it used QueryPerformanceCounter. I want do discontinue that as well. So these are the features of the new DateTime: - small size: 64 uint is the internal format. (Half of std.systemtime, but it lacks timezone, it's only UTC internally). - precise: 100.0/64 nanosecond is the smallest unit. It covers 913 years. - It was built around the new WinAPI GetSystemTimePreciseAsFileTime() It gives me 100ns resolution UTC time in less than 50ns. So that's why I don't need QueryPerformanceCounter anymore. - The extra 6 bits under the 100ns ticks will be used for time based unique ID generation. It's better for me than having 6 years at my hand. - The integration with quantities.si makes my work much easier. I can't wait to use it in my program, as I knows physics things better than me, haha. std.range.recurrence. Indeed, that's an option as well, I forgot about. Thank You!
Creating a custom iota()
Hello, I have my own DateTime struct. It has opCmp() and opBinary(), I can do arithmetic with this custom DateTime and the amazing time units of the **quantities** package. Now I'm about mo make iterations in a DateTime range: const st = DateTime(UTC, "22.1.1 8:30").utcDayStart, en = DateTime(UTC, "22.3.5 19:56").max(now).utcDayStart + (100.0/64)*nano(second); //this works for(auto d = cast()st; d < en; d += day) writeln(d); //this would be nicer, but not works iota(st, en, day).each!writeln; My question is, is there a way to 'extend' the functionality of the std.iota() function or it is better to come up with a unique name for this special 'iota' functionality? I know that if I'm going to patch iota in my module, I have to make ALL the iota() variants plus my special iota variant visible in that module scope. Is this a good practice, or is there a better way? Or maybe put it inside a DateTimeRange struct, and implement the std range functionality?
Re: How to use an existing D package in Visual D?
On Tuesday, 5 April 2022 at 09:57:29 UTC, Mike Parker wrote: On Tuesday, 5 April 2022 at 09:26:54 UTC, realhet wrote: You should compile the existing package as a library, then add the library file to the linker settings in VisualD. Thank You for the fast help! Currently I have my own build system which works similar to Delphi(native target): You specify the main module and the package paths. Press F9. And the it AUTOMATICALLY discovers all the referenced module hierarchy and compiles it then finally producing an .exe. It also does compiled .obj file caching, so only the modules I changed and the modules that using the changed modules will be recompiled. I can do this module caching for myself, since the LDC compiler has the -allinstances flag. I switched from LDC 1.20 to 1.28 and I love the new internal linker. It will eliminate a lot of MS linker specific hacking from my build tool. I can just give LDC a bunch of sources, objects, and libs. And it does all the job intelligently. I'm talking about this if you want to peek: https://github.com/realhet/hetlib/blob/master/het/HLDC/BuildSys.d It basically launches an LDC2 instance for each of the changed modules and calls the linker when all finished. A debug compile takes 15 sec for a 40KLOC project(hierarchically including a few packages too) if I only change the main D file. Is this fast and light weight approach exists at all in VisualStudio? I heard something about "incremental build" in VisualStudio, but I think even if it is working with D, it can't step over the static library boundaries that you mentioned I have top use for the packages.
How to use an existing D package in Visual D?
Hello, I have all my D packages in the c:\D\libs\ directory. I added this path to the PropertyPages/Compiler/Additional Import Paths field. In the project source file I imported a module from my package using "import het.utils;" Also used a function from it. The syntax highlighter worked good, and the compiler was able to build main.obj file. But I can't find the het.utils.obj file nowhere. Also the linker is unable to link the things in it. My question is that how can I add an external package the right way to my project in Visual D? I'm planning to use that package from other projects too, so I want to keep it in one place on my HDD. Thank You in advance!
Re: Is it legal to remove a key from associative array while iterating over aa.keys if a foreach loop?
On Sunday, 29 August 2021 at 09:02:52 UTC, Mike Parker wrote: On Sunday, 29 August 2021 at 08:55:44 UTC, realhet wrote: Is it safe, or do I have to take a snapsot of the keys range like this? -> You shouldn't remove anything when iterating over `.keys` or `.values`. Use `.byKey` and `.byValue` instead to get ranges that are independent of the aa. I did a small test using .byKey, it's totally safe, just as you said. Thank You! ``` void main(){ int[int] aa = [1:10, 2:20, 3:30]; auto k1 = aa.keys; auto k2 = aa.byKey; aa.remove(2); writeln(typeof(k1).stringof); foreach(k; k1) writeln(k); writeln(typeof(k2).stringof); foreach(k; k2) writeln(k); } ```
Is it legal to remove a key from associative array while iterating over aa.keys if a foreach loop?
Hi, //remap the result blobs foreach(k; res.blobs.keys){ int p = map(k); if(p!=k){ res.blobs[p].weight += res.blobs[k].weight; res.blobs.remove(k); } } It boils down to: foreach(k; aa.keys) aa.remove(k); Is it safe, or do I have to take a snapsot of the keys range like this? -> foreach(k; aa.keys.array) aa.remove(k); //this is 100% safe I'm asking because I have no idea how the internal aa.keys range works. If it stores an index or a pionter inside, while I change the underlying structure of the aa, it could be a hazard... Thanks in advance.
Re: array inside a class + alias this + filter -> clears the array.
On Wednesday, 7 July 2021 at 17:10:01 UTC, Paul Backus wrote: On Wednesday, 7 July 2021 at 16:20:29 UTC, realhet wrote: int[] opIndex() { return array; } Thx, I didn't know about this type of opSlice override. It works nicely. Now I have these choices: - write [] everywhere to access the containers. - write nothing extra to access the containers but put the container operations one level higher and select the container for those based on a dummy struct. Like going from: ``` db.entities.add("Entity01"); to db.add(entity("Entity01")); //struct entity{ string name; } ``` Currently I have both ways plus your solution for the range access. Gotta experience with it to choose. Thanks again! I will remember that common container rule from now on.
array inside a class + alias this + filter -> clears the array.
Hi, I wanted to make a container class that exposes its elements using a simple "alias this", but getting weird errors: I test with the std.algorithm.filter template function. 1. when I use "alias this" on a function that returns a slice, making the internal array unreachable, filter just can't compile. 2. when I expose the array as it is, filter deletes the array after it returns. My goal is to make a class, which acts like an array, but also having member functions to add/remove/find its items. On top of that this class has an owner (a database table thing) too. Example use-cases: table.rows.add(...) table.rows[4] table.rows.filter!(...).map!(...) ``` import std.stdio, std.range, std.algorithm, std.uni, std.utf, std.conv, std.typecons, std.array, std.traits, std.exception, std.format, std.random, std.math; class C{ //must be a class, not a struct int[] array; static if(0){ //BAD: filter cannot deduce from an aliased function // that returns a nonref array auto getArray(){ return array; } alias getArray this; }else{ alias array this; //this works } } void main(){ auto c = new C; c.array = [1, 2]; void wl(){ writeln("len=", c.length); } //filtering the array explicitly: GOOD c.array.filter!"true".each!writeln; wl; //filtering the slice of the alias: GOOD c.array.filter!"true".each!writeln; wl; //filtering the alias: BAD -> erases the array c.filter!"true".each!writeln; wl; } ``` Thanks in advance.
Re: Is there a nicer way to get the first element or typeof(element).init from a range?
On Sunday, 30 May 2021 at 12:16:19 UTC, realhet wrote: presets.keys.sort.take(1).get(0); <- Oups: after fixing an error and making it compile the solution is even uglier: presets.keys.sort.take(1).array.get(0);
Is there a nicer way to get the first element or typeof(element).init from a range?
Hello, This is my current solution but there must be a better way to do it in D T get(T)(T[] arr, size_t idx, T def = T.init){ return idx
Re: Voldemort type "this" pointer
On Wednesday, 21 April 2021 at 15:53:59 UTC, Ali Çehreli wrote: On 4/21/21 8:37 AM, realhet wrote: On Wednesday, 21 April 2021 at 10:47:08 UTC, Mike Parker wrote: On Wednesday, 21 April 2021 at 10:00:51 UTC, realhet wrote: It has access to the context of its enclosing scope (via an added hidden field). Thanks! So it is unsafe to return a non-static nested struct from a function. But it is useful to pass it forward into other functions. Not at all. (D is good at preventing such bugs anyway.) The local context that the nested struct object uses becomes the context of that object. Wow, this information is really out of the box for me. I have one misconception less now. (I never used a language with GC before and this thing requires a GC for sure.) /--- auto uiDeclare(void delegate() fun){ struct UiObject{ //void delegate() fun; <- not needed, it captures fun in the params void render(){ fun(); } } return UiObject(); } long rec(long a, long c){ return aauto b = [ uiDeclare({ writeln("boop", a); }), uiDeclare({ writeln("boop", a+1); })]; rec(0, 123456); // destroy the stack to make sure b.each!"a.render"; } Indeed it's not using the stack. And it also works when a delegates captures its scope. In my immediate GUI interface I'm using delegates all the time with the my misconception of I only allowed to call them from inside the function I passed them into. For example: Row({ Text(clBlue, "Hello"); Img(`pictures\pic1.jpg`); }); will call the delegate from inside, not save it for later use. And if I save the delegate inside the Row() function (I mark UI generating functions with a capital letter), it is protected from the GC and can be used later in rendering time... Too bad, the data it uses at that later moment is possibly changed already. Anyways, I've learned a lot now. Thank you!
Re: Voldemort type "this" pointer
On Wednesday, 21 April 2021 at 10:47:08 UTC, Mike Parker wrote: On Wednesday, 21 April 2021 at 10:00:51 UTC, realhet wrote: It has access to the context of its enclosing scope (via an added hidden field). Thanks! So it is unsafe to return a non-static nested struct from a function. But it is useful to pass it forward into other functions.
Voldemort type "this" pointer
Hi, I noticed that there is a hidden "this" pointer in a struct that I declare inside a body of a function. Also noticed when I use the "static" keyword, the "this" pointer disappears. My question is about what is the "this" pointer for. Is it for storing the stack frame of the function in order to be able to serve queries that can lazily use the data from the stack frame? (I guess it's something else because that part of the stack might be undefined after exiting from the function.)
Re: lockstep works with .each, but fails with .map
On Friday, 5 March 2021 at 19:26:38 UTC, Jacob Carlborg wrote: On 2021-03-05 19:49, realhet wrote: Why it works with each (or foreach), but not with map? o.O `lockstep` is specifically designed to work with `foreach`. I think `each` has a special case to work with `lockstep`. If you want to use other range functions, you should use `zip` instead of `lockstep`. It works now: zip(StoppingPolicy.requireSameLength, a, b).map!(a => SE(a[])).sum / float(a.length); I had a misconception (lazyness of learning) that zip is making a simple array, not a tuple array like I guessed lockstep does. Also in zip() the StoppingPolicy is the first parameter and in lockstep() it's the last. Thank you very much!
lockstep works with .each, but fails with .map
Hi What am I doing wrong here? import std.stdio, std.range, std.algorithm, std.uni, std.utf, std.conv, std.typecons, std.array; auto SE(A, B)(in A a, in B b){ return (a-b)^^2; } void main(){ auto a = [1, 2, 3], b = [1, 1, 1]; lockstep(a, b, StoppingPolicy.requireSameLength).each!((a, b){ writeln(SE(a, b)); }); lockstep(a, b, StoppingPolicy.requireSameLength).map !((a, b){ return SE(a, b) ; }).each!writeln; <- error here } The error: map(Range)(Range r) with Range = Lockstep!(int[], int[]) must satisfy the following constraint: isInputRange!(Unqual!Range) Why it works with each (or foreach), but not with map? o.O I just wanted to make a Sum of squared errors function. Thanks in advance!
Re: How to capture a BitFlags type in a function parameter?
On Sunday, 31 January 2021 at 14:16:15 UTC, Paul Backus wrote: On Sunday, 31 January 2021 at 14:04:00 UTC, realhet wrote: Hi, static void stdUI(E, Flag!"unsafe" u)(ref BitFlags!(E, u) flags) {} Thank You! Somehow I forgot I could pass amd match ANY TYPE in the template parameters. I'll remember this, thanks!
How to capture a BitFlags type in a function parameter?
Hi, I wan't to process every specialization of the BitFlags struct in a function: So far the best I can come up is this: static void stdUI(F)(ref F flags) if(F.stringof.startsWith("BitFlags!(")){} But it's obviously lame. If I try this way: static void stdUI(E, U)(ref BitFlags!(E, U) flags){} I get a cannot deduce arguments error. Same error with: static void stdUI(E, U, B = BitFlags!(E, U))(ref B flags){} I'd like to know the Enum type as well. Thank You for your help in advance!
Re: Is there a standard function that combines take() and popFrontExactly()
On Monday, 14 December 2020 at 14:16:41 UTC, Dukc wrote: On Friday, 11 December 2020 at 19:07:23 UTC, realhet wrote: I've just made this unicode wordreplacer function working, but It seems not too nice and functional-ish. Are there ways to make it more simple? To answer the title, yes there is: Thanks for ideas! Yesterday I ended up making this helper funct: auto fetchFrontExactly(R)(ref R r, size_t n) if(isInputRange!R){ auto res = r.takeExactly(n); r.popFrontExactly(n); return res; } Now I leaned from you: refRange and take-s ability to pop elements from a refRange. That's what I was needed! Now the 2 aproach looks like: string replaceWords(alias fun = isWordChar)(string str, string from, string to){ if(1){ auto fetchAndReplace(Tuple!(bool, uint) p){ auto act = refRange().take(p[1]).text; return p[0] && act==from ? to : act; } return str.map!fun .group .map!fetchAndReplace .join; }else{ string res; foreach(isWord, len; str.map!fun.group){ auto act = ().refRange.take(len).text; res ~= (isWord && act==from ? to : act); } return(res); } } They are the same thing, but the first looks nicer because it is a processing pipe with the state modifying thing extracted to a named function (so that's makes the pipe more understandable). However in the foreach version I can have meaningful parameter names: (isWord, len) instead of a tuple. I don't want to do functional programming just for itself. I'm just learning it, and want to understand it better. I already found a lot of good uses of it for my tasks and I still discover a lot of cool stuff. Thanks again!
Is there a standard function that combines take() and popFrontExactly()
Hi, I've just made this unicode wordreplacer function working, but It seems not too nice and functional-ish. Are there ways to make it more simple? import std.stdio, std.range, std.algorithm, std.uni, std.utf, std.conv; bool isWordChar(dchar ch){ return isAlphaNum(ch) || ch=='_'; } string replaceWords(alias fun = isWordChar)(string str, string from, string to){ auto res = appender!string(); auto src = str.byCodePoint; foreach(isWord, len; str.map!fun.group){ auto act = src.take(len).text; src.popFrontExactly(len); res.put(isWord && act==from ? to : act); } return(res[]); } void main(){ immutable str = "Type=FunctionType Type; éType Type2: Type aTypeb Type"; str.replace("Type", "AsmType").writeln; str.replaceWords("Type", "AsmType").writeln; } Thanks in advance!
Re: Handling referencing class parent instances in a GC friendly way.
On Monday, 30 November 2020 at 14:36:08 UTC, FeepingCreature wrote: On Monday, 30 November 2020 at 14:33:22 UTC, realhet wrote: ... Though you may want to do `items = null;` too. I just forgot 1 of three things, thx for pointing it out. And I also forget to notify the parent to remove the reference from its items list.
Handling referencing class parent instances in a GC friendly way.
Hi, class A{ A parent; A[] items; void myDestroy(){ items.each!(i => i.myDestroy); parent = null; // after this point I think the GC will release it automatically, and it will call ~this() too. Am I right? } } I have a hierarchy of class instances forward and backward linked to its items ant its parent. What is a proper way to destroy an instance of class A? Is calling instance.myDestroy sufficient? Am I right that this kind of uninitialization MUST not go into the ~this() destructor, because of the references the instance is holding, the system will never call the ~this()? Or is there a better way for this type of thing in Dlang? Thanks in advance!
Re: C++ or D?
On Tuesday, 10 November 2020 at 01:00:50 UTC, Mark wrote: Hi all, my question would be about using D or not using D. Here are some things you will NOT get in D: youtube -> Dconf 2014 Day 2 Keynote: The Last Thing D Needs -- Scott Meyers For example, you will not get neurosis from it, or badly infected wounds someone mentioned earlier :D I also like the fast compile times, and the compile time programming, the ability that you can program D in D if you wish.
Compile-time function call with transformed parameters
Hi, Is there a way to make this in a nicer way without the string mixin? private auto generateVector(CT, alias fun, T...)(in T args){ static if(anyVector!T){ Vector!(CT, CommonVectorLength!T) res; static foreach(i; 0..res.length) res[i] = mixin("fun(", T.length.iota.map!(j => "args["~j.text~"].vectorAccess!i").join(','), ")"); return res; }else{ return fun(args); } } The mixin expands to: fun(args[0].vectorAccess!i, ..., args[$-1].vectorAccess!i) And vectorAccess is a function with a template int parameter (i). private auto vectorAccess(int idx, T)(in T a){ static if(isVector!T) return a[idx]; else return a; } I tried with staticMap, but that vectorAccess is a runtime thing. Other than that I have no idea. I'm 99% sure DLang has a nice thing for this, but can't find it yet. Maybe it is possible to put a thing like this -> [ args[0].vectorAccess!i ] into an AliasSeq and then give that inside the fun(), but how can I generate effectively an array of code? Thank you!
Re: Getting Field Names of a specific UDA in compile time.
On Saturday, 3 October 2020 at 14:00:30 UTC, Adam D. Ruppe wrote: On Saturday, 3 October 2020 at 13:10:31 UTC, realhet wrote: I only managed to get the string[] by making a static foreach, but I don't know how to put that in an enum xxx = ...; statement. There's always other ways but general rule: if you can get it one way, just wrap that up in a function and call that function for your enum initializer. string[] your_function() { // implementation here you already have return it; } enum NodeNames = your_function(); Though with arrays btw `static immutable` tends to give better results than `enum` since it avoids extra allocations. I tried it to put into a function: auto getSymbolNamesByUDA(T, string uda)(){ string[] res; static foreach(a; getSymbolsByUDA!(T, uda)) res ~= a.stringof; return res; } class Printer{ @("NODES") int gem1, gem2, gem3, gem4, gem5, head1, head2, head3, head4; alias Nodes = getSymbolsByUDA!(typeof(this), "NODES"); enum NodeNames = getSymbolNamesByUDA!(typeof(this), "NODES"); } void main(){ static foreach(n; Printer.Nodes) n.stringof.writeln; Printer.NodeNames.writeln; } Up until this point, the alias declaration was before the enum declaration. It gives an error: Error: unknown, please file report on issues.dlang.org But now I tried to comment out the alias declaration and it worked. It also works when I put the alias declaration after the enum: enum NodeNames = getSymbolNamesByUDA!(typeof(this), "NODES"); alias Nodes = getSymbolsByUDA!(typeof(this), "NODES"); Same behavior with "static immutable". My initial intention was to use the Nodes alias to get the name strings out of it. Now it needs more copy paste but it works. This is weird o.O Thank you!
Getting Field Names of a specific UDA in compile time.
Hi, class Printer{ @("NODES") int gem1, gem2, gem3, gem4, gem5, head1, head2, head3, head4; import std.traits, std.meta; alias Nodes = getSymbolsByUDA!(typeof(this), "NODES"); enum NodeNames = ["gem1", "gem2", ]; } Is there a way to make an enum like the above with compile time programming? I only managed to get the string[] by making a static foreach, but I don't know how to put that in an enum xxx = ...; statement.
Re: Struct initializer in UDA
On Sunday, 27 September 2020 at 11:59:49 UTC, Anonymouse wrote: On Sunday, 27 September 2020 at 10:17:39 UTC, realhet wrote: On Saturday, 26 September 2020 at 17:13:17 UTC, Anonymouse wrote: On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote: That looks the closes to the python named parameters or the struct initializer. For my use case this opDispatch trick seems to be more flexible than the named-parameters thing: @(FieldProps().range(-360, 360).format("%.2f").caption("Turret rotation").unit("deg")) float alpha = 0; for example if I use the name: "logRange" it can also set the isLogarithmic flag as a side effect to true inside the FieldProps struct. Just by choosing a slightly different name. With this idealized format it would be not possible: @FieldProps{ range: {-360, 360}, format:"%.2f", caption:"Turret rotation", unit:"deg"} float alpha = 0; The more work inside the struct is not a problem, because I'm willing to use it from 1000 places. Also __traits(allMembers) can help. Thank you!
Re: Struct initializer in UDA
On Saturday, 26 September 2020 at 17:13:17 UTC, Anonymouse wrote: On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote: The closest I can get is @(S.init.c(9).f(42)) with use of opDispatch, which is easier to read but still ugly. All I can get is that the - an identifier of a member is stronger than the opDispatch. -> Error: function expected before (), not S(0, 0).c of type int - and if I prefix it with '_' it ruins toString. -> Error: no property toString for type onlineapp.S import std.stdio, std.range, std.algorithm, std.traits, std.meta, std.conv, std.string, std.uni, std.meta, std.functional, std.exception; struct S{ int a, b; auto opDispatch(string name, T)(T value) if(name.startsWith("_")) { mixin(name[1..$], "= value;"); return this; } } void main(){ S.init._a(5).writeln; } Now I'm more confused, as the compiler completely ignores the if(name.startsWith("_")) constraint o.O
Struct initializer in UDA
Hi, struct S{int a, b, c=9, d, e, f;} Is there a way or a trick to declare an UDA by using a nice struct initializer? It would be nice to be able to use the form: @S{f:42} int a; //or something similar to this. instead of this longer and error-prone way: @S(0, 0, 0, 9, 0, 42) int a;
Re: Is there a way to return an lvalue and also an rvalue from the same member function?
On Sunday, 20 September 2020 at 17:08:49 UTC, realhet wrote: On Sunday, 20 September 2020 at 16:18:19 UTC, Steven Schveighoffer wrote: On 9/20/20 11:52 AM, realhet wrote: On Sunday, 20 September 2020 at 14:54:09 UTC, Steven Schveighoffer wrote: On 9/20/20 9:30 AM, realhet wrote: Yeah, I think this might work. https://gist.github.com/run-dlang/4b4d4de81c20a082d72eb61307db2946 Here's a little example. In the main() there are the requirements. Below that is the implementation. If it is ugly, please tell me how to make it prettier :D Once I was able to make the compiler for a really long time, so I know it is rather templates than explicit mixins. All the swizzles that cover a contiguous area are mixed in though: in a 4 element vector it is: only a few elements: "x", "y", "z", "w", "xy", "yz", "zw", "xyz", "yzw", "xyzw", "r", "g", "b", "a", "rg", "gb", "ba", "rgb", "gba", "rgba", "s", "t", "p", "q", "st", "tp", "pq", "stp", "tpq", "stpq" For everything there is opDispatch.
Re: Is there a way to return an lvalue and also an rvalue from the same member function?
On Sunday, 20 September 2020 at 16:18:19 UTC, Steven Schveighoffer wrote: On 9/20/20 11:52 AM, realhet wrote: On Sunday, 20 September 2020 at 14:54:09 UTC, Steven Schveighoffer wrote: On 9/20/20 9:30 AM, realhet wrote: Yeah, I think this might work. -Steve That would be a 3rd category out if 4 in total: - ref for the contiguous subVectors (vec4.init.yz is a vec2) - const for the complicated ones (vec4.init.z0 is a vec2, 2nd component is 0) - swizzled struct of a referenced vector: (vec4 a; a.yx is a struct that links to the original 'a' by reference and know it has to swap x and y). - everything else that can contain any vector component at any place including constants 0 and 1. I've learned this kind of swizzling in the good old CAL/AMD_IL times. Swizzled struct is on the righr: then it should be implicitly casted when assigning it to the left to a vector. I gotta learn that too. In GLSL this behavior is implemented deeply in the compiler. I'm so happy in D it seems also possible :D
Re: Is there a way to return an lvalue and also an rvalue from the same member function?
On Sunday, 20 September 2020 at 15:52:49 UTC, realhet wrote: On Sunday, 20 September 2020 at 14:54:09 UTC, Steven Schveighoffer wrote: On 9/20/20 9:30 AM, realhet wrote: I managed to do the constant swizzles and it seems so elegant: auto opDispatch(string def)() const if(validRvalueSwizzle(def)) //making sure that only the few thousand valid swizzles can pass through here { static if(def.startsWith('_')){ //if the swizzle definition starts with a number return opDispatch!(def[1..$]); }else{ Vec!(CT, mixin(def.length)) res; static foreach(i, ch; def) res[i] = mixin(ch); // ch can be one of xyzw or rgba or stpq or 0 or 1. // just mix it in using the already created lvalue swizzles of (integer consts 01) return res; } } I also have an idea that if I use capital letters, it shoud mean negative components. This way importing a 3d vertex could be so easy in compile time: rotated = original.xZy -> this is rotated 90 degrees around the x axis. Just need to add an uppercase check. Never dared to go that far in compile time dlang stuff, and I love it. :D Amazing language!
Re: Is there a way to return an lvalue and also an rvalue from the same member function?
On Sunday, 20 September 2020 at 14:54:09 UTC, Steven Schveighoffer wrote: On 9/20/20 9:30 AM, realhet wrote: ref inout(int) x() inout { return array[0]; } This doesn't work when I type: v.x++; I want to make a similar type like the GLSL vectors. Where the following thing is valid: vec4 a, b; a.yzw = b.xzy; On the left there is a contiguous area of the vector a. It just starts form the 1th element, not form the 0th: a[1..4]. It could be work as an lvalue. On the right there is a non-contiguous swizzle: [b.x, b.z, b.y]. But because it is 3 element wide, it can be assigned to the lvalue "a.yzw". This value cannot be an lvalue because the order of the elements are not the same as in memory. So it must returned as a const. Here's what I achieved so far: private enum swizzleRegs = ["xyzw", "rgba", "stpq"]; //vector, color, and texture component letters struct Vec(CT, int N) if(N>=2 && N<=4){ alias VectorType = typeof(this); alias ComponentType = CT; enum VectorTypeName = ComponentTypePrefix ~ "vec" ~ N.text; CT[N] array = [0].replicate(N).array; //default is 0,0,0, not NaN. Just like in GLSL. alias array this; enum length = N; ... static foreach(regs; swizzleRegs) static foreach(len; 1..N+1) static foreach(i; 0..N-len+1) static if(len==1){ 1)mixin(format!"auto %s() const { return array[%s]; }"(regs[i], i)); 2)mixin(format!"ref %s() { return array[%s]; }"(regs[i], i)); }else{ 3)mixin(format!"auto %s() const { return Vec!(CT, %s)(array[%s..%s]); }"(regs[i..i+len], len, i, i+len)); 4)mixin(format!"ref %s() { return *(cast(Vec!(CT, %s)*) (array[%s..%s])); }"(regs[i..i+len], len, i, i+len)); } } So what I feel, the mixin()-s are a bit nasty :D But sufficient for the following two criteria: 1. immutable vec3 a; a.xy.writeln; // displays a const vec2 casting a constant memory lovation to vec2 -> 3) 2. vec3 b; b.g++; // accessing the 2. component(g=green, 1based) of a vec3 with a memory reference because it is mutable. I only want lvalues from swizzle combinations that are adjacent in memory, so I can cast them. For all the rest I'm using opDispatch(string def)() with a strict constraint on the string 'def'. For example: a. returns vec4(a.x, a.x, a.x, a.x); a.x01z returns vec4(a.x, a.0, a.1, a.z); The only thing I don't want to implement from the GLSL spec is those non-contigous swizzle assignments like: a.zyx = vec3(1,2,3) *** but a.xyz = vec3(1,2,3) should work. *** maybe with a struct that refers to the original vector and the swizzle code it could be also possible. :D
Re: Is there a way to return an lvalue and also an rvalue from the same member function?
On Sunday, 20 September 2020 at 13:30:36 UTC, realhet wrote: Hi, More specifically: struct S{ int[2] array; ref swizzle(string code)(){ static if(code=="x") return array[0]; else static if(code=="y") return array[1]; else static assert("Unhandled"); } } To make this work for const/immutable structs, I have to make another function with the header: auto swizzle(string code)() const{ copy or mixin the whole thing again... } Maybe there is a language feature for this, like "auto ref" or "inout"? Thank you!
Is there a way to return an lvalue and also an rvalue from the same member function?
Hi, struct S{ int[2] array; ref x() { return array[0]; } auto x() const { return array[0]; } } If there a way to write the function 'x' into one function, not 2 overloads. I tried auto/const/ref mindlessly :D, also remembered 'inout', but obviously those weren't solve the problem. (This is going to be a swizzling 'system' that mimics GLSL, later I will make a template that takes 'x'as a template parameter, just wondering that the support for const and non-cons can be done easier.)
Re: What kind of mangling has the LDC2 -X JsonFile "deco" field?
On Thursday, 17 September 2020 at 04:01:11 UTC, Adam D. Ruppe wrote: On Thursday, 17 September 2020 at 03:06:45 UTC, realhet wrote: Anyone can help me telling how to decode these please? Just prepend _D4name Thank you very much!
What kind of mangling has the LDC2 -X JsonFile "deco" field?
Hello, I'm trying to get information from the JsonFile produced by LDC2, but having no clue how to decode this: For example: header: KeywordCat kwCatOf(int k) "deco" : "FAyaZE3het8keywords10KeywordCat", The "deco" field contains the full name of the return type het.keywords.KeywordCat, but in front of that I don't know how to decode that "FAyaZE". Also this is how a string return type is encoded: "FiZAya" I tried std.demangle and and online GCC demangler, but no luck. Anyone can help me telling how to decode these please? Thank you in advance!
Re: Catching OS Exceptions in Windows using LDC
On Saturday, 4 July 2020 at 14:44:06 UTC, Kagamin wrote: try https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter Thank You, this was the winner for me. Not just I can catch the OS Exceptions, I can check and alter the CPU state and decide to continue execution from an optionally modified cpu state, or just stop and show the error. It needed some work, but this seems the best way for LDC2 Win64.
Catching OS Exceptions in Windows using LDC
Hi, I'd like to catch the OS Exceptions including: - access violation - int 3 - invalid opcode etc. The default behavior is that when these events happen, the program immediately exits with some negative exit code. It was not a problem on other systems like: MSVC or Delphi, but on LDC these events are completely ignored. It would be very useful to catch these errors inside and have the opportunity to handle it whatever is the best: application exit, save important data, ignore. I've already found a solution from Adam D. Ruppe, but that's for Linux for the Access Violation case. But is there a similar thing for Windows as well? PS: I do believe rely on AccessViolation to avoid buffer overruns is really useless and unsecure. But it would be so much help for me for developing/debugging my programs. Thank You!
Re: Weird behavior with UDAs
On Saturday, 13 June 2020 at 12:55:36 UTC, realhet wrote: Hello, I have a problem I can't even understand with the code For the first I realized that an UDA can be a type too, and come up with this: template getUDA(alias a, U){ enum u = q{ getUDAs!(a, U)[$-1] }; static if(hasUDA!(a, U) && !is(mixin(u))) enum getUDA = mixin(u); else enum getUDA = U.init; } So I always get an instance of the UDA with the default values. But the second question is still beyond me: How can be a string represented with 'null' by default instead on `""`. Unless I state it explicitly with name="" ? o.O
Weird behavior with UDAs
Hello, I have a problem I can't even understand with the code below: https://run.dlang.io/is/7yXAEA import std.stdio, std.range, std.algorithm, std.traits, std.meta; struct UNIFORM{ string name; } struct A{ int i1; @UNIFORM() int i2; @UNIFORM("fuzz") int i3; @UNIFORM int i4; } template getUDA(alias a, U){ static if(hasUDA!(a, U)) enum getUDA = getUDAs!(a, U)[$-1]; else enum getUDA = U.init; } pragma(msg, getUDA!(A.i1, UNIFORM)); //UNIFORM(null) pragma(msg, getUDA!(A.i2, UNIFORM)); //UNIFORM(null) pragma(msg, getUDA!(A.i3, UNIFORM)); //UNIFORM("fuzz"); pragma(msg, getUDA!(A.i4, UNIFORM)); //Error: initializer must be an expression, not UNIFORM struct UNIFORM2{ string name=""; } struct B{ @UNIFORM2() int i1; } pragma(msg, getUDA!(B.i1, UNIFORM2)); //UNIFORM("") instead if UNIFORM(null) // My first question is, how to avoid that error with A.i4? Why is there a difference between @UNIFORM and @UNIFORM(), do the first returns a type and the later returns a value? My second quertion is, why the UNIFORM struct with uninitialized string producing UNIFORM(null). How can be a difference when I say name="", and it's just the same as the default string initializer, and then it produce UNIFORM("")? Thank You!
Re: Making alias of a struct field needs "this".
On Wednesday, 3 June 2020 at 10:11:59 UTC, realhet wrote: On Tuesday, 2 June 2020 at 20:38:40 UTC, Steven Schveighoffer wrote: On 6/2/20 10:51 AM, realhet wrote: On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote: On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote: mixin("int[", 2, "]") a = mixin([5]) ~ 6; That's insane :D
Re: Making alias of a struct field needs "this".
On Tuesday, 2 June 2020 at 20:38:40 UTC, Steven Schveighoffer wrote: On 6/2/20 10:51 AM, realhet wrote: On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote: On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote: A month ago I discovered that mixinDeclarations can be used for types too: mixin("int[", 2, "]") a = [5, 6];
Re: Making alias of a struct field needs "this".
On Tuesday, 2 June 2020 at 13:37:25 UTC, Stanislav Blinov wrote: On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote: Try UDAs instead of a map: struct A { struct G { @("hauteur") int height; } Good idea, thx! I already using UDA's for range and measurement units. struct Profile{ @STORED: @UNIT("mm") @RANGE(0, 100) float radius = 21; I gonna need one more reasonably named UDA struct.
Re: Making alias of a struct field needs "this".
On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote: On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote: mixin("@property auto ", k, "() const { return ", v, "; }"); Wow, string mixin can process comma separated list, I gotta remember this, thanks!
Re: Making alias of a struct field needs "this".
On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote: On Tuesday, 2 June 2020 at 09:10:03 UTC, Ali Çehreli wrote: On 6/2/20 1:56 AM, realhet wrote: Oh and I can put that function generator mixin thing into a template as well, that way it is reusable and much nicer. There are a lot of possibilities in D, I love it!
Re: Making alias of a struct field needs "this".
On Tuesday, 2 June 2020 at 09:10:03 UTC, Ali Çehreli wrote: On 6/2/20 1:56 AM, realhet wrote: > struct A{ >struct B{ int c; } >B b; > >auto f(){ > alias d = b.c; The spec explicitly says it's not legal: "Aliases cannot be used for expressions" (Item 10): https://dlang.org/spec/declaration.html#alias I use nested functions for such cases: auto f(){ auto d() { return b.c; } return d; } Ali Thanks for responses: I did it that way: private enum fieldMap = [ // simple names for descriptive and structured fields "hauteur" : "general.height", "rayon" : "profile.radius", "plage" : "profile.plage", "offsetv" : "profile.verticalOffset", "offseth" : "profile.horizontalOffset", "varrad0" : "profile.linearVariationBottom", "varrad1" : "profile.linearVariationTop", "amplitude" : "periphery.amplitude", "varlin0" : "periphery.linearVariationBottom", "varlin1" : "periphery.linearVariationTop", "varsinp" : "periphery.cosinusVariationPlage", "varsino" : "periphery.cosinusVariationOffset", "periodes" : "periphery.nbPeriods", "revolution": "periphery.turn" ]; static foreach(k, v; fieldMap){ mixin("@property auto $() const{ return #; }".replace("$", k).replace("#", v)); } //I know, i know -> AliasSeq :D But it doesn't look nice. I've found some additional info here: https://forum.dlang.org/thread/hresorfqicczofnrc...@forum.dlang.org?page=2 Seems like I must not except the same from an alias template paramater and from the alias construct. The alias construct is for a single symbol.
Making alias of a struct field needs "this".
Hello, I have a 2 level nested struct structure with nice descriptive field names. And I thought it will be easy to alias those identifierLists with a few letter names and do some calculations on them. But I'm having an error. struct A{ struct B{ int c; } B b; auto f(){ alias d = b.c; return d; //Compiler Error: need 'this' for c of type int. } } There's the this and it's called "b." Why is this? If I copy paste the aliased expression "b.c", it compiled fine. Thanks in advance!
Re: Getting FieldNameTuple including all base-classes.
On Wednesday, 20 May 2020 at 09:03:51 UTC, realhet wrote: On Wednesday, 20 May 2020 at 01:18:24 UTC, Paul Backus wrote: On Tuesday, 19 May 2020 at 23:15:45 UTC, realhet wrote: With this mod it also works with structs: template AllClasses(T){ static if(is(T == class)) alias AllClasses = Reverse!(AliasSeq!(T, BaseClassesTuple!T[0..$-1])); else alias AllClasses = T; }
Re: Getting FieldNameTuple including all base-classes.
On Wednesday, 20 May 2020 at 01:18:24 UTC, Paul Backus wrote: On Tuesday, 19 May 2020 at 23:15:45 UTC, realhet wrote: I think what you want is `std.meta.staticMap`. Something like this: alias FieldNameTuple2(T) = staticMap!(FieldNameTuple, BaseClassesTuple!T); class A { int a, a1; } class B : A { int b; } class C : B { int c, c1; } alias AllClasses(T) = Reverse!(AliasSeq!(T, BaseClassesTuple!T[0..$-1])); alias AllFieldNames(T) = staticMap!(FieldNameTuple, AllClasses!T); void main(){ static foreach(T; "ABC") mixin("AllFieldNames!"~T~".stringof.writeln;"); } That statticMap unlike the normal map, it also joins the AliasSeq at the end. Just what I needed. Thank You!
Getting FieldNameTuple including all base-classes.
Hi, I was able to reach all the fields in a subclass using foreach and BaseClassesTuple, but is there a way to do this using functional programming primitives, but in compile time for tuples? private template FieldNameTuple2(T) { enum FieldNameTuple2 = BaseClassesTuple!T.map!(S => FieldNameTuple!S).join; } This is obviously wrong, but is there a way to do it? I've searched for FieldNameTuple and BaseClassesTuple, but without luck. It's weird because it seems like a common thing to do. Thanks in advance!
Re: Handle FormatSpec!char in the virtual toString() method of a class.
On Thursday, 14 May 2020 at 19:01:25 UTC, H. S. Teoh wrote: On Wed, May 13, 2020 at 12:26:21PM +, realhet via Digitalmars-d-learn wrote: Thank You, very helpful!
Handle FormatSpec!char in the virtual toString() method of a class.
Hello, Is there a way to the following thing in a class instead of a struct? -- static struct Point { int x, y; void toString(W)(ref W writer, scope const ref FormatSpec!char f) if (isOutputRange!(W, char)) { // std.range.primitives.put put(writer, "("); formatValue(writer, x, f); put(writer, ","); formatValue(writer, y, f); put(writer, ")"); } } -- I think the problem is that the toString() in a class is virtual, and don't let me to have multiple overloaded methods. Is there a way to let format() deal with classes too? Thank You!
Is there an exception for access violation on LDC/win64?
Hi, import std.stdio, std.exception; void main(){ class C{ void foo(){ writeln(123); } } C c; try{ writeln(1); c.foo;// access violation here writeln(2); }catch(Throwable t){ writeln("exception"); } writeln(3); } When I run this code (using LDC2 64bit Windows), it silently crashes where the access violation happens and returns an %ERRORLEVEL% value of -1073741795 (-0x3FE3). On the Online DLang Editor I get some more information: Error: /tmp/onlineapp-cf8e338-8b2478 failed with status: -2 Error: message: Segmentation fault (core dumped) Error: program received signal 2 (Interrupt) This is better, but is there a trick to turn these system errors to an exception, so I would be able to get the location where it crashed in my source code? The best I've found is this trick for Linux: https://forum.dlang.org/post/atxyappczlyvqyalv...@forum.dlang.org That error message would be so usefull, but is there a way to do it on windows?
Re: Using the functions "map" and "any" on tuples in compile time.
On Sunday, 12 April 2020 at 12:42:40 UTC, Harry Gillanders wrote: On Sunday, 12 April 2020 at 11:17:39 UTC, realhet wrote: I only remembered the __traits(identifier...), but completely forgot about the getMember. And I never heard of anySatisfy. My JSON serializer is beautiful now. Thank You very much!
Using the functions "map" and "any" on tuples in compile time.
Hello, anyone can help me make this better? The functionality I want to achieve is: While serializing the fields of a struct, I want it to check the @STORED UDA on every field. If there is no fields are marked with @STORED, that means every field must be serialized. Otherwise only the marked one. I had problems using map and any, so I come up with this lame foreach version: It works, but I think it does it in runtime. bool anySTORED = false; static foreach(fieldName; FieldNameTuple!T) mixin("anySTORED |= hasUDA!(data.*, STORED);".replace("*", fieldName)); static foreach(fieldName; FieldNameTuple!T){{ mixin("const thisSTORED = hasUDA!(data.*, STORED);".replace("*", fieldName)); if(thisSTORED || !anySTORED) mixin("streamAppend_json!(dense, fieldName)(st, data.*, nextIndent);".replace("*", fieldName)); }} Thanks in advance! (ps: I just love string mixins, I know :D)
Re: linking obj files compiled with LDC2 1.20.0 on Win64
On Tuesday, 24 March 2020 at 15:22:19 UTC, Steven Schveighoffer wrote: On 3/24/20 10:28 AM, realhet wrote: On Sunday, 22 March 2020 at 20:20:17 UTC, Steven Schveighoffer If this were Linux, I'd start using nm to search the object files for the symbol that is missing (like search for symbols defining hasToString), and see if it possibly might be mangled in a different way. I'm not sure what tools there are on Windows to do this. -Steve I've found a similar tool in MSVC, it's called DUMPBIN. I was able to find that the linker errors were correct: I wasn't able to find even smaller substrings of that std.format.hasToString symbol, it was called like 4 times. But I had a clue: A problem when trying to call hasToString on my struct, so I located all the references for that and I've found this thing: //infoArray.enumerate.each!writeln; //!!! LDC 1.20.0 win64 linker bug when using enumerate here! //foreach(i, a; infoArray) writeln(tuple(i, a)); //!!! linker error as well //foreach(i, a; infoArray) writeln(tuple(i, i+1)); //!!! this is bad as well, the problem is not related to own structs, just to tuples foreach(i, a; infoArray) writefln("(%s, %s)", i, a); //this works Now I know that [LDC 1.20.0 win64 -allinst] has a problem generating the code for tuple parameters in std.format calls. This was not a problem in 1.6.0 Now I go on and try my bigger projects.
Re: linking obj files compiled with LDC2 1.20.0 on Win64
On Thursday, 26 March 2020 at 14:52:36 UTC, Ferhat Kurtulmuş wrote: On Sunday, 22 March 2020 at 18:43:50 UTC, realhet wrote: Hello, I'm try to use the latest LDC2 version: 1.20.0 Previously I used 1.6.0 [...] Try to run the compiler in visual studio command line terminal. I set up the environment variables with "ldc2\bin\msvcenv amd64", it calls that command prompt implicitly. That couldn't be a problem.
Re: linking obj files compiled with LDC2 1.20.0 on Win64
On Tuesday, 24 March 2020 at 16:35:56 UTC, realhet wrote: On Tuesday, 24 March 2020 at 15:22:19 UTC, Steven Schveighoffer wrote: On 3/24/20 10:28 AM, realhet wrote: On Sunday, 22 March 2020 at 20:20:17 UTC, Steven Schveighoffer Now I have 2 of this: megatexturing.obj : error LNK2019: unresolved external symbol pure nothrow @nogc @safe void std.format.hasToString!( std.typecons.Tuple!( ulong, "index", const(het.megatexturing.SubTexInfo), "value" ).Tuple, char ).__lambda1().S.put(char) referenced in function pure scope @safe bool std.format.FormatSpec!(char).FormatSpec.writeUpToNextSpec!( std.format.hasToString!( std.typecons.Tuple!( ulong, "index", const(het.megatexturing.SubTexInfo), "value" ).Tuple, char ).__lambda1().S ).writeUpToNextSpec( ref std.format.hasToString!(std.typecons.Tuple!(ulong, "index", const(het.megatexturing.SubTexInfo), "value").Tuple, char).__lambda1().S ) And only with that format hasToString! template. I hope I can locate something along this: std.typecons.Tuple!( ulong, "index", const(het.megatexturing.SubTexInfo), "value" ) Maybe it refers to a function parameter list in my program. Something tells me that this should not be look like something recursive o.o I'll search for that Linux tool on windows that you mentioned...
Re: linking obj files compiled with LDC2 1.20.0 on Win64
On Tuesday, 24 March 2020 at 15:22:19 UTC, Steven Schveighoffer wrote: On 3/24/20 10:28 AM, realhet wrote: On Sunday, 22 March 2020 at 20:20:17 UTC, Steven Schveighoffer I managed to compile it with normal compilation. The -allInst flag may be the problem. I also had success by manual linking: ldmd2 -vcolumns -Ic:\D\libs\ -m64 -mcpu=athlon64-sse3 -mattr=+ssse3 -release -O -inline -boundscheck=off -of=c:\D\libs\het\hdmd\hdmd.obj c:\D\libs\het\hdmd\hdmd.d ... -c link /LIBPATH:c:\D\ldc2\lib64 /OUT:c:\D\libs\het\hdmd\hdmd.exe /MACHINE:X64 kernel32.lib user32.lib legacy_stdio_definitions.lib c:\D\libs\het\hdmd\hdmd.obj druntime-ldc.lib phobos2-ldc.lib msvcrt.lib So I will try to narrow the problem in Jsonizer.exceptions.d For a 11k LOC project with 10 .d files when I only modify a few top level d files, and I already have the .obj files for the rest, the compilation time is only 5-10 seconds instead of the 40 with the all in one compilation. I got used to this, so I will try anything to fix it :D
Re: linking obj files compiled with LDC2 1.20.0 on Win64
On Sunday, 22 March 2020 at 20:20:17 UTC, Steven Schveighoffer wrote: Make sure you don't have any stale objects left over in your project from the older build. Build everything clean from scratch. -Steve After narrowing the problem, I fixed all warnings, and deprecations, and I have only one linker error now: Compiler command line (LDC 1.20.0 Win64): ldmd2 -vcolumns -c -op -allinst -Ic:\D\libs\ -m64 -mcpu=athlon64-sse3 -mattr=+ssse3 -release -O -inline -boundscheck=off c:\D\libs\jsonizer\exceptions.d Linker command line: link /LIBPATH:c:\D\ldc2\lib64 /OUT:c:\D\libs\het\hdmd\hdmd.exe /MACHINE:X64 kernel32.lib user32.lib legacy_stdio_definitions.lib ***All the required obj files*** druntime-ldc.lib phobos2-ldc.lib msvcrt.lib Linker response (after demangling): Microsoft (R) Incremental Linker Version 14.23.28105.4 Copyright (C) Microsoft Corporation. All rights reserved. - exceptions.obj : error LNK2019: unresolved external symbol pure nothrow @nogc @safe void std.format.hasToString!(std.json.JSONValue, char).__lambda2().S.put(char) referenced in function pure nothrow @nogc @safe void std.range.primitives.put!(std.format.hasToString!(std.json.JSONValue, char).__lambda2().S, char).put(ref std.format.hasToString!(std.json.JSONValue, char).__lambda2().S, char) - I've searched for the hasToString template, but this seems way too complicated for me. This nested lambda template thing o.O Here is the source code for the exceptions.obj file: https://github.com/rcorre/jsonizer/blob/master/src/jsonizer/exceptions.d These are caused by some format() calls, I don't know why it is a problem now and it's totally OK with a 2017 version. This nested std.range.primitives.put is weird for me. Maybe it's a bug because by the -CompileAllTemplateInstances flag? (That's not the normal use, I know: I comile all the objs, and while I work, I only compile the ones that changed (recursively ofc), and finally link. It's much faster this way on a 8 core machine.).
Re: linking obj files compiled with LDC2 1.20.0 on Win64
On Sunday, 22 March 2020 at 20:20:17 UTC, Steven Schveighoffer wrote: Make sure you don't have any stale objects left over in your project from the older build. Build everything clean from scratch. -Steve Thx, I double checked this. Then I attempted to link from the commandline and it worked. o.O So there must be some weirdness in my build tool which is fine with LDC2 1.6.0 but fails with 1.20.0 :S
linking obj files compiled with LDC2 1.20.0 on Win64
Hello, I'm try to use the latest LDC2 version: 1.20.0 Previously I used 1.6.0 After fixing all the compiler errors and warnings, I managed to compile all the d source files to obj files, and I got 4 linking errors. I think all of them caused by the first 2: 1: msvcrt.lib(initializers.obj) : warning LNK4098: defaultlib 'libcmt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library 2: exceptions.obj : error LNK2019: unresolved external symbol _D3std6format__T11hasToStringTSQBd4json9JSONValueTaZ9__lambda2MFZ1S3putMFNaNbNiNfaZv referenced in function _D3std5range10primitives__T5doPutTSQBh6format__T11hasToStringTSQCj4json9JSONValueTaZ9__lambda2MFZ1STaZQCxFNaNbNiNfKQDdKaZv Anyone knows how to solve these? Please help me! I uploaded all the details to here: https://github.com/realhet/hetlib/blob/master/het/test/linkingerror.txt Or if there is info about how to use the Microsoft 64bit linker with the newest version of LDC2 please let me no. Or maybe an open source build tool that is up to date and I can extract the most recent linker parameters? Is there a new VS Community version requirement? I remember it was also tricky 2.5 years ago, since then it worked perfectly fine for me, but I just decided to use the latest LDC2 and bumped to this. Thank you for the assistance in advance!
Re: Getting the initial value of a class field in compile time.
On Sunday, 9 February 2020 at 02:25:56 UTC, Steven Schveighoffer wrote: On 2/8/20 7:39 PM, realhet wrote: On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote: On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote: Yea, I exactly ran into that "init" problem, I will avoid that, thx!
Re: Getting the initial value of a class field in compile time.
On Sunday, 9 February 2020 at 01:19:55 UTC, Paul Backus wrote: On Sunday, 9 February 2020 at 00:57:05 UTC, realhet wrote: On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote: On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe enum initValue = (new typeof(this)).tupleof[i]; Wow, thx! Accessing by index instead of name. Really powerful!