Re: Automatially move from $n (was: C++11 move semantics)
> On 18 Sep 2018, at 04:48, Frank Heckenbach wrote: > > Hans Åberg wrote: > C++ does not support the implementation of a (tracing) GC, because the information needed, though available to the compiler, is not available from the language. The fact that it does not have a GC is another topic. >>> >>> I know and (again) I don't care because I don't want to use GC >>> anyway. You're basically discussing with yourself here. >> >> It exemplifies the of limitations C++. See below. > > Nope. Again: compile-time != runtime. It is funny, below you give a link of people wanting to add unavailable runtime information to compile time. >>> My option? I'm not having this problem. >> >> So then why bother bringing it up in the first place? > > Funnily, I preemptively answered this question just in the next > sentence that you also quoted: Hilariously, you rather introduced this new topic, when I discussed something else. >>> Again, I only brought up the >>> make_pair thing as a counterexample to your claim that an automatic >>> break would avoid any possible double-move. >> >> You gave a counterexample of something else than what I discussed. > > Nope, you said: "So a way to make it safe is to jump out of the > action statement.", That referred to that other feature. > I replied: "Not necessarily: You could use it > twice within one expression (unsafe even with jump)", and you > replied: "That would probably not be possible, if one gets an > automated break after it." Then I gave an example of what I had said > before, that it *is* possible to use it twice in one statement, > counter to your claim. I never said it occured in my code, just > explained why break isn't the solution. > > You can check it here: > http://lists.gnu.org/archive/html/bug-bison/2018-09/msg00036.html Then when you clarified, I decided to follow your topic. >>> But it might be a solution to someone else's problem (or another >>> problem of mine some other day ;). >> >> Until that day, it's too esoteric to be worth implementing, in my opinion. > > Esoteric I don't know, but certainly not hard to implement. > Basically a flag that it set when moved from and causes an exception > on any subsequent access (except assignment to, and destruction, of > course). Seems like a nice student project ... :) So then implement this compile time check yourself, rather than having lengthy discussions here. > What would be much more interesting would be a generic decorator > that does this and can be applied to any type one wants to, but > that's more tricky and I think impossible in current C++ because one > can't wrap "any method" generically. Maybe if Herb Sutter's > metaclass proposal takes off, one (far) day ... > https://herbsutter.com/2017/07/26/metaclasses-thoughts-on-generative-c/ Even though the compiler may have access to the information to check that, you don't have access to that from the language itself. >>> >>> - Within(!) the compiler, more general, but a job for compiler >>> experts, not me. >> >> You won't get that for the same reason as in the GC case above. > > And why would that be? You said yourself that "the compiler may have > access to the information to check that". Why don't you check with the GCC people if they want to implement it.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> C++ does not support the implementation of a (tracing) GC, because > >> the information needed, though available to the compiler, is not > >> available from the language. The fact that it does not have a GC > >> is another topic. > > > > I know and (again) I don't care because I don't want to use GC > > anyway. You're basically discussing with yourself here. > > It exemplifies the of limitations C++. See below. Nope. Again: compile-time != runtime. > > My option? I'm not having this problem. > > So then why bother bringing it up in the first place? Funnily, I preemptively answered this question just in the next sentence that you also quoted: > > Again, I only brought up the > > make_pair thing as a counterexample to your claim that an automatic > > break would avoid any possible double-move. > > You gave a counterexample of something else than what I discussed. Nope, you said: "So a way to make it safe is to jump out of the action statement.", I replied: "Not necessarily: You could use it twice within one expression (unsafe even with jump)", and you replied: "That would probably not be possible, if one gets an automated break after it." Then I gave an example of what I had said before, that it *is* possible to use it twice in one statement, counter to your claim. I never said it occured in my code, just explained why break isn't the solution. You can check it here: http://lists.gnu.org/archive/html/bug-bison/2018-09/msg00036.html > > But it might be a solution to someone else's problem (or another > > problem of mine some other day ;). > > Until that day, it's too esoteric to be worth implementing, in my opinion. Esoteric I don't know, but certainly not hard to implement. Basically a flag that it set when moved from and causes an exception on any subsequent access (except assignment to, and destruction, of course). Seems like a nice student project ... :) What would be much more interesting would be a generic decorator that does this and can be applied to any type one wants to, but that's more tricky and I think impossible in current C++ because one can't wrap "any method" generically. Maybe if Herb Sutter's metaclass proposal takes off, one (far) day ... https://herbsutter.com/2017/07/26/metaclasses-thoughts-on-generative-c/ > >> Even though the compiler may have access to the information to > >> check that, you don't have access to that from the language > >> itself. > > > > - Within(!) the compiler, more general, but a job for compiler > > experts, not me. > > You won't get that for the same reason as in the GC case above. And why would that be? You said yourself that "the compiler may have access to the information to check that". Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 18 Sep 2018, at 00:20, Frank Heckenbach wrote: > > Hans Åberg wrote: > Yes, indeed C++ does not support that, >>> >>> Are you replying to your own statement now? I never claimed (or >>> cared) whether C++ supports GC. >> >> C++ does not support the implementation of a (tracing) GC, because >> the information needed, though available to the compiler, is not >> available from the language. The fact that it does not have a GC >> is another topic. > > I know and (again) I don't care because I don't want to use GC > anyway. You're basically discussing with yourself here. It exemplifies the of limitations C++. See below. >>> At runtime, yes. Basically an extended unique_ptr could detect this >>> automatically. >> >> This looks like becoming you option. You might use it for >> debugging only. > > My option? I'm not having this problem. So then why bother bringing it up in the first place? > Again, I only brought up the > make_pair thing as a counterexample to your claim that an automatic > break would avoid any possible double-move. You gave a counterexample of something else than what I discussed. > But it might be a solution to someone else's problem (or another > problem of mine some other day ;). Until that day, it's too esoteric to be worth implementing, in my opinion. >>> I'd rather see a compile-time check, even if it's a >>> bit primitive, i.e. gives false positives. >> >> Even though the compiler may have access to the information to >> check that, you don't have access to that from the language >> itself. Parsing the language is a long haul, even though there >> were some here wanting help with that. > > No, I don't want to go there. As said before, I see two viable > compile-time options so far: > > - Within Bison, hopefully rather easy to implement, but with some > false positives. > > - Within(!) the compiler, more general, but a job for compiler > experts, not me. You won't get that for the same reason as in the GC case above.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> Yes, indeed C++ does not support that, > > > > Are you replying to your own statement now? I never claimed (or > > cared) whether C++ supports GC. > > C++ does not support the implementation of a (tracing) GC, because > the information needed, though available to the compiler, is not > available from the language. The fact that it does not have a GC > is another topic. I know and (again) I don't care because I don't want to use GC anyway. You're basically discussing with yourself here. > > At runtime, yes. Basically an extended unique_ptr could detect this > > automatically. > > This looks like becoming you option. You might use it for > debugging only. My option? I'm not having this problem. Again, I only brought up the make_pair thing as a counterexample to your claim that an automatic break would avoid any possible double-move. But it might be a solution to someone else's problem (or another problem of mine some other day ;). > > I'd rather see a compile-time check, even if it's a > > bit primitive, i.e. gives false positives. > > Even though the compiler may have access to the information to > check that, you don't have access to that from the language > itself. Parsing the language is a long haul, even though there > were some here wanting help with that. No, I don't want to go there. As said before, I see two viable compile-time options so far: - Within Bison, hopefully rather easy to implement, but with some false positives. - Within(!) the compiler, more general, but a job for compiler experts, not me. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 17 Sep 2018, at 23:27, Frank Heckenbach wrote: > > Hans Åberg wrote: > This illustrates the problem with make_pair($x, $x): one may try a reference count or GC, but C++ does not support the implementation of a GC, even though the compiler has the required information, it is not accessible from the language. >>> >>> Hold it! We were discussing a static compiler check, and within two >>> paragraphs you divert to runtime checks (which are less reliable) >>> and then to GC which I dislike for many reasons. To me it seems like >>> a last effort: if you can't do proper resource management (like >>> RAII), let the garbage collector pick up the pieces. >> >> Yes, indeed C++ does not support that, > > Are you replying to your own statement now? I never claimed (or > cared) whether C++ supports GC. C++ does not support the implementation of a (tracing) GC, because the information needed, though available to the compiler, is not available from the language. The fact that it does not have a GC is another topic. >>> Fact is, I can >>> do proper resource management in most cases, and just said it would >>> be nice to have an extra check if it's not too hard to implement. >> >> It looks is not hard to implement such a check against double >> moves, and that might be the best solution, though it calls for >> more careful runtime testing. > > At runtime, yes. Basically an extended unique_ptr could detect this > automatically. This looks like becoming you option. You might use it for debugging only. By contrast, a reference count cannot be optimized away, so this might be better. > I'd rather see a compile-time check, even if it's a > bit primitive, i.e. gives false positives. Even though the compiler may have access to the information to check that, you don't have access to that from the language itself. Parsing the language is a long haul, even though there were some here wanting help with that. There are LALR C++ grammars out there at least for some earlier language version.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >>> As I said, this already happens in "$$ = foo ();" (automatially) and > >>> "$$ = std::move ($k);" (whether the move is explicit or > >>> automatically inserted as we're discussing). So if $k is covered, no > >>> special handling for $$ seems necessary. > >> > >> You can do it by hand, > > > > Sorry, but how does this answer anything? The subject (also thread > > subject) is explicitly: "Automatially[sic, sorry for the typo ;] > > move from $n". > > > > So saying "You can do it by hand" is just giving up (which is > > pointless, since I already have a solution). > > It looks as though you are suggesting doing it by hand by writing > $$ = std::move($k) instead of $$ = $k whenever necessary. I'm suggesting doing it automatically (again, see subject). > I considered having it automatically. You focus on one special case (moving $k to $$). You seem to think it's somehow different to moving $k to somewhere else, but you failed to explain why this should be so. I think it's the same, so solving the general case (moving from $k) will also solve the special case (moving $k to $$). > > I can't help but view your insisting on $$ as diverting from the > > actual topic. If you want to discuss any issues with moving to $$ > > (whatever those issues may be; I don't see any), may I suggest you > > start a new thread, please? > > You are the one keeping comping back to the issue, It's you who keeps coming back to $$ again and again. > despite I told you I now see that you are interested in something > else. Not something else, just a more general case. > >> This illustrates the problem with make_pair($x, $x): one may try a > >> reference count or GC, but C++ does not support the implementation > >> of a GC, even though the compiler has the required information, it > >> is not accessible from the language. > > > > Hold it! We were discussing a static compiler check, and within two > > paragraphs you divert to runtime checks (which are less reliable) > > and then to GC which I dislike for many reasons. To me it seems like > > a last effort: if you can't do proper resource management (like > > RAII), let the garbage collector pick up the pieces. > > Yes, indeed C++ does not support that, Are you replying to your own statement now? I never claimed (or cared) whether C++ supports GC. > and it looks it is the same with your problem for the same > reasons, which is why it is so difficult to find solutions within > the language. I don't think so. GC needs type information at runtime. An optimizer needs it at compile type. I don't know if it has access to it already (don't know gcc internals so well), but if not, providing it is something totally different from providing it to the runtime. > > Fact is, I can > > do proper resource management in most cases, and just said it would > > be nice to have an extra check if it's not too hard to implement. > > It looks is not hard to implement such a check against double > moves, and that might be the best solution, though it calls for > more careful runtime testing. At runtime, yes. Basically an extended unique_ptr could detect this automatically. I'd rather see a compile-time check, even if it's a bit primitive, i.e. gives false positives. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 16 Sep 2018, at 19:16, Frank Heckenbach wrote: > > Hans Åberg wrote: > Maybe not for you, but for a more normal use, with types having both copy and move. Then one would like to use move to $$ whenever possible. Doesn't matter with me, as it is just some pointers and integers. >>> >>> As I said, this already happens in "$$ = foo ();" (automatially) and >>> "$$ = std::move ($k);" (whether the move is explicit or >>> automatically inserted as we're discussing). So if $k is covered, no >>> special handling for $$ seems necessary. >> >> You can do it by hand, > > Sorry, but how does this answer anything? The subject (also thread > subject) is explicitly: "Automatially[sic, sorry for the typo ;] > move from $n". > > So saying "You can do it by hand" is just giving up (which is > pointless, since I already have a solution). It looks as though you are suggesting doing it by hand by writing $$ = std::move($k) instead of $$ = $k whenever necessary. I considered having it automatically. >> but the case I considered was to find an automated approach >> without explicitly calling std::move in $$ = $k. But your case is >> different. > > It's more general. "$$ = $k" is strictly a subset of the general > case. (And IMHO not a very important one for k > 1. For k = 1, we > can have a default action, but how often do you really need > "$$ = $2"? In a rule like "expr = '(' expr ')';" typically, but > that's about it.) It happens every now and again. I have identifier_declaration definition[x] where the first just defines the names and does not produce any value. > I can't help but view your insisting on $$ as diverting from the > actual topic. If you want to discuss any issues with moving to $$ > (whatever those issues may be; I don't see any), may I suggest you > start a new thread, please? You are the one keeping comping back to the issue, despite I told you I now see that you are interested in something else. No, but it seems me it is a hard problem. A compiler optimizer can recognize such things if it has sufficient information about the types, by tracing the code flow. >>> >>> Yes, perhaps we should ignore the issue for now and hope for >>> compilers to offer such a warning in the future (which would be more >>> useful anyway, since it would work for all code, not only Bison >>> grammars). >> >> You might make, for debugging purposes, a simplified version of a >> reference count, a boolean that tells whether the object has been >> moved, and issue an error if moved again, or otherwise just have a >> moved from state with such a property. >> >> This illustrates the problem with make_pair($x, $x): one may try a >> reference count or GC, but C++ does not support the implementation >> of a GC, even though the compiler has the required information, it >> is not accessible from the language. > > Hold it! We were discussing a static compiler check, and within two > paragraphs you divert to runtime checks (which are less reliable) > and then to GC which I dislike for many reasons. To me it seems like > a last effort: if you can't do proper resource management (like > RAII), let the garbage collector pick up the pieces. Yes, indeed C++ does not support that, and it looks it is the same with your problem for the same reasons, which is why it is so difficult to find solutions within the language. > Fact is, I can > do proper resource management in most cases, and just said it would > be nice to have an extra check if it's not too hard to implement. It looks is not hard to implement such a check against double moves, and that might be the best solution, though it calls for more careful runtime testing. > Also note that "make_pair($x, $x)" was just a counterexample to your > claim that an automatic break after the statement would avoid the > problem. It's not something I actually need to do. If I did, I could > choose between copying in this case (if possible), using a > shared_ptr, or whatever. Yes of course, I have a polymorphic (virtual) ref GC type that emulates T& holding just a non-null pointer, and one might need to clone the value sometimes.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> Maybe not for you, but for a more normal use, with types having > >> both copy and move. Then one would like to use move to $$ whenever > >> possible. Doesn't matter with me, as it is just some pointers and > >> integers. > > > > As I said, this already happens in "$$ = foo ();" (automatially) and > > "$$ = std::move ($k);" (whether the move is explicit or > > automatically inserted as we're discussing). So if $k is covered, no > > special handling for $$ seems necessary. > > You can do it by hand, Sorry, but how does this answer anything? The subject (also thread subject) is explicitly: "Automatially[sic, sorry for the typo ;] move from $n". So saying "You can do it by hand" is just giving up (which is pointless, since I already have a solution). > but the case I considered was to find an automated approach > without explicitly calling std::move in $$ = $k. But your case is > different. It's more general. "$$ = $k" is strictly a subset of the general case. (And IMHO not a very important one for k > 1. For k = 1, we can have a default action, but how often do you really need "$$ = $2"? In a rule like "expr = '(' expr ')';" typically, but that's about it.) I can't help but view your insisting on $$ as diverting from the actual topic. If you want to discuss any issues with moving to $$ (whatever those issues may be; I don't see any), may I suggest you start a new thread, please? > >> No, but it seems me it is a hard problem. A compiler optimizer can > >> recognize such things if it has sufficient information about the > >> types, by tracing the code flow. > > > > Yes, perhaps we should ignore the issue for now and hope for > > compilers to offer such a warning in the future (which would be more > > useful anyway, since it would work for all code, not only Bison > > grammars). > > You might make, for debugging purposes, a simplified version of a > reference count, a boolean that tells whether the object has been > moved, and issue an error if moved again, or otherwise just have a > moved from state with such a property. > > This illustrates the problem with make_pair($x, $x): one may try a > reference count or GC, but C++ does not support the implementation > of a GC, even though the compiler has the required information, it > is not accessible from the language. Hold it! We were discussing a static compiler check, and within two paragraphs you divert to runtime checks (which are less reliable) and then to GC which I dislike for many reasons. To me it seems like a last effort: if you can't do proper resource management (like RAII), let the garbage collector pick up the pieces. Fact is, I can do proper resource management in most cases, and just said it would be nice to have an extra check if it's not too hard to implement. Also note that "make_pair($x, $x)" was just a counterexample to your claim that an automatic break after the statement would avoid the problem. It's not something I actually need to do. If I did, I could choose between copying in this case (if possible), using a shared_ptr, or whatever. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 16 Sep 2018, at 17:38, Frank Heckenbach wrote: > > Hans Åberg wrote: >>> (*) Nitpick: Except in a case like "$$ = $2;", but then I'd argue >>> it's the passing of $2 to $$'s assignment operator that's the >>> issue. :) >> >> Maybe not for you, but for a more normal use, with types having >> both copy and move. Then one would like to use move to $$ whenever >> possible. Doesn't matter with me, as it is just some pointers and >> integers. > > As I said, this already happens in "$$ = foo ();" (automatially) and > "$$ = std::move ($k);" (whether the move is explicit or > automatically inserted as we're discussing). So if $k is covered, no > special handling for $$ seems necessary. You can do it by hand, but the case I considered was to find an automated approach without explicitly calling std::move in $$ = $k. But your case is different. >> No, but it seems me it is a hard problem. A compiler optimizer can >> recognize such things if it has sufficient information about the >> types, by tracing the code flow. > > Yes, perhaps we should ignore the issue for now and hope for > compilers to offer such a warning in the future (which would be more > useful anyway, since it would work for all code, not only Bison > grammars). You might make, for debugging purposes, a simplified version of a reference count, a boolean that tells whether the object has been moved, and issue an error if moved again, or otherwise just have a moved from state with such a property. This illustrates the problem with make_pair($x, $x): one may try a reference count or GC, but C++ does not support the implementation of a GC, even though the compiler has the required information, it is not accessible from the language. >>> On the same token, Bison could then also (optionally) warn if some >>> $k which has a type is not used. I don't know if there is interest >>> in such a feature. It could also be useful for other languages. >>> >>> It might not be too hard to do for someone who's familiar with >>> Bison's internals. (Unfortunately, I'm not very much, and don't have >>> much free time right now.) >> >> How would this be different from the current static type system? > > The type system wouldn't change. Just an additional check: > > expr: expr '+' expr { $$ = $1; }; > > Obviously one forgot to use $3 here which has a type (unlike $2 > which doesn't have a type and so is not expected to be used). > > Bison could detect and warn about this (proably optional, since I > guess some people declare semantic types that are only meant to be > used sometimes). I use explicitly named variables, which guards against using the wrong $k number when changing a rule: expr: expr[x] "+" expr[y] { $$ = $x + $y; }; It would then, I gather, be easy to warn if such explicit name are unused, as Bison already checks if one is using undefined names.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> Ah, your idea is to wrap std::move around the $k values! My idea > >> is to let the C++ language recognise that, and then automate the > >> assignment to $$. > > > > Again, the assignment to $$ is *NOT* the issue! (*) > > It's the passing (moving) of $k. > > > > (*) Nitpick: Except in a case like "$$ = $2;", but then I'd argue > >it's the passing of $2 to $$'s assignment operator that's the > >issue. :) > > Maybe not for you, but for a more normal use, with types having > both copy and move. Then one would like to use move to $$ whenever > possible. Doesn't matter with me, as it is just some pointers and > integers. As I said, this already happens in "$$ = foo ();" (automatially) and "$$ = std::move ($k);" (whether the move is explicit or automatically inserted as we're discussing). So if $k is covered, no special handling for $$ seems necessary. > > You mean some kind of code analyzer? This might be possible, but may > > be overkill. > > Yes, you might check how people do check against that problem, if > there is some program doing that. Then one might get ideas of how > to get into Bison. > > Perhaps it might be possible to have some DLL or external program and invoke > that. If you know of one, let me know. (And it would have to be GPL-compatible in order to link it into Bison.) > No, but it seems me it is a hard problem. A compiler optimizer can > recognize such things if it has sufficient information about the > types, by tracing the code flow. Yes, perhaps we should ignore the issue for now and hope for compilers to offer such a warning in the future (which would be more useful anyway, since it would work for all code, not only Bison grammars). > > On the same token, Bison could then also (optionally) warn if some > > $k which has a type is not used. I don't know if there is interest > > in such a feature. It could also be useful for other languages. > > > > It might not be too hard to do for someone who's familiar with > > Bison's internals. (Unfortunately, I'm not very much, and don't have > > much free time right now.) > > How would this be different from the current static type system? The type system wouldn't change. Just an additional check: expr: expr '+' expr { $$ = $1; }; Obviously one forgot to use $3 here which has a type (unlike $2 which doesn't have a type and so is not expected to be used). Bison could detect and warn about this (proably optional, since I guess some people declare semantic types that are only meant to be used sometimes). Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
Akim Demaille wrote: > > As I wrote, if Bison could detect multiple uses and warn, that would > > be great, but I didn't look into it as I didn't want to patch Bison > > itself. > > Agreed. But then, the syntax you choose, is a little weird: > the syntax is quite generic (we apply some treatment to $k, > which could be for instance printing its value (stupid, but > why not)), but the warning would be really specific for move. Indeed, I had considered both things separately, but together they don't make too much sense. > Shouldn't we go for something like %define api.value.move, > or api.rhs.move, or api.rhs.rvalue, etc. I mean, as a Boolean > value, not a generic placeholder. Might be better then (and would work for me, of course). Unless someone comes up with another valid use of the more generic feature (then we'd have to see how the warning would interact with it). Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> Le 15 sept. 2018 à 19:15, Frank Heckenbach a écrit : > > Akim Demaille wrote: > >> Would you recommend that we really import this into Bison? > > I would. My grammar file is much more readable with it, as it saves > me multiple std::move calls in most rules. Great, thanks for the input! > As I wrote, if Bison could detect multiple uses and warn, that would > be great, but I didn’t look into it as I didn't want to patch Bison > itself. Agreed. But then, the syntax you choose, is a little weird: the syntax is quite generic (we apply some treatment to $k, which could be for instance printing its value (stupid, but why not)), but the warning would be really specific for move. Shouldn’t we go for something like %define api.value.move, or api.rhs.move, or api.rhs.rvalue, etc. I mean, as a Boolean value, not a generic placeholder. First let’s decide what is the feature, then we’ll find the proper name :) > Another syntax (just for the sake of example "#1" for moving, while > keeping "$1" as is) might be an idea, but is still dangerous if one > uses $1 after #1, so probably not worth it. > > So, lacking other ideas, I'd stay with api.rhs.access, which was > easy to implement and does the job for me. I certainly don't want to > put std::move everywhere in my grammar. -- In fact, if I'd > ultimately have to, I'd make make up something like "#1" and > preprocess my grammar with sed before feeding it to Bison, to keep > it readable. Seeing as Bison does lots of processing of the source > anyway, this would seem overly complicated and bizarre to me. I don’t think Bison’s should have more special characters. #define M std::move can make it light enough, but I agree with adding automove.
Re: Automatially move from $n (was: C++11 move semantics)
> On 16 Sep 2018, at 01:01, Frank Heckenbach wrote: > > Hans Åberg wrote: > >> I realize now that you want to wrap $k with std::move and guard against >> reuse of that! (See below) > > Yes, see $subject. > >>> Sure it's possible: "make_pair ($1, $1)". Don't do that with >>> automatic move! >> >> Ah, your idea is to wrap std::move around the $k values! My idea >> is to let the C++ language recognise that, and then automate the >> assignment to $$. > > Again, the assignment to $$ is *NOT* the issue! (*) > It's the passing (moving) of $k. > > (*) Nitpick: Except in a case like "$$ = $2;", but then I'd argue >it's the passing of $2 to $$'s assignment operator that's the >issue. :) Maybe not for you, but for a more normal use, with types having both copy and move. Then one would like to use move to $$ whenever possible. Doesn't matter with me, as it is just some pointers and integers. >> Maybe there is some more general C++ code checking program that >> can be linked into Bison to check the actions. > > You mean some kind of code analyzer? This might be possible, but may > be overkill. Yes, you might check how people do check against that problem, if there is some program doing that. Then one might get ideas of how to get into Bison. Perhaps it might be possible to have some DLL or external program and invoke that. > Bison could keep track if any $k is used several times > and warn about that; though it may give false positives in cases > such as: > > $$ = $1 ? foo (move ($2)) : bar (move ($2)); // safe > > But the user could work around such (hopefully) rare cases with a > temporary variable holding move ($2). > > Or can code analyzers recognize the above as safe? (Do you have > experience with any?) No, but it seems me it is a hard problem. A compiler optimizer can recognize such things if it has sufficient information about the types, by tracing the code flow. > On the same token, Bison could then also (optionally) warn if some > $k which has a type is not used. I don't know if there is interest > in such a feature. It could also be useful for other languages. > > It might not be too hard to do for someone who's familiar with > Bison's internals. (Unfortunately, I'm not very much, and don't have > much free time right now.) How would this be different from the current static type system?
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > I realize now that you want to wrap $k with std::move and guard against reuse > of that! (See below) Yes, see $subject. > > Sure it's possible: "make_pair ($1, $1)". Don't do that with > > automatic move! > > Ah, your idea is to wrap std::move around the $k values! My idea > is to let the C++ language recognise that, and then automate the > assignment to $$. Again, the assignment to $$ is *NOT* the issue! (*) It's the passing (moving) of $k. (*) Nitpick: Except in a case like "$$ = $2;", but then I'd argue it's the passing of $2 to $$'s assignment operator that's the issue. :) > Maybe there is some more general C++ code checking program that > can be linked into Bison to check the actions. You mean some kind of code analyzer? This might be possible, but may be overkill. Bison could keep track if any $k is used several times and warn about that; though it may give false positives in cases such as: $$ = $1 ? foo (move ($2)) : bar (move ($2)); // safe But the user could work around such (hopefully) rare cases with a temporary variable holding move ($2). Or can code analyzers recognize the above as safe? (Do you have experience with any?) On the same token, Bison could then also (optionally) warn if some $k which has a type is not used. I don't know if there is interest in such a feature. It could also be useful for other languages. It might not be too hard to do for someone who's familiar with Bison's internals. (Unfortunately, I'm not very much, and don't have much free time right now.) Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 16 Sep 2018, at 00:18, Frank Heckenbach wrote: > > Hans Åberg wrote: > >>case k: >> auto action_k = [...](){ ... return ...; }; >> $$ = std::move(action_k(...)); > > I think you're at "$$" again rather than "$1" etc. I think we had > cleared that up. I realize now that you want to wrap $k with std::move and guard against reuse of that! (See below) So a way to make it safe is to jump out of the action statement. >>> >>> Not necessarily: You could use it twice within one expression >>> (unsafe even with jump) >> >> That would probably not be possible, if one gets an automated break after it. > > Sure it's possible: "make_pair ($1, $1)". Don't do that with > automatic move! Ah, your idea is to wrap std::move around the $k values! My idea is to let the C++ language recognise that, and then automate the assignment to $$. If you have a move only type and want it to safe as above, then you need some more general C++ checking mechanism. >>> or just not use it twice (safe even without >>> jump). >> >> But then one has to find a way to guard against that. > > So far, the guard would have to be the programmer. (Which is not > completely different from explicit std::move where one also needs to > be careful. C++ is not BASIC. ;) > > If Bison can detect it automatically, that would be nice, but > otherwise demanding some responsibility by the programmer seems > acceptable. Maybe there is some more general C++ code checking program that can be linked into Bison to check the actions. But that just applies it always, which might be safe for your move only type, >>> >>> In fact it's safe for copy-only types, and possibly unsafe precisely >>> for movable types (move-only or move-and-copyable). >> >> It is always unsafe with moves, unless one can find a guard against >> unintentional reuse of a moved-from element. > > "always ... unless" = "possibly" :) Indeed you have a lot of code, and then somebody sometime in the future should check it, perhaps yourself, and have forgotten about the details.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> But you can't safely or in general have Bison writing $$ = > >> std::move(a) directly as one might do something else to a > >> afterwards. > > > > It would be safe if Bison checked that it's used only once in the > > action. > > But in view of that is complicated, I was playing along with idea > to somehow using C++ to recognize it. The only way seems to use > function calls and return, as assignments can be applied more than > once. So the idea is that if Bison now writes > switch (yyn) { > ... > case k: > { > ... > } > } > where the action may have $$ = ..., one has > case k: > $$ = std::move(action_k(...)); > where the action_k is some function where one returns the value instead. I'm > not sure exactly how to pick it together, perhaps fitting a lambda capture > case k: > auto action_k = [...](){ ... return ...; }; > $$ = std::move(action_k(...)); I think you're at "$$" again rather than "$1" etc. I think we had cleared that up. > >> So a way to make it safe is to jump out of the action statement. > > > > Not necessarily: You could use it twice within one expression > > (unsafe even with jump) > > That would probably not be possible, if one gets an automated break after it. Sure it's possible: "make_pair ($1, $1)". Don't do that with automatic move! > > or just not use it twice (safe even without > > jump). > > But then one has to find a way to guard against that. So far, the guard would have to be the programmer. (Which is not completely different from explicit std::move where one also needs to be careful. C++ is not BASIC. ;) If Bison can detect it automatically, that would be nice, but otherwise demanding some responsibility by the programmer seems acceptable. > >> But that just applies it always, which might be safe for your move only > >> type, > > > > In fact it's safe for copy-only types, and possibly unsafe precisely > > for movable types (move-only or move-and-copyable). > > It is always unsafe with moves, unless one can find a guard against > unintentional reuse of a moved-from element. "always ... unless" = "possibly" :) Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 15 Sep 2018, at 23:26, Frank Heckenbach wrote: > > Hans Åberg wrote: > >> But you can't safely or in general have Bison writing $$ = >> std::move(a) directly as one might do something else to a >> afterwards. > > It would be safe if Bison checked that it's used only once in the > action. But in view of that is complicated, I was playing along with idea to somehow using C++ to recognize it. The only way seems to use function calls and return, as assignments can be applied more than once. So the idea is that if Bison now writes switch (yyn) { … case k: { … } } where the action may have $$ = …, one has case k: $$ = std::move(action_k(…)); where the action_k is some function where one returns the value instead. I'm not sure exactly how to pick it together, perhaps fitting a lambda capture case k: auto action_k = […](){ … return …; }; $$ = std::move(action_k(…)); >> So a way to make it safe is to jump out of the action statement. > > Not necessarily: You could use it twice within one expression > (unsafe even with jump) That would probably not be possible, if one gets an automated break after it. > or just not use it twice (safe even without > jump). But then one has to find a way to guard against that. >>> What I want (or actually have, since I imeplented it :) is a way to >>> make Bison apply std::move automatically. >> >> But that just applies it always, which might be safe for your move only type, > > In fact it's safe for copy-only types, and possibly unsafe precisely > for movable types (move-only or move-and-copyable). It is always unsafe with moves, unless one can find a guard against unintentional reuse of a moved-from element.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > But you can't safely or in general have Bison writing $$ = > std::move(a) directly as one might do something else to a > afterwards. It would be safe if Bison checked that it's used only once in the action. > So a way to make it safe is to jump out of the action statement. Not necessarily: You could use it twice within one expression (unsafe even with jump) or just not use it twice (safe even without jump). > > What I want (or actually have, since I imeplented it :) is a way to > > make Bison apply std::move automatically. > > But that just applies it always, which might be safe for your move only type, In fact it's safe for copy-only types, and possibly unsafe precisely for movable types (move-only or move-and-copyable). > but is not safe in general, right? Right, that't why I made it opt-in by setting api.rhs.access. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 15 Sep 2018, at 22:56, Frank Heckenbach wrote: > > You don't need h at all. > > Simply "b = std::move (a);" will do the same. All it does is convert > a to an rvalue reference. If A has a move assignment operator, this > will be chosen, if it doesn't but a copy assignment operator, that > one will be chosen. That's all standard C++ behaviour. But you can't safely or in general have Bison writing $$ = std::move(a) directly as one might do something else to a afterwards. So a way to make it safe is to jump out of the action statement. Using functions and returns is probably not a good idea because one would have to capture variables in the action. > What I want (or actually have, since I imeplented it :) is a way to > make Bison apply std::move automatically. But that just applies it always, which might be safe for your move only type, but is not safe in general, right?
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > If I write: > > A& h(A& a) { > return a; > } > > A&& h(A&& a) { > return std::move(a); > } h seems like a NOP. > int main() { > A a, b; > > b = std::move(h(a)); > b = std::move(h(std::move(a))); You don't need "std::move" twice here. > return EXIT_SUCCESS; > } > > Then if A only has copy assignment, that will be used, but if has > that and move assignment or only move assignment, then move > assignment will be used. No copying occurs with copy elision. You don't need h at all. Simply "b = std::move (a);" will do the same. All it does is convert a to an rvalue reference. If A has a move assignment operator, this will be chosen, if it doesn't but a copy assignment operator, that one will be chosen. That's all standard C++ behaviour. > Isn't that what you want? What I want (or actually have, since I imeplented it :) is a way to make Bison apply std::move automatically. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
On 15 Sep 2018, at 22:10, Frank Heckenbach wrote: > > Hans Åberg wrote: > >> The idea would be to write something equivalent to >> return make_unique($1, $2, $3); >> and the Bison writes something like >> $$ = std::move(action_k(...return make_unique($1, $2, $3);...)) > > I don't follow you. What is action_k, and how would that cause > moving from $1 etc.? Action k in the switch statement. >>> >>> Huh? I really don't get what your proposed syntax is supposed to >>> mean. Is action_k supposed to be a lambda (what else could appear in >>> an expression and contain a statement inside)? What would it do? >> >> Just produce an r-value. > > Again: > > - make_unique already produces an rvalue > > - (I'll ignore the "...return", since you didn't comment on it, I > assume it's a typo) > > - Then, you say, action_k produces an rvalue, from an rvalue? > > - Finally, std::move takes this rvalue and turns it into an rvalue > (because that's what std::move does). > > Do you want a triple-r-value? > > Sorry if I'm a bit cynical meanwhile, but I said I don't follow what > you intend to do, so it would be nice to explain it with something > more than half a sentence, really. If I write: A& h(A& a) { return a; } A&& h(A&& a) { return std::move(a); } int main() { A a, b; b = std::move(h(a)); b = std::move(h(std::move(a))); return EXIT_SUCCESS; } Then if A only has copy assignment, that will be used, but if has that and move assignment or only move assignment, then move assignment will be used. No copying occurs with copy elision. Isn't that what you want?
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > The idea would be to write something equivalent to > return make_unique($1, $2, $3); > and the Bison writes something like > $$ = std::move(action_k(...return make_unique($1, $2, $3);...)) > >>> > >>> I don't follow you. What is action_k, and how would that cause > >>> moving from $1 etc.? > >> > >> Action k in the switch statement. > > > > Huh? I really don't get what your proposed syntax is supposed to > > mean. Is action_k supposed to be a lambda (what else could appear in > > an expression and contain a statement inside)? What would it do? > > Just produce an r-value. Again: - make_unique already produces an rvalue - (I'll ignore the "...return", since you didn't comment on it, I assume it's a typo) - Then, you say, action_k produces an rvalue, from an rvalue? - Finally, std::move takes this rvalue and turns it into an rvalue (because that's what std::move does). Do you want a triple-r-value? Sorry if I'm a bit cynical meanwhile, but I said I don't follow what you intend to do, so it would be nice to explain it with something more than half a sentence, really. > >> Move operators were originally designed to avoid copying in returns. > > > > I don't know if this was so or not originally, but I'm talking about > > moving arguments, not return values. That's what I've been saying > > the whole time, including the thread subject! Moving the return > > value is no big problem most of the time: "$$ = make_unique ..." > > works without any std::move because a function result(*) is > > automatically an rvalue. > > The idea is to create an r-value situation, which then translates into a move > assignment. Again, make_unique already "creates an rvalue situation". And, also again, how does any of that help with moving from $1, $2 etc. which is the actual topic? Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 15 Sep 2018, at 21:57, Frank Heckenbach wrote: > > Hans Åberg wrote: > The idea would be to write something equivalent to return make_unique($1, $2, $3); and the Bison writes something like $$ = std::move(action_k(...return make_unique($1, $2, $3);...)) >>> >>> I don't follow you. What is action_k, and how would that cause >>> moving from $1 etc.? >> >> Action k in the switch statement. > > Huh? I really don't get what your proposed syntax is supposed to > mean. Is action_k supposed to be a lambda (what else could appear in > an expression and contain a statement inside)? What would it do? Just produce an r-value. >> Move operators were originally designed to avoid copying in returns. > > I don't know if this was so or not originally, but I'm talking about > moving arguments, not return values. That's what I've been saying > the whole time, including the thread subject! Moving the return > value is no big problem most of the time: "$$ = make_unique ..." > works without any std::move because a function result(*) is > automatically an rvalue. The idea is to create an r-value situation, which then translates into a move assignment.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> The idea would be to write something equivalent to > >> return make_unique($1, $2, $3); > >> and the Bison writes something like > >> $$ = std::move(action_k(...return make_unique($1, $2, $3);...)) > > > > I don't follow you. What is action_k, and how would that cause > > moving from $1 etc.? > > Action k in the switch statement. Huh? I really don't get what your proposed syntax is supposed to mean. Is action_k supposed to be a lambda (what else could appear in an expression and contain a statement inside)? What would it do? > Move operators were originally designed to avoid copying in returns. I don't know if this was so or not originally, but I'm talking about moving arguments, not return values. That's what I've been saying the whole time, including the thread subject! Moving the return value is no big problem most of the time: "$$ = make_unique ..." works without any std::move because a function result(*) is automatically an rvalue. (*) Nitpick: unless it's declared of lvalue-reference type which is not the case here. I'm afrading you're barking up the wrong tree. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 15 Sep 2018, at 21:25, Frank Heckenbach wrote: > > Hans Åberg wrote: >> The idea would be to write something equivalent to >> return make_unique($1, $2, $3); >> and the Bison writes something like >> $$ = std::move(action_k(...return make_unique($1, $2, $3);...)) > > I don't follow you. What is action_k, and how would that cause > moving from $1 etc.? Action k in the switch statement. Move operators were originally designed to avoid copying in returns. >> Even in view of copy elision, default in C++17 [1], this would be safe, >> because one cannot move an already moved object by mistake. > > Why not? Because it breaks the execution path, so one cannot apply it twice to the same value. >> As the point is breaking out of the execution path, one might use your >> suggestion of a special operator in combination with an immediately >> following break in the action switch statement. So writing say >> $$$(make_unique($1, $2, $3)); >> translates into >> $$ = std::move(make_unique($1, $2, $3)); >> break; > > What if I want to write: > > $$ = make_unique ($1, $2, $3); > print ($$); Then you can't use the proposed $$$, but has to use the old syntax.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> One idea might be to wrap the actions in inlines, and use return instead, > >> as C++ can recognize r-values in such situations. > > > > I think we discussed this before, but this would only cover the case > > "$$ = $N" (which is covered by the default action for N = 1 anyway). > > > > More interesting are cases such as: > > > > $$ = make_unique ($1, $2, $3); > > The idea would be to write something equivalent to > return make_unique($1, $2, $3); > and the Bison writes something like > $$ = std::move(action_k(...return make_unique($1, $2, $3);...)) I don't follow you. What is action_k, and how would that cause moving from $1 etc.? > Even in view of copy elision, default in C++17 [1], this would be safe, > because one cannot move an already moved object by mistake. Why not? > As the point is breaking out of the execution path, one might use your > suggestion of a special operator in combination with an immediately following > break in the action switch statement. So writing say > $$$(make_unique($1, $2, $3)); > translates into > $$ = std::move(make_unique($1, $2, $3)); > break; What if I want to write: $$ = make_unique ($1, $2, $3); print ($$); Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 15 Sep 2018, at 20:19, Frank Heckenbach wrote: > > Hans Åberg wrote: > >> One idea might be to wrap the actions in inlines, and use return instead, as >> C++ can recognize r-values in such situations. > > I think we discussed this before, but this would only cover the case > "$$ = $N" (which is covered by the default action for N = 1 anyway). > > More interesting are cases such as: > > $$ = make_unique ($1, $2, $3); The idea would be to write something equivalent to return make_unique($1, $2, $3); and the Bison writes something like $$ = std::move(action_k(…return make_unique($1, $2, $3);…)) Even in view of copy elision, default in C++17 [1], this would be safe, because one cannot move an already moved object by mistake. As the point is breaking out of the execution path, one might use your suggestion of a special operator in combination with an immediately following break in the action switch statement. So writing say $$$(make_unique($1, $2, $3)); translates into $$ = std::move(make_unique($1, $2, $3)); break; 1. https://en.cppreference.com/w/cpp/language/copy_elision
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > One idea might be to wrap the actions in inlines, and use return instead, as > C++ can recognize r-values in such situations. I think we discussed this before, but this would only cover the case "$$ = $N" (which is covered by the default action for N = 1 anyway). More interesting are cases such as: $$ = make_unique ($1, $2, $3); Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 15 Sep 2018, at 19:15, Frank Heckenbach wrote: > > Akim Demaille wrote: > >>> By default it's empty, so it's like before, but one can e.g. add >>> >>> %define api.rhs.access {std::move} >> >> I would like to have your opinion on this, a few months after >> having practiced the idea. It looks great, but some ideas look >> great first, and them show some limitations. >> >> Would you recommend that we really import this into Bison? > > I would. My grammar file is much more readable with it, as it saves > me multiple std::move calls in most rules. > > Of course, there's a danger of using a moved-from value. When I > introduces it, I had to check my grammars for multiple uses of the > same value which I did to a first approximation with a regex search > (something like "(\$[0-9]+).*\1"), then checked the few remaining > cases manually (but my grammar rules are rather simple; most of the > actual work is done in external functions, often just make_unique<>, > sometimes self-written ones). > > As I wrote, if Bison could detect multiple uses and warn, that would > be great, but I didn't look into it as I didn't want to patch Bison > itself. > > Another syntax (just for the sake of example "#1" for moving, while > keeping "$1" as is) might be an idea, but is still dangerous if one > uses $1 after #1, so probably not worth it. > > So, lacking other ideas, I'd stay with api.rhs.access, which was > easy to implement and does the job for me. I certainly don't want to > put std::move everywhere in my grammar. -- In fact, if I'd > ultimately have to, I'd make make up something like "#1" and > preprocess my grammar with sed before feeding it to Bison, to keep > it readable. Seeing as Bison does lots of processing of the source > anyway, this would seem overly complicated and bizarre to me. One idea might be to wrap the actions in inlines, and use return instead, as C++ can recognize r-values in such situations.
Re: Automatially move from $n (was: C++11 move semantics)
Akim Demaille wrote: > > Le 1 avr. 2018 à 16:43, Frank Heckenbach a écrit : > > > > I've now changed my grammars to use my new C++17 skeletons with > > std::variant and move semantics. So far, it seems to work fine. > > > > As expected, they now contain a lot of "std::move ($n)" expressions. > > Even though the simple case "$$ = std::move ($1)" is now covered by > > the default action, most are actually within expressions such as > > "$$ = make_foo (std::move ($1), std::move ($2))" which is less than > > perfectly readable ... > > > > [...] > > That's what I've implemented now -- except for the warning (which > > doesn't seem possible without changes to Bison itself). > > > > In fact, rather than a Boolean option, I added a define that's > > wrapped around every $n access. (Though ATM I can't think of any > > other function except std::move one might want to use there -- maybe > > some fancy debugging stuff if Bison's trace mechanism isn't > > sufficient, or whatever ...) > > > > By default it's empty, so it's like before, but one can e.g. add > > > > %define api.rhs.access {std::move} > > I would like to have your opinion on this, a few months after > having practiced the idea. It looks great, but some ideas look > great first, and them show some limitations. > > Would you recommend that we really import this into Bison? I would. My grammar file is much more readable with it, as it saves me multiple std::move calls in most rules. Of course, there's a danger of using a moved-from value. When I introduces it, I had to check my grammars for multiple uses of the same value which I did to a first approximation with a regex search (something like "(\$[0-9]+).*\1"), then checked the few remaining cases manually (but my grammar rules are rather simple; most of the actual work is done in external functions, often just make_unique<>, sometimes self-written ones). As I wrote, if Bison could detect multiple uses and warn, that would be great, but I didn't look into it as I didn't want to patch Bison itself. Another syntax (just for the sake of example "#1" for moving, while keeping "$1" as is) might be an idea, but is still dangerous if one uses $1 after #1, so probably not worth it. So, lacking other ideas, I'd stay with api.rhs.access, which was easy to implement and does the job for me. I certainly don't want to put std::move everywhere in my grammar. -- In fact, if I'd ultimately have to, I'd make make up something like "#1" and preprocess my grammar with sed before feeding it to Bison, to keep it readable. Seeing as Bison does lots of processing of the source anyway, this would seem overly complicated and bizarre to me. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> Le 1 avr. 2018 à 16:43, Frank Heckenbach a écrit : > > I've now changed my grammars to use my new C++17 skeletons with > std::variant and move semantics. So far, it seems to work fine. > > As expected, they now contain a lot of "std::move ($n)" expressions. > Even though the simple case "$$ = std::move ($1)" is now covered by > the default action, most are actually within expressions such as > "$$ = make_foo (std::move ($1), std::move ($2))" which is less than > perfectly readable ... > > […] > That's what I've implemented now -- except for the warning (which > doesn't seem possible without changes to Bison itself). > > In fact, rather than a Boolean option, I added a define that's > wrapped around every $n access. (Though ATM I can't think of any > other function except std::move one might want to use there -- maybe > some fancy debugging stuff if Bison's trace mechanism isn't > sufficient, or whatever ...) > > By default it's empty, so it's like before, but one can e.g. add > > %define api.rhs.access {std::move} Frank, I would like to have your opinion on this, a few months after having practiced the idea. It looks great, but some ideas look great first, and them show some limitations. Would you recommend that we really import this into Bison?
Re: Automatially move from $n (was: C++11 move semantics)
> On 1 Apr 2018, at 23:13, Frank Heckenbach wrote: > > Hans Åberg wrote: > >> An advantage with operators names is avoiding parentheses, but a >> problem is that they are hard to search for, but here, since they >> will always together with the $k, that should not be a problem. >> Candidate names might be operator * & ~ + -. > > As I said, I'm not really fond of (mis)using operators like that. > Of course, you (or anyone else) might disagree and do it like that, > Bison neither encourages nor prevents it. > > My "%define" proposal is an alternative (also completely optional; > if you don't set it, it won't do anything). I think it's a bit > easier to use and more general -- it will apply to all types > (including primitive types, where moving is the same as copying, so > effectively no change for them), whereas you'd have to define the > overloaded operator for each relevant type (and couldn't blindly > define it for all types as it already has a meaning for some of > them). Do you have any objections to my "%define" proposal? It any future Bison developer that decides what to integrate. Otherwise, I think it is OK to be able to choose wrap around $k, but potentially unsafe to always have implicit std::move without pitfall checks.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > An advantage with operators names is avoiding parentheses, but a > problem is that they are hard to search for, but here, since they > will always together with the $k, that should not be a problem. > Candidate names might be operator * & ~ + -. As I said, I'm not really fond of (mis)using operators like that. Of course, you (or anyone else) might disagree and do it like that, Bison neither encourages nor prevents it. My "%define" proposal is an alternative (also completely optional; if you don't set it, it won't do anything). I think it's a bit easier to use and more general -- it will apply to all types (including primitive types, where moving is the same as copying, so effectively no change for them), whereas you'd have to define the overloaded operator for each relevant type (and couldn't blindly define it for all types as it already has a meaning for some of them). Do you have any objections to my "%define" proposal? Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 1 Apr 2018, at 22:32, Frank Heckenbach wrote: > > Hans Åberg wrote: > >>> If semantic_type doesn't have a "*" operator of its own, this might >>> work (but look confusing). However, I use the variant (so I'd need >>> this function for each alternative, which might be possible to do >>> with templates), but some of my semantic values are (smart) >>> pointers, so "*" is already used (and even if I could somehow >>> override it, it would suggest dereferencing rather than moving). >> >> Alternative unary operators are listed as point 3 at [1]. One can >> overload operator&, but is more confusing than *, as it disables >> taking the address-of. > > Yeah; all existing operators have their meaning, and might apply to > some or all alternatives one might use. C++ doesn't allow defining > new operators (probably for good reasons), and I'm generally wary of > overloading operators for unrelated purposes (don't already like the > stream "<<" and ">>" too much). > >>> Now, if C++ had a dedicated move operator (which would also be >>> useful in other code) ... But (ab)using an existing operator seems >>> confusing to me. >> >> Or a shorter name. > > Well, with "using std::move" it's a bit shorter (just "move ($n)"), > but still too much clutter for my taste. An advantage with operators names is avoiding parentheses, but a problem is that they are hard to search for, but here, since they will always together with the $k, that should not be a problem. Candidate names might be operator * & ~ + -.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > > If semantic_type doesn't have a "*" operator of its own, this might > > work (but look confusing). However, I use the variant (so I'd need > > this function for each alternative, which might be possible to do > > with templates), but some of my semantic values are (smart) > > pointers, so "*" is already used (and even if I could somehow > > override it, it would suggest dereferencing rather than moving). > > Alternative unary operators are listed as point 3 at [1]. One can > overload operator&, but is more confusing than *, as it disables > taking the address-of. Yeah; all existing operators have their meaning, and might apply to some or all alternatives one might use. C++ doesn't allow defining new operators (probably for good reasons), and I'm generally wary of overloading operators for unrelated purposes (don't already like the stream "<<" and ">>" too much). > > Now, if C++ had a dedicated move operator (which would also be > > useful in other code) ... But (ab)using an existing operator seems > > confusing to me. > > Or a shorter name. Well, with "using std::move" it's a bit shorter (just "move ($n)"), but still too much clutter for my taste. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 1 Apr 2018, at 21:47, Frank Heckenbach wrote: > > Hans Åberg wrote: > Maybe Bison might support some additional symbol for move action values, like $$k. >>> >>> I'd thought about this, but it would require changes to Bison itself >>> (for a rather special feature, only for only target language, which >>> can be done in the skeletons), and the user grammar files would also >>> look differently, whereas with my way, they generally look just like >>> they would with shared pointers, or in C, Java, etc., i.e. >>> "$$ = make_foo ($1, $2)". >>> >>> Also "$$k" would look rather similar to "$$" (probably not strictly >>> a conflict, but maybe confusing). >> >> Maybe just add to %code: >> semantic_type&& operator*(semantic_type& x) { return std::move(x); } >> and use *$k, in case this operator is not needed for something else. Should have been inlined: inline semantic_type&& operator*(semantic_type& x) { return std::move(x); } > If semantic_type doesn't have a "*" operator of its own, this might > work (but look confusing). However, I use the variant (so I'd need > this function for each alternative, which might be possible to do > with templates), but some of my semantic values are (smart) > pointers, so "*" is already used (and even if I could somehow > override it, it would suggest dereferencing rather than moving). Alternative unary operators are listed as point 3 at [1]. One can overload operator&, but is more confusing than *, as it disables taking the address-of. 1. http://en.cppreference.com/w/cpp/language/operator_precedence > Now, if C++ had a dedicated move operator (which would also be > useful in other code) ... But (ab)using an existing operator seems > confusing to me. Or a shorter name.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > >> Maybe Bison might support some additional symbol for move action values, > >> like $$k. > > > > I'd thought about this, but it would require changes to Bison itself > > (for a rather special feature, only for only target language, which > > can be done in the skeletons), and the user grammar files would also > > look differently, whereas with my way, they generally look just like > > they would with shared pointers, or in C, Java, etc., i.e. > > "$$ = make_foo ($1, $2)". > > > > Also "$$k" would look rather similar to "$$" (probably not strictly > > a conflict, but maybe confusing). > > Maybe just add to %code: > semantic_type&& operator*(semantic_type& x) { return std::move(x); } > and use *$k, in case this operator is not needed for something else. If semantic_type doesn't have a "*" operator of its own, this might work (but look confusing). However, I use the variant (so I'd need this function for each alternative, which might be possible to do with templates), but some of my semantic values are (smart) pointers, so "*" is already used (and even if I could somehow override it, it would suggest dereferencing rather than moving). Now, if C++ had a dedicated move operator (which would also be useful in other code) ... But (ab)using an existing operator seems confusing to me. Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 1 Apr 2018, at 19:23, Frank Heckenbach wrote: > > Hans Åberg wrote: > >>> On 1 Apr 2018, at 16:43, Frank Heckenbach wrote: >>> >>> As expected, they now contain a lot of "std::move ($n)" expressions. >>> Even though the simple case "$$ = std::move ($1)" is now covered by >>> the default action, most are actually within expressions such as >>> "$$ = make_foo (std::move ($1), std::move ($2))" which is less than >>> perfectly readable ... >> >> Maybe Bison might support some additional symbol for move action values, >> like $$k. > > I'd thought about this, but it would require changes to Bison itself > (for a rather special feature, only for only target language, which > can be done in the skeletons), and the user grammar files would also > look differently, whereas with my way, they generally look just like > they would with shared pointers, or in C, Java, etc., i.e. > "$$ = make_foo ($1, $2)". > > Also "$$k" would look rather similar to "$$" (probably not strictly > a conflict, but maybe confusing). Maybe just add to %code: semantic_type&& operator*(semantic_type& x) { return std::move(x); } and use *$k, in case this operator is not needed for something else.
Re: Automatially move from $n (was: C++11 move semantics)
Hans Åberg wrote: > > On 1 Apr 2018, at 16:43, Frank Heckenbach wrote: > > > > I've now changed my grammars to use my new C++17 skeletons with > > std::variant and move semantics. So far, it seems to work fine. > > > > As expected, they now contain a lot of "std::move ($n)" expressions. > > Even though the simple case "$$ = std::move ($1)" is now covered by > > the default action, most are actually within expressions such as > > "$$ = make_foo (std::move ($1), std::move ($2))" which is less than > > perfectly readable ... > > Maybe Bison might support some additional symbol for move action values, like > $$k. I'd thought about this, but it would require changes to Bison itself (for a rather special feature, only for only target language, which can be done in the skeletons), and the user grammar files would also look differently, whereas with my way, they generally look just like they would with shared pointers, or in C, Java, etc., i.e. "$$ = make_foo ($1, $2)". Also "$$k" would look rather similar to "$$" (probably not strictly a conflict, but maybe confusing). Regards, Frank
Re: Automatially move from $n (was: C++11 move semantics)
> On 1 Apr 2018, at 16:43, Frank Heckenbach wrote: > > I've now changed my grammars to use my new C++17 skeletons with > std::variant and move semantics. So far, it seems to work fine. > > As expected, they now contain a lot of "std::move ($n)" expressions. > Even though the simple case "$$ = std::move ($1)" is now covered by > the default action, most are actually within expressions such as > "$$ = make_foo (std::move ($1), std::move ($2))" which is less than > perfectly readable ... Maybe Bison might support some additional symbol for move action values, like $$k.
Re: Automatially move from $n (was: C++11 move semantics)
> On 1 Apr 2018, at 16:43, Frank Heckenbach wrote: > > I've now changed my grammars to use my new C++17 skeletons with > std::variant and move semantics. So far, it seems to work fine. > > As expected, they now contain a lot of "std::move ($n)" expressions. > Even though the simple case "$$ = std::move ($1)" is now covered by > the default action, most are actually within expressions such as > "$$ = make_foo (std::move ($1), std::move ($2))" which is less than > perfectly readable ... Maybe Bison might support some additional symbol for move action values, like $$k.
Automatially move from $n (was: C++11 move semantics)
I've now changed my grammars to use my new C++17 skeletons with std::variant and move semantics. So far, it seems to work fine. As expected, they now contain a lot of "std::move ($n)" expressions. Even though the simple case "$$ = std::move ($1)" is now covered by the default action, most are actually within expressions such as "$$ = make_foo (std::move ($1), std::move ($2))" which is less than perfectly readable ... In the original thread, I wrote: > Hans Åberg wrote: > > > >> Perhaps if it know that $1 expires, it can apply a move assignment. > > > > > > It could do that if $1 is mentioned only once. [...] > > > > I think it would be complicated, so just std::move for now. > > I looked into the code. Just adding std::move seems rather easy, but > finding out if a $n is mentioned several times might be tricky on > the m4 level, might require changes to Bison itself. > > And the question remains what to do then. One possibility would be > an option auto-move or such. If not set, std::move is not inserted; > if set it's always inserted, but Bison warns if $n is mentioned > several times. That's what I've implemented now -- except for the warning (which doesn't seem possible without changes to Bison itself). In fact, rather than a Boolean option, I added a define that's wrapped around every $n access. (Though ATM I can't think of any other function except std::move one might want to use there -- maybe some fancy debugging stuff if Bison's trace mechanism isn't sufficient, or whatever ...) By default it's empty, so it's like before, but one can e.g. add %define api.rhs.access {std::move} to always move from all $n. It's then left to the user to make sure moving is safe. For my style of grammar that's fine -- I prefer to do all nontrivial stuff in helper functions, so it's very rare that any $n is mentioned several times in an action (including mid-rule actions) at all. If it is, one can always work around it, by moving to a temporary first, or "un-moving" (after all, std::move doesn't actually move, just type-cast to a moveable rvalue, so one can make it unmoveable again with no harm done). This seems rather lightweight, both to implement in the skeleton and to use in the grammar file, and helps readability a lot for me. Regards, Frank