Re: What parser generator can let me run arbitrary code in its match rules?
On Monday, 20 November 2023 at 23:50:24 UTC, Dmitry Ponyatov wrote: - not abandoned years ago - documentation and commented samples presenets - CTFE the best https://code.dlang.org/packages/pegged
Re: What parser generator can let me run arbitrary code in its match rules?
On Monday, 20 November 2023 at 23:56:36 UTC, Dmitry Ponyatov wrote: Or maybe someone advice me some set of books deeply targets for learning of binary and symmetric parsing (such as binpac), DCG in C or using generators in D, etc to let me write my own lib. 'Crafting Interpreters' book explain recursive descent parser, including parsing binary operators with priorities.
Re: What parser generator can let me run arbitrary code in its match rules?
Or maybe someone advice me some set of books deeply targets for learning of binary and symmetric parsing (such as binpac), DCG in C or using generators in D, etc to let me write my own lib. Everething I found (besides the Dragon book) uses black magic with Haskell, Lisp etc.
What parser generator can let me run arbitrary code in its match rules?
- not abandoned years ago - documentation and commented samples presenets - CTFE the best
Re: What is :-) ?
On Monday, 20 November 2023 at 16:09:33 UTC, Antonio wrote: **Why this is a function and not a delegate?** ```auto createCounter = (int nextValue) => (int dummy) => nextValue++;``` Syntactically I dont see any difference: `createCounter` is a function, and not a delegate, as it doesn't close over any variables. It returns a delegate as the variable `nextValue` is closed over. There's no difference in syntax. The difference is however important as an environment must be retained for the closed-over variables and passed along with the pointer, making delegates both more expensive and incompatible with function pointers on the C ABI. Note that `f` and `g` are obviously not pointing to the same `nextValue`: ```d auto createCounter = (int nextValue) => () => nextValue++; void main() { import std.stdio : writeln; auto f = createCounter(5); auto g = createCounter(0); writeln(f()); // 5 writeln(g()); // 0 writeln(f()); // 6 writeln(g()); // 1 } ``` What "breaks" my mind is that a compiler decision (treat a piece of code as function or delegate) is not completely transparent D is trying to be convenient (by offering delegates at all, and by making the syntax so light) while offering fine control (by letting you distinguish between function pointers and delegates). It'd be a much simpler language if it dropped one of those aims, but such languages also already exist. Similarly D also distinguishes between "numbers" (`int`) and "numbers" (`double`) and this can also be transparent and also cause 'side effects'. Someone educated in mathematics but not familiar with computing might complain about ```d void main() { import std.stdio : writefln; auto n = 1; writefln!"%d"(n); } ``` breaking when "all I did was bump n by one-tenth, to 1.1". I'm not trying to be mean with this example, and I don't think it's shameful either to know mathematics but not computing. But D expects you to be familiar with such things for you to not be surprised by how it behaves.
Re: What is :-) ?
On Monday, 20 November 2023 at 16:09:33 UTC, Antonio wrote: What "breaks" my mind is that a compiler decision (treat a piece of code as function or delegate) is not completely transparent causing "side" effects on your code (writeln doesn't work the same way: it shows the delegate signature, but not the function signature). It's certainly surprising that `writeln` treats function pointers and delegates differently. My guess is that it's because [`isPointer`][1] returns `true` for functions and `false` for delegates. [1]: https://phobos.dpldocs.info/std.traits.isPointer.html Is there any way to force D compiler to treat this "createCounter" declaration as **delegate** instead of **function**? ```d auto createCounter = (int nextValue) => () => nextValue++; ``` You can put the `delegate` keyword in front of the function literal: ```d auto createCounter = delegate (int nextValue) => () => nextValue++; ``` This syntax is documented in the spec's section on [Function Literals][2] (look at the grammar box and the examples). [2]: https://dlang.org/spec/expression.html#function_literals
Re: What is :-) ?
On Monday, 20 November 2023 at 16:09:33 UTC, Antonio wrote: Is there any way to force D compiler to treat this "createCounter" declaration as **delegate** instead of **function**? ```d auto createCounter = (int nextValue) => () => nextValue++; ``` generally there is a way to tell the compiler specifically that you want a delegate or a function, and additionally there is `toDelegate` function from std.functional that could be useful in some cases. https://dlang.org/phobos/std_functional.html#toDelegate the syntax for specifying delegate/function is smth like this, IIRC return type can be omitted but for reference I write it here as auto. ```d // this is a function returning a delegate auto createCounter(int nextValue) => auto delegate() => nextValue++; // this is a function returning a function auto createCounter(int nextValue) => auto function() => nextValue++; ```
Re: What is :-) ?
On Monday, 20 November 2023 at 13:25:48 UTC, Paul Backus wrote: On Monday, 20 November 2023 at 08:47:34 UTC, Antonio wrote: - What is the way to do ```writeln``` work with ```Counter``` function the same way it works with ```next``` function? `writeln()` should do it. It does not do the same: It shows an address, not the function signature. Because I need to understand "why", I propose a second example (with some additional info based on @evilrat proposals :-) ): ```d import std.stdio; void main() { auto createCounter = (int nextValue) => (int dummy) => nextValue++; auto getNext = createCounter(10); writeln( "'getNext' is ", getNext ); writeln( "'createCounter' is ", createCounter ); writeln( "'typeof(getNext).stringof' is ", typeof(getNext).stringof ); writeln( "'typeof(createCounter).string' is ", typeof(createCounter).stringof ); } ``` The output is ``` 'next' is int delegate(int) pure nothrow @nogc @safe 'createCounter' is 557FFCC00968 'typeof(getNext).stringof' is int delegate(int dummy) pure nothrow @nogc @safe 'typeof(createCounter).string' is int delegate(int dummy) pure nothrow @nogc @safe function(int nextValue) pure nothrow @safe ``` **Why ```writeln``` doesn't treat the same way ```getNext``` and ```createCounter```?** Because ```getNext``` is a delegate and ```createCounter``` is a function. **Why this is a function and not a delegate?** ```auto createCounter = (int nextValue) => (int dummy) => nextValue++;``` Syntactically I dont see any difference: ```auto name = "expression returning a delegate"``` The reason is **D compiler takes the decision**. If you make ```createCounter``` to depend on an external variable, it will be treated as delegate (because it has context information associated to the function: a closure) ```d import std.stdio; void main() { int diff = 1; auto createCounter = (int nextValue) => () { scope(exit) nextValue+=diff; return nextValue;}; writeln( "'typeof(createCounter).string' is ", typeof(createCounter).stringof ); } ``` Will output that createCounter is a delegate: ``` 'typeof(createCounter).string' is int delegate() pure nothrow @nogc @safe delegate(int nextValue) pure nothrow @safe ``` What "breaks" my mind is that a compiler decision (treat a piece of code as function or delegate) is not completely transparent causing "side" effects on your code (writeln doesn't work the same way: it shows the delegate signature, but not the function signature). But the decision of the compiler is predictable and you can argue different effects are not side effects: only something you should pay attention to. **This long and winding road toke me to a third and crazzy question** Is there any way to force D compiler to treat this "createCounter" declaration as **delegate** instead of **function**? ```d auto createCounter = (int nextValue) => () => nextValue++; ```
Re: What is :-) ?
On Monday, 20 November 2023 at 08:47:34 UTC, Antonio wrote: - What is the way to do ```writeln``` work with ```Counter``` function the same way it works with ```next``` function? `writeln()` should do it.
Re: What is :-) ?
On Monday, 20 November 2023 at 08:47:34 UTC, Antonio wrote: I understand the problem with UFCS (``next`` is not using UFCS because it is a delegate defined in the own main() function, and ``Counter``` without () is treated as a function call because it is UFCS eligible ) This is not UFCS, it's [optional parentheses][1], which is a separate language feature. (Reminder: UFCS only applies when the callee has the form `x.y`) According to the spec, it's disabled for function pointers and delegates due to the potential for ambiguity. [1]: https://dlang.org/spec/function.html#optional-parenthesis
Re: What is :-) ?
On Monday, 20 November 2023 at 09:44:32 UTC, Antonio wrote: - Why writeln doesn't treat ```next``` and ```Counter``` the same way? (I think I understand why, but it shows a "low" level difference of something that syntactically is equivalent) - What is the way to show Counter signature using ```writeln``` (if possible)? I found no way to tell compiler that I don't want to call Counter and instead want to take the function itself, but closest thing is just to take the string representation at compile time (same as used in pragma msg) and pass it to writeln instead of Counter. I guess this is one of these bif oof moments with UFCS, a function returning a (parameterless) function. Note that in most cases you should never make runtime decisions on .stringof value as it is not standardized. ``` //pragma(msg, typeof(Counter)); // pure nothrow @safe int delegate() pure nothrow @nogc @safe(int nextValue) enum f = typeof(Counter).stringof; // same string as above writeln( "'Counter' is ", f); ``` Of course this works too `writeln( "'Counter' is ", typeof(Counter).stringof);`
Re: What is :-) ?
On Monday, 20 November 2023 at 09:11:07 UTC, evilrat wrote: if you meant to take the function/delegate and not invoke try `` instead, otherwise it expects the parameters. If you execute ``` writeln( "'Counter' is ", ); ``` It shows the Counter address: ``` 'Counter' is 557F2567F940 ``` Not the function signature like it does with ```next``` I propose a simple change: ```d void main(){ auto Counter = (int nextValue) => () => nextValue++; auto next = Counter(10); writeln( "'next' is ", next ); writeln( "'Counter' is ", Counter ); } ``` first ```writeln``` shows the signature of next: ``` 'next' is int delegate() pure nothrow @nogc @safe ``` second writeln shows the address of Counter ``` 'Counter' is 55568953C910 ``` - Why writeln doesn't treat ```next``` and ```Counter``` the same way? (I think I understand why, but it shows a "low" level difference of something that syntactically is equivalent) - What is the way to show Counter signature using ```writeln``` (if possible)? ```
Re: What is :-) ?
On Monday, 20 November 2023 at 08:47:34 UTC, Antonio wrote: Now, I uncomment the ```writeln( "'Counter' is ", Counter );``` line and compiler says ``` /home/antonio/Devel/topbrokers/whatsapp-srv/admin/x.d(12): Error: function `x.Counter(int nextValue)` is not callable using argument types `()` /home/antonio/Devel/topbrokers/whatsapp-srv/admin/x.d(12): too few arguments, expected 1, got 0 ``` I understand the problem with UFCS (``next`` is not using UFCS because it is a delegate defined in the own main() function, and ``Counter``` without () is treated as a function call because it is UFCS eligible ) `writeln( "'Counter' is ", Counter );` this code is actually internally looks like this `writeln( "'Counter' is ", Counter() );` if you meant to take the function/delegate and not invoke try `` instead, otherwise it expects the parameters. - What is the way to do ```writeln``` work with ```Counter``` function the same way it works with ```next``` function? Sorry, that's too confusing and I have no idea what you mean, maybe if you can explain what you are trying to achieve someone might be able to help you.
What is :-) ?
If I run this code ```d import std.stdio; void main(){ auto next = Counter(10); next().writeln; next().writeln; next().writeln; // What is "next" function? writeln( "'next' is ", next ); // What is "Counter" function? This fails // writeln( "'Counter' is ", Counter ); } auto Counter(int nextValue) => () => nextValue++; ``` Executing this code results in: ``` 10 11 12 'next' is int delegate() pure nothrow @nogc @safe ``` Now, I uncomment the ```writeln( "'Counter' is ", Counter );``` line and compiler says ``` /home/antonio/Devel/topbrokers/whatsapp-srv/admin/x.d(12): Error: function `x.Counter(int nextValue)` is not callable using argument types `()` /home/antonio/Devel/topbrokers/whatsapp-srv/admin/x.d(12): too few arguments, expected 1, got 0 ``` I understand the problem with UFCS (``next`` is not using UFCS because it is a delegate defined in the own main() function, and ``Counter``` without () is treated as a function call because it is UFCS eligible ) - What is the way to do ```writeln``` work with ```Counter``` function the same way it works with ```next``` function?
Re: cannot find source code for runtime library file 'object.d'
denis via Digitalmars-d-learn wrote: ``` $ zypper install dmd $ dmd main.d Error: cannot find source code for runtime library file 'object.d' dmd might not be correctly installed. Run 'dmd -man' for installation instructions. config file: /etc/dmd.conf I would say the package has files in the wrong locations. Try the binary from dlang.org: https://downloads.dlang.org/releases/2.x/2.105.3/dmd-2.105.3-0.openSUSE.x86_64.rpm I'm not familiar with zypper but I'll bet you can install it by: # zypper install ./dmd-2.105.3-0.openSUSE.x86_64.rpm On a RHEL-like distro, this works: # yum install ./pkgname.rpm Just be sure to use your package manager tool (yum, zypper, whatever) to install the binary so it can later be removed or updated. More details: I ran into something similar,'object.d' not found, when trying to build dmd from source. In the end I grabbed the prebuilt dmd binary RPM from dlang.org and followed the locations where it placed files, then everything "just works". If you have the rpm command, you can run the following to get the file list without installing it: $ rpm -qlp pkgname.rpm If you do not have the rpm command, you can use rpm2cpio to convert the rpm into a cpio archive, then read it: $ rpm2cpio pkgname.rpm > pkgname.cpio $ cpio -itv < pkgname.cpio | more $ cat /etc/dmd.conf [Environment32] DFLAGS=-I/usr/include/dlang/dmd -L-L/usr/lib -L--export-dynamic -fPIC [Environment64] DFLAGS=-I/usr/include/dlang/dmd -L-L/usr/lib64 -L--export-dynamic -fPIC Here's what's in my /etc/dmd.conf; Note there is no 'dlang' subdir in /usr/include, just 'dmd'. cut here [Environment32] DFLAGS=-I/usr/include/dmd/phobos -I/usr/include/dmd/druntime/import -L-L/usr/lib -L--export-dynamic -fPIC [Environment64] DFLAGS=-I/usr/include/dmd/phobos -I/usr/include/dmd/druntime/import -L-L/usr/lib64 -L--export-dynamic -fPIC cut here $ ls /usr/include/dlang/dmd /usr/include/dmd should have two directories: druntime and phobos, nothing else. object.d lives here: /usr/include/dmd/druntime/import/object.d $ cat /etc/os-release NAME="openSUSE Tumbleweed" VERSION="20231006" $ dmd --version DMD64 D Compiler v2.105.3 ``` Help? If you decide to build from source, keep in mind you need a D compiler to build dmd. Either use a binary tarball from dlang.org, or you have to bootstrap dmd 2.067.1 with a C++ compiler, then keep upgrading dmd until you get to the version you want. It can be done and does work, but takes time. Instructions are here: https://wiki.dlang.org/Building_under_Posix I'm guessing the person who build the package was thinking they wanted to allow allow installing mulitple D compilers, all under /usr/include/dlang, like so: /usr/include/dlang/{dmd,gdc,ldc2} and libraries would go under /usr/lib64/dlang/{dmd,gdc,ldc2}. I made several attempts at this and they failed. Like I said, follow the locations of the dlang.org prebuilt rpm and it all just works, or use a binary from dlang.org. scot