On Tuesday, 25 May 2021 at 17:21:16 UTC, Andrei Alexandrescu wrote:
> dmd has a few string functions with names having "Then" as a prefix that take a lambda and call it with a temporary string converted for OS purposes (zero-terminated, encoded a specific way etc). The use goes like this:
[...]
I was thinking there's an easier way that's also more composable:
int i = stat(stringz(name).ptr, &statbuf));
where stringz
returns a temporary struct offering primitives such as ptr
and opSlice
. In the destructor, the struct frees temporary memory if allocated. Better yet, it can return them as scope
variable, that way ensuring correctness in safe code.
Well, the usage of CPS is limited to one level here. As your example show, we can return whatever we want from toCStringThen
, and if needed, chain the return value with something else.
The struct
approach works to a certain degree: DIP1000 would not provide the tool to make this pattern work in a @safe
context. I have yet to see a container that is @safe
to use with DIP1000 (e.g. https://github.com/dlang/phobos/pull/8101 ), but making the CPS work with DIP1000 is possible (provided DIP1000 works as intended). It's from this observation that this approach became my preferred one, and that's what led to toCStringThen
(origin: https://github.com/dlang/dmd/pull/8585 ).
But this function is only used a handful of times (~10?) in DMD, and only for C functions or in trampoline functions (turning a slice into a pointer). Is there a large ROI in finding the best possible pattern for it ? There are many large architectural problems in DMD that needs to be addressed, such as the absolute lack of abstraction despite the OOP hierarchy. The semantic routines will cast a base type (Expression
, Dsymbol
, etc...) to a more specialized type literally everywhere, instead of relying on virtual functions / properties available in the base classes. Just grep for cast(TypeFunction)
to get an idea of what I mean.