Skip to content

Commit c77de70

Browse files
committed
Add support for inspecting values (not just types), closes #79
Also cleaned up _alternative_ to use _type-id_ rather than _id-expression_.
1 parent a102dfd commit c77de70

12 files changed

+126
-11
lines changed

include/cpp2util.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,23 @@ auto is( X const& x ) -> bool {
616616
}
617617

618618

619+
//-------------------------------------------------------------------------------------------------------------
620+
// Built-in is (values)
621+
//
622+
623+
inline constexpr auto is( auto const& x, auto const& value ) -> bool
624+
requires requires{ x == value; }
625+
{
626+
return x == value;
627+
}
628+
629+
inline constexpr auto is( auto const& x, auto const& value ) -> bool
630+
requires (!requires{ x == value; })
631+
{
632+
return false;
633+
}
634+
635+
619636
//-------------------------------------------------------------------------------------------------------------
620637
// Built-in as (partial)
621638
//
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
main: ()->int = {
2+
test(42);
3+
test(3.14);
4+
test(0);
5+
test(-42);
6+
test("xyzzy" as std::string);
7+
}
8+
9+
test: (x:_) = {
10+
forty_two := 42;
11+
std::cout << inspect x -> std::string {
12+
is 0 = "zero";
13+
is (forty_two) = "the answer";
14+
is int = "integer " + cpp2::to_string(x);
15+
is std::string = x;
16+
is _ = "(no match)";
17+
} << "\n";
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
the answer
2+
(no match)
3+
zero
4+
integer -42
5+
xyzzy

regression-tests/test-results/clang-12/pure2-inspect-values.cpp.output

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
the answer
2+
(no match)
3+
zero
4+
integer -42
5+
xyzzy

regression-tests/test-results/gcc-10/pure2-inspect-values.cpp.output

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
the answer
2+
(no match)
3+
zero
4+
integer -42
5+
xyzzy
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-inspect-values.cpp
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// ----- Cpp2 support -----
2+
#define CPP2_USE_MODULES Yes
3+
#include "cpp2util.h"
4+
5+
6+
#line 1 "pure2-inspect-values.cpp2"
7+
[[nodiscard]] auto main() -> int;
8+
#line 9 "pure2-inspect-values.cpp2"
9+
auto test(auto const& x) -> void;
10+
11+
//=== Cpp2 definitions ==========================================================
12+
13+
#line 1 "pure2-inspect-values.cpp2"
14+
[[nodiscard]] auto main() -> int{
15+
test(42);
16+
test(3.14);
17+
test(0);
18+
test(-42);
19+
test(cpp2::as< std::string>("xyzzy"));
20+
}
21+
22+
auto test(auto const& x) -> void{
23+
auto forty_two { 42 };
24+
std::cout << [&] () -> std::string { auto&& __expr = x;
25+
if (cpp2::is(__expr, 0)) { if constexpr( requires{"zero";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("zero")),std::string> ) return "zero"; else return std::string{}; else return std::string{}; }
26+
else if (cpp2::is(__expr, (std::move(forty_two)))) { if constexpr( requires{"the answer";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("the answer")),std::string> ) return "the answer"; else return std::string{}; else return std::string{}; }
27+
else if (cpp2::is<int>(__expr)) { if constexpr( requires{"integer " + cpp2::to_string(x);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("integer " + cpp2::to_string(x))),std::string> ) return "integer " + cpp2::to_string(x); else return std::string{}; else return std::string{}; }
28+
else if (cpp2::is<std::string>(__expr)) { if constexpr( requires{x;} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((x)),std::string> ) return x; else return std::string{}; else return std::string{}; }
29+
else return "(no match)"; }
30+
()
31+
<< "\n";}
32+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-inspect-values.cpp2... ok (all Cpp2, passes safety checks)
2+

source/cppfront.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,8 +1294,14 @@ class cppfront
12941294

12951295
auto id = std::string{};
12961296
printer.emit_to_string(&id);
1297-
assert(alt->id_expression);
1298-
emit(*alt->id_expression);
1297+
1298+
if (alt->type_id) {
1299+
emit(*alt->type_id);
1300+
}
1301+
else {
1302+
assert(alt->value);
1303+
emit(*alt->value);
1304+
}
12991305
printer.emit_to_string();
13001306

13011307
assert (*alt->is_as_keyword == "is" || *alt->is_as_keyword == "as");
@@ -1330,7 +1336,15 @@ class cppfront
13301336
}
13311337
}
13321338
else {
1333-
printer.print_cpp2("if " + constexpr_qualifier + "(cpp2::is<" + id + ">(__expr)) " + return_prefix, alt->position());
1339+
printer.print_cpp2("if " + constexpr_qualifier, alt->position());
1340+
if (alt->type_id) {
1341+
printer.print_cpp2("(cpp2::is<" + id + ">(__expr)) ", alt->position());
1342+
}
1343+
else {
1344+
assert (alt->value);
1345+
printer.print_cpp2("(cpp2::is(__expr, " + id + ")) ", alt->position());
1346+
}
1347+
printer.print_cpp2(return_prefix, alt->position());
13341348
}
13351349

13361350
printer.print_cpp2(statement, alt->position());

source/parse.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,11 @@ struct alternative_node
664664
{
665665
std::unique_ptr<unqualified_id_node> name;
666666
token const* is_as_keyword;
667-
std::unique_ptr<id_expression_node> id_expression;
667+
668+
// One of these will be used
669+
std::unique_ptr<type_id_node> type_id;
670+
std::unique_ptr<postfix_expression_node> value;
671+
668672
source_position equal_sign;
669673
std::unique_ptr<statement_node> statement;
670674

@@ -776,8 +780,13 @@ auto alternative_node::visit(auto& v, int depth) -> void
776780
}
777781
assert (is_as_keyword);
778782
v.start(*is_as_keyword, depth+1);
779-
assert (id_expression);
780-
id_expression->visit(v, depth+1);
783+
if (type_id) {
784+
type_id->visit(v, depth+1);
785+
}
786+
else {
787+
assert (value);
788+
value->visit(v, depth+1);
789+
}
781790
assert (statement);
782791
statement->visit(v, depth+1);
783792
v.end(*this, depth);
@@ -1785,7 +1794,7 @@ class parser
17851794
}
17861795

17871796
//G expression-list:
1788-
//G expression
1797+
//G parameter-direction-opt expression
17891798
//G expression-list , expression
17901799
//G
17911800
auto expression_list(source_position open_paren, bool inside_initializer = false) -> std::unique_ptr<expression_list_node> {
@@ -2302,11 +2311,15 @@ class parser
23022311

23032312
//G alternative:
23042313
//G alt-name-opt is-type-constraint = statement
2314+
//G alt-name-opt is-value-constraint = statement
23052315
//G alt-name-opt as-type-cast = statement
23062316
//GTODO alt-name-opt is-expression-constraint = statement
23072317
//G
23082318
//G is-type-constraint
2309-
//G is id-expression
2319+
//G is type-id
2320+
//G
2321+
//G is-value-constraint
2322+
//G is postfix-expression
23102323
//G
23112324
//G as-type-cast
23122325
//G as id-expression
@@ -2343,11 +2356,14 @@ class parser
23432356
n->is_as_keyword = &curr();
23442357
next();
23452358

2346-
if (auto id = id_expression()) {
2347-
n->id_expression = std::move(id);
2359+
if (auto id = type_id()) {
2360+
n->type_id = std::move(id);
2361+
}
2362+
else if (auto e = postfix_expression()) {
2363+
n->value = std::move(e);
23482364
}
23492365
else {
2350-
error("expected id-expression after 'is' in inspect alternative");
2366+
error("expected type-id or value after 'is' in inspect alternative");
23512367
return {};
23522368
}
23532369

0 commit comments

Comments
 (0)