Re: DMD [-O flag] vs. [memory allocation in a synchronized class]
On Thursday, 8 June 2017 at 17:39:41 UTC, Ivan Kazmenko wrote: Reported: https://issues.dlang.org/show_bug.cgi?id=17481 Thank You!
Out of memory error (even when using destroy())
Hi, I'm kinda new to the D language and I love it already. :D So far I haven't got any serious problems but this one seems like beyond me. import std.stdio; void main(){ foreach(i; 0..2000){ writeln(i); auto st = new ubyte[500_000_000]; destroy(st); //<-this doesnt matter } } Compiled with DMD 2.074.0 Win32 it produces the following output: 0 1 2 core.exception.OutOfMemoryError@src\core\exception.d(696): Memory allocation failed It doesn't matter that I call destroy() or not. This is ok because as I learned: destroy only calls the destructor and marks the memory block as unused. But I also learned that GC will start to collect when it run out of memory but in this time the following happens: 3x half GB of allocations and deallocations, and on the 4th the system runs out of the 2GB limit which is ok. At this point the GC already has 1.5GB of free memory but instead of using that, it returns a Memory Error. Why? Note: This is not a problem when I use smaller blocks (like 50MB). But I want to use large blocks, without making a slow wrapper that emulates a large block by using smaller GC allocated blocks. Is there a solution to this? Thank You!
Re: Out of memory error (even when using destroy())
Thanks for the answer! But hey, the GC knows that is should not search for any pointers in those large blocks. And the buffer is full of 0-s at the start, so there can't be any 'false pointers' in it. And I think the GC will not search in it either. The only reference to the buffer is 'st' which will die shortly after it has been allocated. 64bit is not a solution because I need to produce a 32bit dll, and I also wanna use 32bit asm objs. The total 2GB amount of memory is more than enough for the problem. My program have to produce 300..500 MB of continuous data frequently. This works in MSVC32, but with D's GC it starts to eat memory and fails at the 4th iteration. Actually it never releases the previous blocks even I say so with destroy(). At this point I only can think of: a) Work with the D allocator but emulate large blocks by virtually stitching small blocks together. (this is unnecessary complexity) b) Allocating memory by Win32 api and not using D goodies anymore (also unnecessary complexity) But these are ugly workarounds. :S I also tried to allocate smaller blocks than the previous one, so it would easily fit to the prevouisly released space, and yet it keeps eating memory: void alloc_dealloc(size_t siz){ auto st = new ubyte[siz]; } void main(){ foreach(i; 0..4) alloc_dealloc(500_000_000 - 50_000_000*i); }
Re: Out of memory error (even when using destroy())
Jordan Wilson wrote: This I think achieves the spirit of your code, but without the memory exception: ubyte[] st; foreach(i; 0..2000){ writeln(i); st.length=500_000_000; // auto = new ubyte[500_000_000]; st.length=0; // destory(st) st.assumeSafeAppend; // prevent allocation by assuming it's ok to overrwrite what's currently in st } Yea, that's the perfect solution. It uses exactly the amount of memory that is required and still I'm using D things only. The only difference is that I need only one variable outside of the loop, but it's well worth it because I only need one large buffer at a time. Also refreshed my knowledge about assumeSafeAppend() which is now clear to me, thanks to You. Using this information I'll be able to do a BigArray class that will hold large amount of data without worrying that the program uses 3x more memory than needed :D Thanks for everyone, Such a helping community you have here!
Re: DMD [-O flag] vs. [memory allocation in a synchronized class]
On Thursday, 8 June 2017 at 10:48:41 UTC, ketmar wrote: worksforme with -O, and with -O -inline. I forgot to mention, that I'm generating win32 output. DMD32 D Compiler v2.074.0
DMD [-O flag] vs. [memory allocation in a synchronized class]
Hi, This code works well with the unoptimized compilation with DMD. import std.array; synchronized class Obj{ private int[] arr; void trigger(){ arr.length += 1; } } void main(){ auto k = new shared Obj; k.trigger; } And when I use the -O option, it shows the following error in the trigger() method: core.exception.InvalidMemoryOperationError@src\core\exception.d(696): Invalid memory operation Why? o.O
Re: DMD [-O flag] vs. [memory allocation in a synchronized class]
I've managed to narrow the problem even more: //win32 dmd -O class Obj{ synchronized void trigger(){ new ubyte[1]; } } void main(){ auto k = new shared Obj; k.trigger; } This time I got a more sophisticated error message: object.Error@(0): Access Violation 0x7272456D in SymInitialize 0x00402667 0x00402A97 0x00402998 0x004022A0 0x76F13744 in BaseThreadInitThunk 0x773B9E54 in RtlSetCurrentTransaction 0x773B9E1F in RtlSetCurrentTransaction
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Friday, 8 June 2018 at 02:44:13 UTC, Mike Parker wrote: ...you can get it with this: dmd -m64 -L/SUBSYSTEM:console -L/ENTRY:WinMainCRTStartup foo.d Thank You! It works with LDC -m64 as well. And now that I repaired my VCRedist2015 the bat file test (my second code example) is working too.
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Friday, 8 June 2018 at 03:08:21 UTC, Mike Franklin wrote: I recall similar issues with a project I was working on, but I don't remember all the details now. Anyway, I ended up with this in the end. Using main() instead of WinMain() did the trick too. Also it's simpler, so I choose this way. But it was also important to learn about the SUBSYSTEM and ENTRY linker options. Thank you all very much!
Using stdin/out in a windows application bugs only when compiled to 64bit.
Hi, The following narrow test program works fine when compiled with DMD to 32bit target: import std.stdio, core.sys.windows.windows, core.runtime; extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { Runtime.initialize; writeln("Hello"); stdout.flush; //exception readln; //exception return 0; } It shows the console window and waits for user input at readln. If I try to compile this to 64bit target or with LDC (both 32 and 64) it gets privileged instruction exception at stdout.flush. If I comment out flush then it fails at readln. Is there a way to fix this? I don't wanna lose the console window even on 64bit. Thanks!
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Thursday, 7 June 2018 at 19:42:05 UTC, Steven Schveighoffer wrote: Are you just compiling the 32-bit dmd version with default flags? Yes, no flags at all and it defaults to a 32bit target. I can use the console and able to make windows, and able to setup an opengl window too. The console (stdin/stdout/SetConsoleAttribute) stuff crashes only when I compile to 64bit with DMD or to 32/64 with LDC. If so, it's likely an issue with MSVC runtime library not being properly set up. DMD 32 bit by default uses DMC runtime. I just tried to put up msvcrt2017 runtime but doesnt solved the issue. To verify, use the switch -m32mscoff to do 32-bit result but link against MSVC library. Compiling this way is impossible: It can't link even basic stuff like GetDC(). I know this isn't really an answer, but it at least narrows it down. Been a while since I did windows development, but it sounds like you are trying to print to or read from a console that isn't open. A windows program that has gui-only flag doesn't by default allocate a console. Most likely dmc just does it for you. To be honest I don't use gui-only flag as I don't even know about where to put it :D (.def file maybe, but I don't). I use core.Runtime.initialize only. That is enough in 32bit but not in 64bit. My goal is to have a fully functional exe that contains every necessary things inside it. So far this is given when I use DMD and compile to win32. The error I'm getting is not a 'friendly' exception. It is a privileged instruction crash. And it caused only by adding the -m64 option, not changing anything else. The linking is done by DMD itself also. (If I link with msvcenv.bat && MSLink.exe, it produces also the same fail.)
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Thursday, 7 June 2018 at 23:25:45 UTC, Steven Schveighoffer wrote: ... The WinMain exported function works alone well and on 32bit it also does the console. On 64 I also tried AllocConsole, but fail. I get the Console handle with GetConsoleHandle, it sends back a nonzero value. But as I play with it, now I can broke it even when I only use main() as export. This bat file runs(dmd and visual-d installed to default c:\d path) (It only affects LDC & win64) echo void main(){ import std.stdio; writeln(123); } > test.d ldmd2 -vcolumns -c -op -allinst -w -m64 -release -O -inline -boundscheck=off test.d call msvcenv amd64 cd c:\d link /LIBPATH:C:\d\ldc2\lib64 /OUT:test.exe /MACHINE:X64 /MAP legacy_stdio_definitions.lib test.obj druntime-ldc.lib phobos2-ldc.lib msvcrt.lib test.exe And when I want to run the same exe from outside with totalcommander, it brings up an "application was unable to start: 0xc0fb exception in a small window o.O. UPDATE: The exe only starts when "msvcenv.bat amd64" was called before. That enironment setter bat file is needed for the exe as well o.O I really thank you for trying to help me. Maybe that other different runtime you mentioned is using environment variables to be able to start up. Tomorrow I will test it.
Re: DMD Windows 64bit target - how to setup the environment?
Thank You for fast help! I just reply late because I wanted to try out many things. With Benjamin's list it was indeed easy to set up the environment. I also installed LDC and it worked without problems too. Made some tests about sse vectorization and it turned out that I'm in love with LDC now :D ( https://realhet.wordpress.com/2017/12/29/my-first-impressions-of-64-bit-dlang-compilers/ ) The next thing I wanna test is compiling speed. As you said, DMD is fast enought to let it just compile all the project in one run, because it reuses a lot of data it discovered through the compiling process. However I had a lot of experiences with Delphi which is a really fast one (at least on 32bits, without sse vectorization), and on top of that is uses incremental compilation. Later I got to Qt+MSVC, and noticed that my 40K LOC not-so-big project takes 40 seconds to compile and another 10 to launch in the debugger. At the time when the program started, I already forgot why I started it to debug, lol. So that's why I was happy to find D, an elegant language that compiles fast, (not as fast as Delphi, 'though, but it is really comparable to it). So for development, I made a small incremental build manager thingie: It launches a DMD for each of the modules, that aren't in its cache. For a 6K LOC, 220KB project i was able to test, it works well: When I modify a only high level module, it only takes 3 seconds to launch, not 7 while I build it once with DMD. When the object cache is empty, it takes 6 seconds on all 8 cores, but it has to be done only once. On Delphi I had usually 0.5sec launch times when I changed only a few units, so if I have to choose 7 secs of 3 secs, then it's not even a question. Anyways, Thank You for help again!
DMD Windows 64bit target - how to setup the environment?
Hello, I'm very well satisfied with the DMD 32bit compiler and the OptLink linker on Windows. I even made an incremental builder to it, and I can see the running program in 1 second. Lately I sadly noticed, that the OptLink works only for 32bit target, and I need to go to 64bit if I want to have access to the SIMD instructions on vector operations. So this is what I've tried so far: - Installed visual C++ 2010. - Installed Windows SDK 7.1 (don't know why, 'though) -> Error: dmd cant find "\bin\link.exe" - Added environment variable: set VCINSTALLDIR=c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC -> Error: Can't load mspdb100.dll - Added set PATH=%PATH%;c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE -> Error: LNK1104: cannot open file 'libcmt.lib' - copied it to c:\D\dmd2\windows\lib64 (yes, I really desperately want it to work lol) -> Error: LNK1104: OLDNAMES.lib, shell32.lib - copied these too And finally got the error: -> libcmt.lib(fdopen.obj) : fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64' So I've searched through the whole C drive and this 32bit one was the only libcmt.lib. The linker is located at: "c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe" There is no amd64 folder near to it at all. Obviously I'm doing something wrong because a trivial task like changing target to 64bit can't be so complicated. Please help and tell me how to do it properly! Thanks in advance!
Re: DMD Windows 64bit target - how to setup the environment?
Now I have my first DMD 64bit windows console app running. (And I'm already afraid of the upcoming windowed application haha) After further fiddling I installed the >>>Visual Cpp tools 2015<<< package that contains a linker with x64 stuff in it (along with several GB of bloatware). contents of test64bit.d: import std.stdio; void main(){writeln("Hello 64");} compiling: dmd test64bit.d -c -op -allinst -vcolumns -m64 linking: "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\link.exe" /MACHINE:X64 /SUBSYSTEM:CONSOLE test64bit.obj /LIBPATH:c:\D\dmd2\windows\lib64 /LIBPATH:"c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64" /LIBPATH:"c:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x64" /LIBPATH:"c:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64" legacy_stdio_definitions.lib (note: legacy_stdio_definitions.lib contains sprintf and sscanf)
append uninitialized elements to array
Hello, I've already found out how to create an array with uninitialized elements, but what I'm looking for is a way to append 16 uninitialized ushorts to it and after I will it directly from 2 SSE registers. The approximate array length is known at the start so I could be able to do this by making an uninitializedArray and then doing the appending manually, but I wonder if there is a way to do this with array.reserve(). Basically it would be a thing that when this special uninitialized append is happening and when the reserved array size is big enough, it only increments the internal array length effectively. Thanks
Re: append uninitialized elements to array
Thank You!
Re: strip() and formattedRead()
On Wednesday, 21 March 2018 at 18:50:18 UTC, Adam D. Ruppe wrote: On Wednesday, 21 March 2018 at 18:44:12 UTC, realhet wrote: Compiling this I get an error: "formattedRead: cannot deduce arguments from (string, string, float, float, float)" What compiler version are you using? The newest versions allow this code, though the old ones require an intermediate variable to satisfy the `ref` requirement on formattedRead (it will want to update that variable to advance it past the characters it read). so either update your version, or just give an and use an intermediate: string s = "".strip; formattedRead(s, ) Thank both of You! You guys are super helpful. (I'm learning from Ali's book and after these instant answers I was like: "I'm not worthy" :D) So I had v2077.1 previously, now I've installed 2079.0 and it all works great.
strip() and formattedRead()
Hi, I just got this problem and since an hour can't find answer to it. float x,y,z; if(formattedRead("vertex -5.1 2.4 3.666".strip, "vertex %f %f %f", x, y, z)){ writefln("v(%f, %f, %f)", x, y, z); } Compiling this I get an error: "formattedRead: cannot deduce arguments from (string, string, float, float, float)" When I don't use .strip(), just a string literal or a string variable it works good. (It fails also when I'm using UFCS) What did I do wrong?
Problem with opBinary
Hi, Just a little weird thing I noticed and don't know why it is: I have a FilePath struct and I wanted to make it work with the "~" operator and an additional string. So I've created a global funct: FilePath opBinary(string op:"~")(FilePath p1, string p2){ return FilePath(p1, p2); } The problem is that this funct is only callable with the following code: auto vlcPath = programFilesPath.opBinary!"~"(`VideoLAN\VLC`); And it is not callable using the ~ operator directly. It says unable to call with types FilePath and string When I rewrite the opBinary funct as a member of the FilePath struct, everything is working fine. The problem is only happening when opBinary is a global funct. (I'm using LDC Win64) Is it a bug or is there an explanation to this?
Re: Problem with opBinary
Thanks, this make it clear. (This also explains the existence of opBinaryRight)
Re: LDC2 win64 calling convention
On Wednesday, 28 November 2018 at 21:58:16 UTC, kinke wrote: You're not using naked asm; this entails a prologue (spilling the params to stack etc.). Additionally, LDC doesn't really like accessing params and locals in DMD-style inline asm, see https://github.com/ldc-developers/ldc/issues/2854. You can check the final asm trivially online, e.g., https://run.dlang.io/is/e0c2Ly (click the ASM button). You'll see that your params are in R8, RDX and RCX (reversed order as mentioned earlier). Hi again. I just tried a new debugger: x64dbg. I really like it, it is not the bloatware I got used to nowadays. It turns out that LDC2's parameter/register handling is really clever: - Register saving/restoring: fully automatic. It analyzes my asm and saves/restores only those regs I overwrite. - Parameters: Reversed Microsoft x64 calling convention, just as you said. Parameters in the registers will be 'spilled' onto the stack no matter if I'm using them by their names or by the register. Maybe this is not too clever but as I can use the params by their name from anywhere, it can make my code nicer. - Must not use the "ret" instruction because it will take it literally and will skip the auto-generated exit code. In conclusion: Maybe LDC2 generates a lot of extra code, but I always make longer asm routines, so it's not a problem for me at all while it helps me a lot.
LDC2 win64 calling convention
Hi, Is there a documentation about the win64 calling convention used with LDC2 compiler? So far I try to use the Microsoft x64 calling convention, but I'm not sure if that's the one I have to. But it's not too accurate becaues I think it uses the stack only. https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention I'm asking for Your help in the following things: 1. Is there register parameters? (I think no) 2. What are the volatile regs? RAX, RCX, RDX, XMM6..XMM15? 3. Is the stack pointer aligned to 16? 4. Is there a 32 byte shadow area on the stack? Thank you!
Re: LDC2 win64 calling convention
Thank You for the explanation! But my tests has different results: void* SSE_sobelRow(ubyte* src, ubyte* dst, size_t srcStride){ asm{ push RDI; mov RAX, 0; mov RDX, 0; mov RCX, 0; //clear 'parameter' registers mov RAX, src; mov RDI, dst; //gen movups XMM0,[RAX]; movaps XMM1,XMM0; pslldq XMM0,1; movaps XMM2,XMM1; psrldq XMM1,1; pavgb XMM1,XMM0; pavgb XMM1,XMM2; movups [RDI],XMM1; //gen end pop RDI; }} When I clear those volatile regs that are used for register calling, I'm still able to get good results. However when I put "mov [RBP+8], 0" into the code it generates an access violation, so this is why I think parameters are on the stack. What I'm really unsire is that the registers I HAVE TO save in my asm routine. Currently I think I only able to trash the contents of RAX, RCX, RDX, XMM0..XMM5 based on the Microsoft calling model. But I'm not sure what's the actual case with LDC2 Win64. If my code is surrounded by SSE the optimizations of the LDC2 compiler, and I can't satisfy the requirements, I will have random errors in the future. I better avoid those. On the 32bit target the rule is simpe: you could do with all the XMM regs and a,c,d what you want. Now at 64bit I'm quite unsure. :S
Multitasking question: Making a picture viewer, loading lots of images in the background
Hi, I'm writing a picture browser program and I'd like to ask for a bit of assistance. My app is basically a Win32 window with an OpenGL surface. Currently I'm able to display a lot of pictures in it. The decompression of the bitmaps take place at the beginning of the program. I want to make this more user friendly, so at first I only draw placeholders for the pictures while the actual loading and decompression is happening on worker threads. I used std.concurrency.spawn. The parameters are the filename, and an index. After the decompression I let the main thread know about there is a bitmap it should upload to a texture later. I do it using synchronize, it works without error and was really easy to implements in D. My problem is that when I launch 1000 spawn(), the work overload on the main thread is so heavy that the 60FPS timer which is refreshing the windows never can be called. Obviously spawn() is not the right choice for this. In my previous projects I addressed this by creating NumberOfProcessorThreads threads,and locked them on specific ProcessorThreads by using ProcessAffinity, so the main thread has enough time to generate fluid user interface while the other worker threads used 100%CPU for the fastest processing. I also remember that with OPENMP I was also able to lock workers onto specific ProcessorThreads, it also worked fine. But how can I do this elegantly in D? Thanks in advance! (Also I'm not sure how spaw()-n is working exactly. Is it creates a new process for every spawn() call, or is it assigns the task to one of the N worker processes? 1000 CreateProcess() api calls would be not so nice. I just wanna know it in order to avoid it.)
Re: Multitasking question: Making a picture viewer, loading lots of images in the background
On Wednesday, 3 April 2019 at 04:09:45 UTC, DanielG wrote: My understanding is that there's no benefit to creating more than the number of hyperthreads your CPU Yes. I'm just searching for a higher abstraction to manage this easily in D. I've already did it years ago on Delphi. (-> Manage N worker threads, and only put light stress on the thread which is running on the same core as the main thread.) Later it was easier to make it in OpenMP, and now I'm just looking for an even prettier way in DLang. Also it's good to know what happens inside. I've checked Resource Monitor, and as you said, the thread count reached above 1000 in the first 3 seconds of running the program. But after that something unusual happens: While my overall CPU usage was still high, the number of threads dropped down to 15, and the remaining 20 seconds of processing was don like this. But still, while all the processing, the main thread got no cpu% at all, it was able to render only the very first frame, the one that displayed the empty 'loading in progress' images. After 23 sec I was able to see all the 1000 pictures. You should probably be looking at std.parallelism (TaskPool etc) for this. Thank you for mentioning, this std.parallelism.Task.executeOnNewThread will be the next test. Is that behaving the same way like 'spawn'? From its name, I don't think so, but I'll find out.
check if _argument[0] is a descendant of a specific class.
Hi, I'm googling since an hour but this is too much for me: class A{} class B:A{} void foo(...){ if(_arguments[0]==typeid(A)){ //obviously not works for B } if(_arguments[0] is_a_descendant_of A){ //how to make it work for both A and B? } } -- Also I tried to write a funct to compare classes by TypeInfo, but the TypeInfo.next field is not works in the way as I thought. It gives null, so the following code doesn't work. auto isClass(C)(TypeInfo i){ if(i==typeid(C)) return true; auto n = i.next; return n is null ? false : n.isClass!C; } I just wanna check if a compile_time _argument[0] is a descendant of a class or not. I also tried (is : ) but without luck. Thank you.
Variadic template parameters, refactor a long chain of static if's to 'functions'.
Hi again, I'm trying to do variadic parameter processing, and I have the following function that works fine: static bool same(T1, T2)(){ pragma(msg, "same? "~T1.stringof~" "~T2.stringof); return is(immutable(T1)==immutable(T2)); } Btn btn(T...)(string params, T args){ enum captureIntID = true, captureBoolEnabled = true, captureFunct = true; Args r; //Arg is a struct to store all the possible parameters in runtime static foreach(a; args){ //process id parameter static if(same!(typeof(a), id)) r.id = a.val; else static if(captureIntID && (same!(typeof(a), int) || same!(typeof(a), uint))) r.id = a; //process enabled/disabled else static if(same!(typeof(a), enabled )) r.enabled = a.val; else static if(same!(typeof(a), disabled)) r.enabled = !a.val; else static if(captureBoolEnabled && same!(typeof(a), bool) ) r.enabled = a; //process data events else static if(same!(typeof(a), onClick )) r.events.onClick = a.f; else static if(same!(typeof(a), onPress )) r.events.onPress = a.f; else static if(same!(typeof(a), onRelease)) r.events.onRelease = a.f; else static if(same!(typeof(a), onChange )) r.events.onChange = a.f; else static if(same!(typeof(a), onTrue )) r.events.onTrue = a.f; else static if(same!(typeof(a), onFalse )) r.events.onFalse = a.f; else static if(same!(typeof(a), onBool )) r.events.onBool = a.f; else static if(typeof(a).stringof.startsWith("void delegate()")) r.events.onClick = a; else static if(typeof(a).stringof.startsWith("void delegate(bool)")) r.events.onBool = a; else static assert(false, "Unsupported type "~typeof(a).stringof); } return new Btn(params, r.id, r.enabled, r.events); } The long chain of is's are required to be able to show the error message at the end when an unhandled parameter type is found. I will have more of these and want to reuse these ifs in other functions as well, so I decided to take out the first 2 if's and put it into a template function: static bool processId(bool captureIntId, alias r, alias a)(){ mixin("alias ta = typeof("~a.stringof~");"); pragma(msg, "ta "~ta.stringof); static if(same!(ta, id)) { r = a.val; return true; } else static if(captureIntId && (same!(ta, int) || same!(ta, uint))) { r = a; return true; } else return false; } later I call it with: static if(processId!(true, r.id, a)){} else static if(... 'a' is the variadic foreach variable (_param_1 and so on), 'r.id' is the result field from an Arg structure. Both 'a' and 'r.id' are existing and compiling, also the pragma messages are good, I see it can find the right types, but I have the following error for every variadic parameter: Error: template instance processId!(true, id, _param_1) processId!(true, id, _param_1) is nested in both Args and btn id is a struct. And also a field in the Args struct. I changed it to id1 in the Args struct ant the error remains the same. Everything resides in the scope of a class called ContainerBuilder. Is there a way to do this elegantly? Maybe if I put everything in a very large chain of if's and enable the required parameters with a set of flags, but that's not structured well, and also needs the biggest possible set of runtime parameter storage to store the processed parametest. Here's an example using the above function: btn(`Yes flex=1`, id(54231), enabled(true), { lastClickedBtn = "Yes"; hehe = true; }) checkbox("Checkbox_1", 12345432, (bool b){ hehe = b; }) I will have a lot of controls and a lot of parameter types. I wanna do something like in the old VisualBasic, where you can skip a lot of default parameters, and also access the only few you need by name. Something like this: btn("caption", hint:"blabla", icon:"icon.ico"), but as I currently know this is not implemented in D. Thank You in advance!
Re: check if _argument[0] is a descendant of a specific class.
On Saturday, 8 June 2019 at 21:25:41 UTC, Adam D. Ruppe wrote: On Saturday, 8 June 2019 at 21:24:53 UTC, Adam D. Ruppe wrote: _arguments is a compile time construct, it is a run time thing. err i meant is *NOT* a compile time construct Thank You for the fast help! At first I was happy to find the variadic example and didn't even realized, that was the runtime version. Now it works correctly with the base class check, and also it is now static and fast: static foreach(a; args){ static if(is(typeof(a)==string)){ //... }else static if(is(typeof(a) : Cell)){ if(a !is null){ //... } }else static if(is(typeof(a)==TextStyle)){ //... }else{ static assert(0, "Unsupported type: "~typeof(a).stringof); } }
Re: Variadic template parameters, refactor a long chain of static if's to 'functions'.
On Tuesday, 11 June 2019 at 13:22:26 UTC, Adam D. Ruppe wrote: On Tuesday, 11 June 2019 at 09:26:56 UTC, realhet wrote: static bool processId(bool captureIntId, alias r, alias a)(){ mixin("alias ta = typeof("~a.stringof~");"); As I have been saying a lot, mixin and stringof should almost never be used together. You could write this a lot easier: ... Thank you for the long example, it helped me a lot! The thing is now capable of: - getting a specific type of parameter -> args.paramByType!(string[int]).writeln; - including wrapper structs. In that case, optionally can fall back to the type inside the struct. - handle and call events (structs or fallback as well) - It is super easy now to make a function that can process a specific set of events: struct onClick { void delegate() val; } ... struct onHold { void delegate() val; } void processBtnEvents(T...)(bool click, bool state, bool chg, T args){ if(click) args.paramCall!(onClick, true/*fallback to pure delegate*/); if(state) args.paramCall!onHold; if(chg){ args.paramCall!onChange; if(state) args.paramCall!onPress; else args.paramCall!onRelease; } } - Also I've found a way to exchange state values (for example a bool for a CheckBox control): - I can give it a pointer to a bool - Or I can give a getter and 0 or more setter(s): bool delegate(), void delegate(bool) - Can be functionPointers too, not just delegates. - example: void fIncrementer(T...)(T args){ paramGetterType!T x; args.paramGetter(x); x = (x + 1).to!(paramGetterType!T); args.paramSetter(x); } - it is letting me use enumerated types too -> I will not have to write anything, and there will be an automatic RadioButtonGroup on the screen, just bu mentioning that variable. It will be awesome! - Sorry for the lot of string processing and some mixin()s :D At the end of the code below, I've learned a lot while being able to write nicer code. Thank you for your example code, I've learned a lot from it. -- private{ bool is2(A, B)() { return is(immutable(A)==immutable(B)); } bool isBool (A)(){ return is2!(A, bool ); } bool isInt (A)(){ return is2!(A, int ) || is2!(A, uint ); } bool isFloat (A)(){ return is2!(A, float ) || is2!(A, double); } bool isString(A)(){ return is2!(A, string); } bool isSimple(A)(){ return isBool!A || isInt!A || isFloat!A || isString!A; } bool isGetter(A, T)(){ enum a = A.stringof, t = T.stringof; return a.startsWith(t~" delegate()") || a.startsWith(t~" function()"); } bool isSetter(A, T)(){ enum a = A.stringof, t = T.stringof; return a.startsWith("void delegate("~t~" ") || a.startsWith("void function("~t~" "); } bool isEvent(A)(){ return isGetter!(A, void); } //event = void getter bool isCompatible(TDst, TSrc, bool compiles, bool compilesDelegate)(){ return (isBool !TDst && isBool !TSrc) || (isInt !TDst && isInt !TSrc) || (isFloat !TDst && isFloat !TSrc) || (isString!TDst && isString!TSrc) || !isSimple!TDst && (compiles || compilesDelegate); //assignment is working. This is the last priority } } auto paramByType(Tp, bool fallback=false, T...)(T args){ Tp res; enum isWrapperStruct = __traits(hasMember, Tp, "val") && Fields!Tp.length==1; //is it encapsulated in a wrapper struct? -> struct{ type val; } enum checkDuplicatedParams = q{ static assert(!__traits(compiles, duplicated_parameter), "Duplicated parameter type: %s%s".format(Tp.stringof, fallback ? "("~typeof(Tp.val).stringof~")" : "")); enum duplicated_parameter = 1; }; static foreach_reverse(idx, t; T){ //check simple types/structs static if(isCompatible!(typeof(res), t, __traits(compiles, res = args[idx]), __traits(compiles, res = args[idx].toDelegate))){ static if(__traits(compiles, res = args[idx])) res = args[idx];else res = args[idx].toDelegate; mixin(checkDuplicatedParams); }else //check fallback struct.val static if(fallback && isWrapperStruct && isCompatible!(typeof(res.val), t, __traits(compiles, res.val = args[idx]), __traits(compiles, res.val = args[idx].toDelegate))){ static if(__traits(compiles, res.val = args[idx])) res.val = args[idx]; else res.val = args[idx].toDelegate; mixin(checkDuplicatedParams); } } static if(isWrapperStruct) return res.val; else return res; } void paramCall(Tp, bool fallback=false, T...)(T args){ auto e = paramByType!(Tp, fallback)(args); static assert(isEvent!(typeof(e)), "paramCallEvent() error: %s is not an event.".format(Tp.stringof)); if(e !is null) e(); } template paramGetterType(T...){ static foreach(t; T){ static
Re: Can I remove an element from a global associative array from within a class destructor?
On Saturday, 3 August 2019 at 05:33:05 UTC, Jonathan M Davis wrote: On Friday, August 2, 2019 5:13:10 PM MDT realhet via Digitalmars-d-learn wrote: Hi, ... Thank you! Now I have 2 solutions in mind: 1. If I only want to track the count and totalBytes for a specific kind of reference, I will be able update those from the destructor. 2. If I wanna track all instances of resources, I will use 2 classes instead of one class and an associative array: - When I create a resource, I create class1 for the statistics, and store them in an assocArray. Then I create a class2 and inside it there is a reference to class1. Class2 will be given to the user. If the user don't use it anymore, the GC will destroy class2, and in it's destructor it will mark a field in class1. And it will be periodically checked, so the actual deletion of the GLBuffer and other statistics will be done by me. With millions of resources it will be slow, but for a few thousand it's ok. (I can also put them in a hierarchy, but the most important is not to alloc/dealloc from ~this()) I hope it will be stable :D Thank You again!
Can I remove an element from a global associative array from within a class destructor?
Hi, I tried to make some resource statistict for my OpenGL Buffer objects: //here are the things that hold the statistics. private __gshared{ size_t[int] textureSizeMap, bufferSizeMap; } struct GLCounters{ int programs, shaders, textures, buffers; size_t textureSize, bufferSize; } __gshared GLCounters glCounters; ... //And this is the buffer creation. int genBuffer(size_t size){ int res; glGenBuffers (1, ); glChk; glCounters.buffers ++; glCounters.bufferSize += size; bufferSizeMap [res] = size; writefln("buffer allocated %d %d", res, size); return res; } //Finally, this is the deallocation. If it is called from the GC (when it destroys a class), it has a big chance to throw an Invalid Memory Operation exception. void deleteBuffer (int handle){ if(!handle) return; glDeleteBuffers (1, ); glChk; glCounters.buffers --; glCounters.bufferSize -= bufferSizeMap [handle]; writefln("buffer deallocated %d %d", handle, bufferSizeMap [handle]); bufferSizeMap.remove(handle); <- this is the problematic part. } Today I read the documentation about structs, unions and classes, but I haven't find any restrictions for the ~this() destructors. Is there some extra rules regarding the GC and what I must not do in the destructors? I think the destructor always called in the same thread where the instance was created. This can't be the case. But what I can guess is: The GC makes a collection and calls my destructor and inside I do something and the GC calls a collection again recursively. But it seems a bit crazy, so I think it's not the case :D Please help me solve this! *I'm using LDC 1.6.0 Win64
How to create a custom max() function without the ambiguity error.
Hi, I'm trying to use a popular function name "max", and extend it for my special types: For example: module utils; MyType max(in MyType a, in MyType a){...} //static function struct V3f{ V3f max(in V2f b){...} //member function } module gl3n; vec3 max(in vec3 a, in vec3 a) //another static function in different module I also want to use std.algorithm.comparison.max as well. I know that the ambiguity error can be avoided by public importing all the various max implementations into one place, but how to do this when I want to use 3 modules? Need a 4th module to combine them all? Is there a nicer way? Another question that is it possible to extend the the template function "to" in more than one module and use it easily from my main project modules?
Re: How to create a custom max() function without the ambiguity error.
On Friday, 6 December 2019 at 13:04:57 UTC, Ferhat Kurtulmuş wrote: On Friday, 6 December 2019 at 12:34:17 UTC, realhet wrote: Hi, I'm trying to use a popular function name "max", and extend it for my special types: For example: module utils; MyType max(in MyType a, in MyType a){...} //static function struct V3f{ V3f max(in V2f b){...} //member function } module gl3n; vec3 max(in vec3 a, in vec3 a) //another static function in different module I also want to use std.algorithm.comparison.max as well. I know that the ambiguity error can be avoided by public importing all the various max implementations into one place, but how to do this when I want to use 3 modules? Need a 4th module to combine them all? Is there a nicer way? Another question that is it possible to extend the the template function "to" in more than one module and use it easily from my main project modules? how about this: import std.stdio; import std.algorithm.comparison: max1 = max; int max(int a, int b){ // dummy max return 5; } void main(){ int a = 2; int b = 3; max1(a, b).writeln; // writes 3 } Thx for answering! This is what I want to avoid: To use extra identifiers or imports for the same semantic task. module m1; public import std.algorithm.comparison: max; struct MyType{ int x;} MyType max(in MyType a, in MyType a){ return a.x>b.x ? a : b; } module main; import m1; From here: the max() is working for MyType and also for the types supported by std.algo.comparison.max. BUT! What if I want to import another module which is overloading max?! It will be an ambiguity between m1 and the other module. I'm searching for a clever solution, not just manually reimporting everything in every module where I use multiple modules which also manually reimporting those simple names like 'max'.
Re: How to create a custom max() function without the ambiguity error.
On Friday, 6 December 2019 at 14:55:18 UTC, Ferhat Kurtulmuş wrote: On Friday, 6 December 2019 at 13:25:24 UTC, realhet wrote: On Friday, 6 December 2019 at 13:04:57 UTC, Ferhat Kurtulmuş wrote: [...] Thx for answering! [...] In d you can also use scoped imports: https://dlang.org/spec/module.html#scoped_imports Yea, I know about that. I also read the documentation about module imports, but in reality it feels like a bit different. Here's my latest attempt on EXTENDING std.algorithm.max's functionality with a max operation on a custom type. The type is the GLSL vec2 type which does the max operation component-wise. The D std implementation uses the < operator, but with overriding that for my custom type it is impossible to realise. -> max(vec2(1, 2), vec2(2,1)) == vec2(2,2) //So here is my helper module: - module testimport_a; import std.algorithm; struct vec2{ float x, y; } auto max(in vec2 a, in vec2 b){ return vec2(max(a.x, b.x), max(a.y, b.y)); } import std.algorithm: max; // and the main module module testimport_main; import std.stdio, testimport_a; void main(){ auto a = vec2(1, 2), b = vec2(0, 5); max(a, b).writeln; max(1, 2).writeln; } -- Both of the max instructions are working nicely. But here are all the things/restrictions which aren't as nice: - in the imported module it is really important, to put my max() function BEFORE the std one. The std implementation tries to serve EVERYTHING, but it fails the compilation when it check the < operator (which is non-existent on 2d vectors). - It doesn't matter if I use public import or not. When it finds any compatible max() inside the helper unit's functions, and its imported functionst that are specified by name, it will compile it. - It is really important to import the original max() by name. (After my narrower max()) - If I import std.algorithm in the main module, no matter the order, it will fail. As the std.algorithm.max alone is unable to serve vec2 types. - I tried to make one more module, to be able to use max on vec2, vec3 and everything else, but I failed. none of the my random guessing worked.
Map, filter and pure functions
Hi, I have an input range. I use the map! on it to transform using a function. Finally I use filter! on the transformed data. When I do a foreach on this, i noticed, that the transform function is called twice for each element. If I remove the filter! it does only one transform function call per element. Is this because the function is NOT PURE, so Phobos thinks that the function can give different results for the same input? If I modify the function to be pure, will the transform function be called only once?
Re: Map, filter and pure functions
On Friday, 29 November 2019 at 15:30:22 UTC, realhet wrote: ... Unfortunately function purity is not the answer. I put a very long calculation into the transform function which is called from "map!". And the "filter!" is making the "map!" call my function 2 times: First for the "filter!" to decide it allows the element or not. And second when the map! is passing it to the foreach() where I write the elements out. Is there a solution for this performance issue? Using functional programming, my program looks beautiful. But I need it to be optimal too. //To be easier to understand, I want to make the following: foreach(a; input){ auto temp = slowFunction(a); if(check(temp)) writeln(temp); } //But the elegant functional form -> input.map!slowFunction.filter!(a => check(a)).each!writeln; //Produces the following unoptimal solution: foreach(a; input){ if(check(slowFunction(a))) writeln(slowFunction(a)); } Is there a functional way to fix this? Thank you in advance!
Re: Map, filter and pure functions
On Friday, 29 November 2019 at 15:49:24 UTC, Paul Backus wrote: It's actually a much simpler reason: filter calls .front twice for each element in its input (once to check if the value satisfies the predicate, and then again to return the value if it does), and the range returned by map doesn't save the value of .front between calls, so it has to re-compute it each time by calling the transform function. This makes it clear. In my case a cache which can access all the previous elements would be a too big thing, so I will do the filtering in a later stage manually. But most importantly, now I know what's going on, Thank You!
Re: Getting the initial value of a class field in compile time.
On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe wrote: On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote: classinfo.m_init can be an option, but maybe there's a nicer way to do this? eh the initializer i think is the best. you can sometimes shortcut it pragma(msg, (new A).i); which will call the ctor at ctfe and get the value. but if there isn't a default constructor that's harder. (of course at runtime you can yank it out of the init member... but ctfe will fail that i believe because of the reinterpret cast involved). i can't think of a better way right now. Thank you! It works! Somehow I thought that 'new' is too much in CTFE, now I can rethink that.
Re: Getting the initial value of a class field in compile time.
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 wrote: Using what I've learned: class A{ int i=42; void init(){ // reInitialize class fields alias T = typeof(this); mixin([FieldNameTuple!T].map!(n => n~"=(new T)."~n~";").join); } } (I also like to live dangerously with string mixins :D)
Getting the initial value of a class field in compile time.
Hello, class A{ int i = 42; } Is there a way to get that 42? (Input is the class A and the name of the field 'i') A.i.init returns 0, so it doesn't care about the class. classinfo.m_init can be an option, but maybe there's a nicer way to do this? Thx!
Re: Getting the initial value of a class field in compile time.
On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote: On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote: Hello, class A{ int i = 42; } Is there a way to get that 42? (Input is the class A and the name of the field 'i') A.i.init returns 0, so it doesn't care about the class. classinfo.m_init can be an option, but maybe there's a nicer way to do this? Thx! Try A.init.i I tried and A.init.stringof == "void()" That generates a new question, what is void() ? It has no sizeof property. I guess it's the voidest of the voids in D :D
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!
Re: Getting the initial value of a class field in compile time.
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 wrote: mixin([FieldNameTuple!T].map!(n => n~"=(new T)."~n~";").join); After checking it in the asm debugger, it turned out, that it evaluates (new T) in runtime. (Silly me, because the constructor can have side effects.) So I first put the default values into an enum, and then do the assignment: foreach(n; FieldNameTuple!T){{ mixin("enum def = (new T).@; @ = def;".replace("@", n)); }} And that became as fast as it can be: mov dword ptr ds:[rax+10], 2A Thanks for the help again.
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!
Information about the 'magic' field in object.Object class
Hello, I'm try to figure out the contents od the base class instance in D, LDC Windows 64bit. I'm sure that there is a 8 byte VMT pointer. But unable to fund information about the remaining 8 byte. I guess it must be a unique 8byte (void* ?) identifier that is useful for Monitor. In a video someone mentioned this as 'magic'. Is there a documentation about that 'magic' field? I'd love to use some bits in it if I'm sure about the consequences. I have a really small object, only 32 bytes. At this point if I want to add a flag bit I have 3 choices: - add a new field to the class -> effectively the instanceSize will grow by 50% (16bytes with alignment) - compress the current 16bytes of data. -> eats more cpu - Hide it somewhere 'magically'. Thank You in advance!
Re: Information about the 'magic' field in object.Object class
On Thursday, 16 January 2020 at 14:32:24 UTC, Adam D. Ruppe wrote: On Thursday, 16 January 2020 at 14:30:04 UTC, realhet wrote: Is there a documentation about that 'magic' field? I'm pretty sure the only fields in there are pointer to vtable and pointer to monitor object... I have a really small object, only 32 bytes. At this point if I want to add a flag bit I have 3 choices: Do you need virtual functions? If not, you could probably just make a struct instead. Thank you both for the hints! Yes I need virtual functions (this is the base class of my layout system: it can be a letter, a picture, or a paragraph of text.). I've tried extern(C++) and it went down 8 bytes. But the I tried the following: synchronized(obj){ ... } Compiles without a problem. Hmm... I think I will use extern(C++) and later when I will have a big system to test, I will benchmark it. I'm sure that Monitor functionality is not needed for these objects, so that extra 8 bytes will worth it. Update: - All of the child classes needed to be marked with extern(C++) - static class members are not supported, only __gshared static. - passing a delegate to a constructor of this class expects a (extern(C++) delegate) too. - Internal compiler error: string[string] can not be mapped to C++ So extern(C++) is not good in the current case. I will try to use that 8 byte magic illegally, and will see if it is unstable or not. I will not do any synchronization, but I think the GC will crash upon releasing these objects. Thx for the help!
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: 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!
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: 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 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.
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!
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: 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
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 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 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...
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!
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!
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: 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!
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
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.
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!
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 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 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.
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 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.
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: 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!
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 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
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!
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: 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.
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 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
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: 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
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: 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.
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: 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.
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: 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!
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
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: 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.
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!
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!