> On 6 Mar 2018, at 00:24, Frank Heckenbach <f.heckenb...@fh-soft.de> wrote:
> Hans Åberg wrote:
>>> On 5 Mar 2018, at 18:15, Frank Heckenbach <f.heckenb...@fh-soft.de> wrote:
>>> Let's see if I can add "$$ = std::move ($1)" as a default action in
>>> my patches. (Not as a pre-action as in C, that would be wrong with
>>> move, only as a default action when no user action is supplied.)
>> That might be OK in this special case.
> No special case, I implemented it fully generally in the C++11
> template (my previous patch).
I meant the special case of a default action, as it is harder to deduce when
std::move should be applied.
Perhaps wrapping the actions in inline functions might get C++ to apply moves
correctly (see below).
>>> So I see no reason why it shouldn't be done by default, especially
>>> since in C that's not a Bison quirk, but actually a Yacc feature.
>> I got the impression it might be complicated to implement.
> I had feared so, but as you can see, it wasn't. (And it would get
> even easier with std::variant.)
Otherwise, there is no reason for Bison to be Yacc compatible, except for the
special Yacc mode, which Paul Eggert worked on becoming POSIX compliant. For
example, Yacc has optional rule colons, but that might have been removed in
Bison in some modes at least. And Bison now has grammar variable naming, as I
indicated, which in fact is very convenient.
>>> That's unrelated. std::vector does all the std::move's it needs
>> This f you might want to avoid tweaking the M4 file and just change the
> Again, changing the container does not help. The parser needs move
> semantics in other places, and once they're implemented (which I
> did), vector just works!
C++ std::stack though has std::deque as default. If one wants to access
elements not on top, std::stack does not work, though.
>>> In user actions, one needs std::move regardless, e.g.
>>> "$$ = std::move ($1)" (like the default action) or something like
>>> "$$ = build_something (std::move ($1), std::move ($2))" with some
>>> user-defined build_something function. That's not poor design; such
>>> code is expected when using move-only types. But again, the user
>>> actions are not the issue, bison can't do anything there anyway
>>> (except for the default action, see above). The required moves
>>> within the parser are the problem.
>> It seems to be forced that way, but ideally, the moves should be hidden away
>> in containers.
> We're talking about user-actions here. To them, $$, $1, etc. do and
> should behave just like varibles. (That $1 is an element of a
> container is irrelevant, and again, there's no difference between
> vector and deque in this regard.) The user action might use them
> twice ("foo ($1); bar ($1);"), so always moving would be wrong. It's
> up to the user to move when wanted. And it's not really a problem --
> with a move-only type, the compiler will complain when you forget
Using inline functions for the actions might do it. The compiler can then
remove the inlines, but the moves should be still applied correctly. Or maybe
not, depending on how the C++ standard is written.
>>> GC doesn't call destructors, does it?
>> One can a could of different things with the Boehm GC, register
>> finalizers, and it also a deallocation function.
> If you have to register them explictly, all the beauty of RAII is
One can mix both GC and standard stack allocations. Guile uses now the Boehm
GC, and I have a similar dynamic polymorphy. For that I wrote a template
reference class. The use of finalizers did not seem to impose a significant
overhead. They are otherwise only needed so collect non-memory resources, such
as open streams.
Then the problem is if that a standard container has such a GC collected
reference, then the GC cannot trace the pointer and keep it alive if not using
its allocator and deallocator, so that pointers that should be alive might be
collected. This does indeed happen, resulting in mysterious memory errors.
>>>> and shared_ptr might be an alternative.
>>> Not for me (in many cases), as I explained.
>> You will have to explain it again.
> Though I don't understand why we need to argue this.
Just to let me follow. You did not explain why you can't allocate the move-only
type on the heap, and keep a pointer.
I used a reference count for two functions: polymorphy, and optimizing by
avoiding copying. For the polymorphy, I switched to the GC, and for simple
types, standard automatic objects relying on C++11 move constructors. These
changes were made to be able to keep the program together semantically, thus
accepting some overhead. For the switch to automatic objects, that was not so
> Others on the
> list have requested move semantics, and you put some work into it
> yourself, so it seems obvious they're useful (just like most modern
> C++ is based on them).
I just moved along and give advice given the current state of lack active Bison
development. If you want to fix this, that would be best, but I do not know how
to get it into the Bison releases - perhaps Paul Eggert can help out.
>>>> It is not difficult to hack the M4 file, but if one writes the
>>>> parser, not actively develops for awhile, and Bison changes it,
>>>> then that may turn out be a hurdle say in a few years time.
>>> Exactly. That's why I hoped to see a maintainer here.
>> I can't help you. The CC you removed was to one of them.
> I didn't remove any CC. You CC'ed one (short) mail to Paul Eggert
> which just said that Akim Demaille has not been active for some time
> now. I hadn't replied to that mail, but to the main thread which was
> not CC'ed.
I did not see his reply. Paul Eggert only programs C, but he might help you to
get changes into the Bison distribution.
>>>> I do not remember, so you would have to search the list archives. I am
>>>> just saying there might a risk there.
>> Maybe "C++17" then.
> Found it, I suppose that's what you mean:
Yes, that seems so.
> Indeed, it seems it doesn't work with $<...>. I didn't notice
> because I never use this feature. (When I need a temporary value
> from a mid-rule action, I turn it into a nonterminal instead; seems
> more type-safe to me, no need to manually match the type on
> assignment and usage.)
> Bison's variant implementation really breaks down here. One could
> work around it with some extra code to keep track of the dynamic
> type of $<...>, but that gets really close to reimplementing
> std::variant, so it seems rather pointless. So std::variant is the
> way to go, at least in the long run. (As I said, I don't use gcc7
> set, but I don't require $<...>, so for now I'll be fine with
> Bison's variant.)
Since C++17 now is available and supported by GCC7, std::variant would be best