| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Rebase to main. Make is() function constexpr |
Sorry, something went wrong.
|
Thanks! This also has some variant changes that I want to avoid now so as not to break variants with repeated types, but I don't think anything in the rest of the PR depends on those and I can just look at the literal-related changes -- correct? |
Sorry, something went wrong.
|
Check the literals part. I will check the commits. Give me a minute. |
Sorry, something went wrong.
|
Ahh... I was rebasing yesterday to resolve this dependency and forgot to push. Now fixed. |
Sorry, something went wrong.
|
OK, it's mostly clean, but GCC 10.3 is having trouble with the double_wrapper. I tried extending your #if defined(_clang_) with || defined(__GNUC__) but that didn't solve it. That's the main version of GCC I use as a baseline and everything else currently works with it, so I'd like not to have to increase the lowest level of GCC compatibility unless I have to. Also, I'm trying out variations of your code to support also non-literals. More soon... |
Sorry, something went wrong.
|
OK, I think I have it... thanks for prodding me about inspecting to match values. I've taken inspiration from this PR and followed your basic parsing implementation (looks exactly right, thanks!) and I'll apply it in a separate commit because I reworked the basic implementation in cpp2util.h to just this: inline constexpr auto is( auto const& x, auto const& value ) -> bool
requires requires{ x == value; }
{
return x == value;
}
inline constexpr auto is( auto const& x, auto const& value ) -> bool
requires (!requires{ x == value; })
{
return false;
}
This is the direction I had in mind for the "is value" case in P2392 which has "use ==" as one of the rule cascade that covers value comparison. The above has a couple of benefits (besides being shorter):
So whereas for the "is type" case we still emit is<typeid>(__expr), for the "is value" case we emit is(__expr, value). Granted, this doesn't force literals to be processed at compile time, but if that's an issue we can optimize later... and even now the literal is visible in the generated Cpp1 source, and it's just a single one-line inlined function away from the call site, so I'm optimistic the Cpp1 compiler will pick it up after inlining. (The eventual most aggressive optimization would be to optimize a series of is integer-literal alternatives as in P2392 section 4.2, by emitting that subset of consecutive alternatives as a C switch or a table lookup. But that's for much later.) Here is my test case: main: ()->int = {
test(42);
test(3.14);
test(0);
test(-42);
test("xyzzy" as std::string);
}
test: (x:_) = {
forty_two := 42;
std::cout << inspect x -> std::string {
is 0 = "zero";
is (forty_two) = "the answer";
is int = "integer " + cpp2::to_string(x);
is std::string = x;
is _ = "(no match)";
} << "\n";
}
This (now) prints: the answer (no match) zero integer -42 xyzzy The one inelegant thing right now is the parens required for the (forty-two) case to turn it into a postfix-expression. I can clean that up later, this should be enough to unblock value matching. Thanks for prompting this! I harvested your basic parser implementation and it was fine, I just changed the names a little, most of the change was the above generalization in cpp2util.h. |
Sorry, something went wrong.
|
Excellent! I like the simplicity of this solution. I was afraid that my solution was too complicated. |
Sorry, something went wrong.
|
That approach will probably simplify also use of the functions/unnamed functions in that context: #90 |
Sorry, something went wrong.
|
Now that I've done the support requested in #90: Yes it did simplify it, but only after a lot of fiddling with if constexpr and requires { ... }, and getting their test order right, and remembering to bool { ... } in all the right places. :) Checking in now... |
Sorry, something went wrong.
Also cleaned up _alternative_ to use _type-id_ rather than _id-expression_.
| Back | FazBrowse Home | New Git URL |
The current implementation of alternatives for inspect handles only types. It makes it impossible to replace the cpp1 switch with it. This change brings support for literals in alternatives which makes it possible to use as in given example:
std::cout << inspect v -> std::string { is lexeme::hash = "lexeme hash enum"; is lexeme2::hash = "lexeme2 hash enum"; is "hash" = "'hash' string"; is 42 = "42 int"; is 1.23 = "1.23 double"; is 'a' = "'a' character"; is _ = "unmatched value"; } << std::endl;The implementation of specializations of is() functions is complicated by the fact that the support for Non-Type Template Parameters (NTTP) is not fully (uniformly) implemented in GCC, clang, and MSVC. I have made a lot of tests to find a solution with workarounds that will not require preprocessor ifs for the specific compiler but one issue in clang makes me use it (probably a bug in clang). A working prototype of the solution is available here: https://godbolt.org/z/j1fqWKa9G (if you have any idea how to improve the implementation please let me know).
One of the supported NTTPs is double but there is an issue in clang and MSVC with it which was solved by introducing an intermediate type double_wrapper that makes it work for clang and MSVC. Unfortunately, it additionally needs a special version of is() function that makes the magic work for clang.
During my experiments, I have been studying https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2392r0.pdf to understand the feature.
This PR makes #74 obsolete - enums are also covered by this implementation. Closes #73