Skip to content

Commit 586ff20

Browse files
committed
Add basic AST pretty-print visualizer and @print metafunction
Also make `unique`, `shared`, and `nonesuch` be `inline`, closes #685. And finally fix `token::to_string`'s default to never decorate, all callers passed `true` anyway except the one use in `parse_tree_printer::start(token)`.
1 parent 99d66f0 commit 586ff20

23 files changed

+1536
-250
lines changed

include/cpp2util.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,14 +517,14 @@ struct {
517517
[[nodiscard]] auto cpp2_new(auto&& ...args) const -> std::unique_ptr<T> {
518518
return std::make_unique<T>(CPP2_FORWARD(args)...);
519519
}
520-
} unique;
520+
} inline unique;
521521

522522
[[maybe_unused]] struct {
523523
template<typename T>
524524
[[nodiscard]] auto cpp2_new(auto&& ...args) const -> std::shared_ptr<T> {
525525
return std::make_shared<T>(CPP2_FORWARD(args)...);
526526
}
527-
} shared;
527+
} inline shared;
528528

529529
template<typename T>
530530
[[nodiscard]] auto cpp2_new(auto&& ...args) -> std::unique_ptr<T> {
@@ -1009,7 +1009,7 @@ inline constexpr auto is( auto const& x, auto const& value ) -> bool
10091009
struct nonesuch_ {
10101010
auto operator==(auto const&) -> bool { return false; }
10111011
};
1012-
constexpr static nonesuch_ nonesuch;
1012+
constexpr inline nonesuch_ nonesuch;
10131013

10141014
// The 'as' cast functions are <To, From> so use that order here
10151015
// If it's confusing, we can switch this to <From, To>

regression-tests/pure2-intro-example-hello-2022.cpp2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ main: () -> int = {
55

66
for view do (inout str) {
77
len := decorate(str);
8-
println(str, len);
8+
print_it(str, len);
99
}
1010
}
1111

@@ -14,7 +14,7 @@ decorate: (inout thing: _ ) -> int = {
1414
return thing.ssize();
1515
}
1616

17-
println: (x: _, len: _) =
17+
print_it: (x: _, len: _) =
1818
std::cout
1919
<< ">> " << x
2020
<< " - length "

regression-tests/pure2-print.cpp2

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
// Exercise the pretty-print visualizer for the various grammar elements
3+
4+
outer: @print type = {
5+
6+
mytype: final type =
7+
{
8+
protected f: () -> int = 42;
9+
10+
g: (virtual this, i:int) -> int = {
11+
s := "string literal";
12+
ret: int = i;
13+
p: const * const int = ret&;
14+
if p* < 0 {
15+
ret = -p*;
16+
}
17+
ret += strlen(s) - 10 + s.strlen() * (16 / (3 & 2)) % 3;
18+
19+
m: std::map<const int,std::string> = ();
20+
m[0] = "har" as std::string;
21+
ret -= h("x", m).length();
22+
_ = m;
23+
24+
return ret;
25+
}
26+
27+
private h: (s: std::string, inout m: std::map<const int,std::string> ) -> std::string
28+
[[pre: m.empty() == false || false]]
29+
[[pre Bounds: 0 < m.ssize() < 100 && true != false]]
30+
= {
31+
a := :()={};
32+
b := :()={};
33+
c := :()={};
34+
35+
while s.empty() next a() { break; }
36+
37+
do { } while s.empty() next b();
38+
39+
label: for m next c() do (_) { continue label; }
40+
41+
if !s.empty() is (true) { a(); }
42+
else if !m.empty() { b(); }
43+
else { c(); }
44+
45+
[[assert: true]]
46+
47+
return :() -> std::string = (s + m[0])$; ();
48+
}
49+
50+
values: <T> (this, t: T) throws -> (offset: int, name: std::string) = {
51+
offset = 53;
52+
name = "plugh";
53+
}
54+
55+
operator=: (out this) = { }
56+
57+
operator=: (out this, that) = { }
58+
59+
operator=: (implicit out this, _: int) = { }
60+
61+
variadic: (x...: int) = { }
62+
}
63+
64+
test: () = {
65+
var: ::outer::mytype = ();
66+
std::cout << var.g(42) << "\n";
67+
68+
std::cout << inspect var.g(42) -> std::string {
69+
is 43 = "forty-and-three";
70+
is _ = "default case";
71+
} << "\n";
72+
73+
}
74+
75+
x: <Ts...: type> type = {
76+
tup: std::tuple<Ts...> = ();
77+
}
78+
79+
print: <Args...: type> (inout out: std::ostream, args...: Args) requires sizeof...(Args) >= 0 = {
80+
(out << ... << args);
81+
}
82+
83+
all: <Args...: type> (args...: Args) -> bool =
84+
(... && args);
85+
86+
}
87+
88+
main: () = {
89+
outer::test();
90+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
43
2+
forty-and-three
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pure2-print.cpp2:50:80: warning: unused parameter 't' [-Wunused-parameter]
2+
template<typename T> [[nodiscard]] auto outer::mytype::values(T const& t) const& -> values__ret{
3+
^
4+
pure2-print.cpp2:61:53: warning: unused parameter 'x' [-Wunused-parameter]
5+
auto outer::mytype::variadic(auto const& ...x) -> void{}
6+
^
7+
2 warnings generated.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
In file included from pure2-print.cpp:7:
2+
../../../include/cpp2util.h:10005:33: error: expected initializer before ‘static_assert’
3+
pure2-print.cpp2:80:1: note: in expansion of macro ‘CPP2_REQUIRES_’
4+
pure2-print.cpp2:79:37: error: no declaration matches ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
5+
pure2-print.cpp2:79:37: note: no functions named ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
6+
pure2-print.cpp2:4:7: note: ‘class outer’ defined here
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
43
2+
forty-and-three

regression-tests/test-results/gcc-13/pure2-print.cpp.output

Whitespace-only changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32538 for x86
1+
Microsoft (R) C/C++ Optimizing Compiler Version 19.37.32824 for x86
22
Copyright (C) Microsoft Corporation. All rights reserved.
33

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
43
2+
forty-and-three
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-print.cpp

regression-tests/test-results/pure2-intro-example-hello-2022.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919

2020
#line 17 "pure2-intro-example-hello-2022.cpp2"
21-
auto println(auto const& x, auto const& len) -> void;
21+
auto print_it(auto const& x, auto const& len) -> void;
2222

2323

2424
//=== Cpp2 function definitions =================================================
@@ -30,7 +30,7 @@ auto println(auto const& x, auto const& len) -> void;
3030

3131
for ( auto& str : view ) {
3232
auto len {decorate(str)};
33-
println(str, len);
33+
print_it(str, len);
3434
}
3535
}
3636

@@ -39,7 +39,7 @@ auto println(auto const& x, auto const& len) -> void;
3939
return CPP2_UFCS_0(ssize, thing);
4040
}
4141

42-
auto println(auto const& x, auto const& len) -> void {
42+
auto print_it(auto const& x, auto const& len) -> void {
4343
std::cout
4444
<< ">> " << x
4545
<< " - length "
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
10+
#line 4 "pure2-print.cpp2"
11+
class outer;
12+
13+
14+
//=== Cpp2 type definitions and function declarations ===========================
15+
16+
17+
// Exercise the pretty-print visualizer for the various grammar elements
18+
19+
#line 4 "pure2-print.cpp2"
20+
class outer {
21+
22+
public: class mytype final
23+
{
24+
protected: [[nodiscard]] static auto f() -> int;
25+
26+
public: [[nodiscard]] virtual auto g(cpp2::in<int> i) const& -> int;
27+
28+
29+
#line 27 "pure2-print.cpp2"
30+
private: [[nodiscard]] static auto h(cpp2::in<std::string> s, std::map<int const,std::string>& m) -> std::string;
31+
struct values__ret { int offset; std::string name; };
32+
33+
34+
35+
#line 50 "pure2-print.cpp2"
36+
public: template<typename T> [[nodiscard]] auto values(T const& t) const& -> values__ret;
37+
38+
39+
#line 55 "pure2-print.cpp2"
40+
public: explicit mytype();
41+
42+
public: mytype([[maybe_unused]] mytype const& that);
43+
44+
public: mytype([[maybe_unused]] cpp2::in<int> param2);
45+
46+
public: static auto variadic(auto const& ...x) -> void;
47+
};
48+
49+
public: static auto test() -> void;
50+
51+
52+
#line 75 "pure2-print.cpp2"
53+
public: template<typename ...Ts> class x {
54+
private: std::tuple<Ts...> tup {};
55+
public: x() = default;
56+
public: x(x const&) = delete; /* No 'that' constructor, suppress copy */
57+
public: auto operator=(x const&) -> void = delete;
58+
59+
#line 77 "pure2-print.cpp2"
60+
};
61+
62+
public: template<typename ...Args> static auto print(std::ostream& out, Args const& ...args) -> void
63+
CPP2_REQUIRES_ (cpp2::cmp_greater_eq(sizeof(Args)...,0))
64+
#line 79 "pure2-print.cpp2"
65+
;
66+
67+
68+
#line 83 "pure2-print.cpp2"
69+
public: template<typename ...Args> [[nodiscard]] static auto all(Args const& ...args) -> bool;
70+
71+
public: outer() = default;
72+
public: outer(outer const&) = delete; /* No 'that' constructor, suppress copy */
73+
public: auto operator=(outer const&) -> void = delete;
74+
75+
76+
#line 86 "pure2-print.cpp2"
77+
};
78+
79+
auto main() -> int;
80+
81+
82+
//=== Cpp2 function definitions =================================================
83+
84+
85+
#line 8 "pure2-print.cpp2"
86+
[[nodiscard]] auto outer::mytype::f() -> int { return 42; }
87+
88+
[[nodiscard]] auto outer::mytype::g(cpp2::in<int> i) const& -> int{
89+
auto s {"string literal"};
90+
int ret {i};
91+
int const* const p {&ret};
92+
if (cpp2::cmp_less(*cpp2::assert_not_null(p),0)) {
93+
ret = -*cpp2::assert_not_null(std::move(p));
94+
}
95+
ret += strlen(s) - 10 + CPP2_UFCS_0(strlen, std::move(s)) * (16 / (3 & 2)) % 3;
96+
97+
std::map<int const,std::string> m {};
98+
cpp2::assert_in_bounds(m, 0) = cpp2::as_<std::string>("har");
99+
ret -= CPP2_UFCS_0(length, h("x", m));
100+
static_cast<void>(std::move(m));
101+
102+
return ret;
103+
}
104+
105+
[[nodiscard]] auto outer::mytype::h(cpp2::in<std::string> s, std::map<int const,std::string>& m) -> std::string
106+
107+
#line 30 "pure2-print.cpp2"
108+
{
109+
cpp2::Default.expects(CPP2_UFCS_0(empty, m) == false || false, "");
110+
cpp2::Bounds.expects([_0 = 0, _1 = CPP2_UFCS_0(ssize, m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false, "");
111+
#line 31 "pure2-print.cpp2"
112+
auto a {[]() -> void{}};
113+
auto b {[]() -> void{}};
114+
auto c {[]() -> void{}};
115+
116+
for( ; CPP2_UFCS_0(empty, s); a() ) {break; }
117+
118+
do {} while ( CPP2_UFCS_0(empty, s) && [&]{ b() ; return true; }() );
119+
120+
for ( [[maybe_unused]] auto const& param1 : m ) {
121+
#line 39 "pure2-print.cpp2"
122+
{ do {goto CONTINUE_39_13; } while (false); c(); } CPP2_CONTINUE_BREAK(39_13) }
123+
124+
#line 41 "pure2-print.cpp2"
125+
if (cpp2::is(!(CPP2_UFCS_0(empty, s)), (true))) {std::move(a)(); }
126+
else {if (!(CPP2_UFCS_0(empty, m))) {std::move(b)(); }
127+
else {std::move(c)(); }}
128+
129+
cpp2::Default.expects(true, "");
130+
131+
return [_0 = (s + cpp2::assert_in_bounds(m, 0))]() -> std::string { return _0; }();
132+
}
133+
134+
template<typename T> [[nodiscard]] auto outer::mytype::values(T const& t) const& -> values__ret{
135+
cpp2::deferred_init<int> offset;
136+
cpp2::deferred_init<std::string> name;
137+
#line 51 "pure2-print.cpp2"
138+
offset.construct(53);
139+
name.construct("plugh");
140+
return { std::move(offset.value()), std::move(name.value()) }; }
141+
142+
outer::mytype::mytype(){}
143+
144+
outer::mytype::mytype([[maybe_unused]] mytype const& that){}
145+
146+
outer::mytype::mytype([[maybe_unused]] cpp2::in<int> param2){}
147+
148+
auto outer::mytype::variadic(auto const& ...x) -> void{}
149+
150+
#line 64 "pure2-print.cpp2"
151+
auto outer::test() -> void{
152+
::outer::mytype var {};
153+
std::cout << CPP2_UFCS(g, var, 42) << "\n";
154+
155+
std::cout << [&] () -> std::string { auto&& __expr = CPP2_UFCS(g, std::move(var), 42);
156+
if (cpp2::is(__expr, 43)) { if constexpr( requires{"forty-and-three";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("forty-and-three")),std::string> ) return "forty-and-three"; else return std::string{}; else return std::string{}; }
157+
else return "default case"; }
158+
() << "\n";
159+
160+
}
161+
162+
#line 79 "pure2-print.cpp2"
163+
template<typename ...Args> auto outer::print(std::ostream& out, Args const& ...args) -> void
164+
requires (cpp2::cmp_greater_eq(sizeof(Args)...,0))
165+
#line 79 "pure2-print.cpp2"
166+
{
167+
(out << ... << args);
168+
}
169+
170+
template<typename ...Args> [[nodiscard]] auto outer::all(Args const& ...args) -> bool {
171+
return (... && args); }
172+
173+
#line 88 "pure2-print.cpp2"
174+
auto main() -> int{
175+
outer::test();
176+
}
177+

0 commit comments

Comments
 (0)