C++ Logo

SG7

Advanced search

Subject: Re: Questions about P2237R0
From: Hana Dusíková (hanicka_at_[hidden])
Date: 2020-11-18 08:52:09


No reason at all, this email was supposed to be only heads-up for questions I was asked by her to ask you.

But since you added your answers here I'm adding her and SG7 reflector to the conversation.

Hana

> On 18. 11. 2020, at 15:34, Andrew Sutton <asutton_at_[hidden] <mailto:asutton_at_[hidden]>> wrote:
>
> Any reason Isabella isn't CC'd on this email? Or sent to the reflector?
>
>
> re: splicing
>
> 1. I like the idea of splicing as a concept. I am mildly concerned about the syntax, as the examples only show non-ambiguous declarations for parsing. On page 18 the in 6.3.1, the phrase
>> In other words, splicing a reflected construct is exactly as if that construct had been written by hand
>
> if written, but if these ' handwritten names' work correctly i.e., wouldn't x |reflexpr(std)| technically count as a valid expression? And if not, could this section be expanded to explain this more clearly.
> Additionally wouldn't the syntax of |x|>>y be ambiguous if the |> operator is added? Even 4<|x|>3 could technically be ambiguous with some parsers, would it not, even if the code is incorrect?
>
> 2. How will splicing work in conjunction with operator |> overall?
>
> Yes, |reflexpr(std)| would be a valid expression to be spliced, The result is that it would (eventually) generate the namespace-name std, as expected.
>
> If |> is taken as an operator for C++2X, then there will be max munch issues. But I think the resolutions are not fundamentally different than handling >> at the end of a nested template-argument-list. There are more cases though. In |x|>>y, the parser knows to expect a single | after x, but finds |> followed by >. It should be possible to transform the token sequence to | and >>. The same is true for 4<|x|>3, but that's a little easier because you don't need an extra token of lookahead.
>
> 2 is a fairly broad question. I don't really know much about it, so any thoughts I had about language interaction would be... not well informed :) That said, I'm not particularly concerned about grammatical interactions. Because splicing is a primary expression, the places where the parser matches |> and the start of |x| do not overlap. For example, |a| |> |b| is just fine. As is the terser and less comprehensible spelling |a||>|b|, if parsers can separate the ||> into
>
>
> re: source code injection
>
> 1. I am very much not a fan of unary << as an injector. There MUST be a better way to do this, and I would like to see more rationale regarding the selection of syntax beyond "std::istream uses it, and we're re-using it from the std::forward as a builtin operator paper"
>
> The motivation and rationale is entirely that we conventionally use << for stream insertion. Of course there are other ways to spell it, and I haven't been happy with many of them. I am quite happy with <<.
>
> Although, as I think about it, this is going to potentially interact with stereotypes (if we adopt that feature with that syntax)... hmm.
>
> I'm not sure what the std::forward reference is for. I don't think I mentioned that paper.
>
>
> 2. is usage of %{name} needed? Even EBCDIC has a $. Some folks have said this would 'break' their tools, but these tools aren't written in C++ nor would said tools be necessary if metaprogramming were added
>
> Yes and no. There is a language mechanic with the semantics we attribute to %{name}. Initially (early metaclass work), I chose to represent that as a capture list on the fragment. Herb didn't like that, so we made it entirely implicit. I *hated* that---it made code very, very confusing to reason about---so we invented something that looks a bit like string interpolation.
>
> Sadly, $ as an operator was killed a long time ago. Before Urbana-Champaign IIRC (and I probably don't). That's a fight I"m not going take up.
>
>
> 3. Instead of calling these injections declarations, I would prefer the name blueprint declaration and the action we take with a blueprint of any kind is to inject its result.
>
> Hard pass.
>
> The declaration is named after the injection mechanism, not the operand, which is an expression. You're not declaring the thing to be injected, you're declaring that there is an injection *at this point in the program*.
>
>
> 4. I am also concerned regarding the usage of |# and #| delimiters. Does this mean that bitor # is a valid delimiter? If not, would we not need a ISO646 equivalent of these operators? (I am aware this has not been discussed with the |> paper, and that most folks would like to kill this stuff but they exist and we should have to care about them :sweat_smile:
>
> No, it does not imply that. |# and #| are distinct tokens. If we really need ISO6464 alternatives, I'm sure we can come up with some weird alternative spelling.
>
>
> 5. Instead of opening and closing a fragment with <, would it be better to continue introducing the use of template? i.e., template fragment-declaration-here instead of < would introduce a fragment? I feel like the opening and closing of <> is going to be a constant mistake folks make, and tools like VSCode and other 'auto-closing of braces' will break or get things wrong.
>
> Fragments are sufficiently different from templates that the name doesn't fit. Templates are complete definitions, fragments are not. Templates are instantiated by substituting template arguments for their parameters. Fragments are injected by substituting "other things".
>
> I have no idea what mistakes people are going to make. I also hate these kinds of arguments because they're really indefensible. I feel that people won't make those mistakes. Now we're at an impasse :)
>
> I don't think auto-closing these things would be that hard to implement. If you can do it for template argument lists, you should be able do it for <>-enclosed fragments. To be fair, though, I'm not sure how much syntactic analysis is performed when auto-closing braces.
>
>
> 6. P1887 introduces a standard attribute decorator, but if attributes can't be enforced, how can we rely on its usage + existence?
>
> Good question. Not my paper, not my fight.
>
> I think the idea of having queryable attribute data satisfies a lot of metaprogramming use cases, especially when coupled with source code injection. That said, I don't like the + notation very much and I think you make a strong argument here that a different syntax should be chosen.
>
> I've been wondering if we shouldn't fold these attributes into the stereotype concept, just because the syntax is way different than attributes and already expects an expression as an operand. You can probably differentiate a stereotype "label" (as data) from a stereotype transformation by the type or form of the expression.
>
> <<catch::test_case("blah")>> // data
> void f();
>
> <<herb::interface>> // transform
> struct ifoo { ... };
>
>
> 7. Could the usage of a + in 8.3 interact poorly with a lambda and possibly be ambiguous? Would [[using Catch: +test_case("copy")]] be valid syntax?
>
> I don't know. I don't think so. See above.
>
>
> re: compile-time i/o
>
> 1. 9.3.1 says regarding names "in an implementation-defined way", however I would recommend we ask SG16 for guidance on this, as it turns out "implementation defined" can mean a lot of things even for one implementation. There is also no mention of environment variables, which is a valid use case for configuration at compile vs runtime.
>
> Sure. When I say "implementation-defined", I assume vendors will consult on the side to find some common practices.
>
> Environment variables are interesting. I didn't mention them, because they aren't actually external data. It's part of the operating environment and should be considered separately from file I/O. I'm actually working on something that would make the compiler's environment and some build options available during constant expression evaluation. We'll see how that works out.
>
>
> 2. 9.3.4 shows modifying files at compile time. I see no evidence on how to prevent file writing race conditions in a distributed build that might occur across a network. Additionally I don't see anything regarding how this might affect dynamic dependencies in existing build systems when we struggle to do this in extreme cases already (see shake, llbuild as the only build systems to date which support this random output, of which llbuild just runs ninja twice). Theoretically, a modify of a file during a build could cause an infinite build loop with no termination.
>
> There's no provision for avoiding race conditions in writable resources. That's the responsibility of the build system. And yes, the build system could time out. This entire section is speculative, so take it with a grain of salt. That said, there are certainly use cases for synthesizing data from C++ code.
>
> Given that each translation unit in a program is unique, we could probably alleviate the data race problem by defining an abstract set of writable files associated specifically with each translation unit. Kind of like a module partition and not a globally accessible module name, but specific to the TU and not the module. Basically, each TU can write to its own distinct set of outputs and no others.
>
>
> re: runtime facilities
>
> 1. 10.1 -- Would operator . be needed if 10.2 is utilized to inject fragments?
>
> Needed? I don't know. Purely speculating here.
>
>
> 2. How does this affect things like lldb python api and gdb's Xmethod plugin?
>
> No idea.
>
>
> 3. 10.2 -- will we be able to inject dynamic constructors?
>
> Same answer.
>
> Andrew



SG7 list run by sg7-owner@lists.isocpp.org

Older Archives on Google Groups