Skip to content

Commit ab29f19

Browse files
committed
Add support for return expression lists, closes #325
1 parent 81e08cf commit ab29f19

File tree

2 files changed

+140
-3
lines changed

2 files changed

+140
-3
lines changed

source/cppfront.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,7 +2201,19 @@ class cppfront
22012201
}
22022202
}
22032203

2204-
emit(*n.expression);
2204+
// If this expression is just a single expression-list, we can
2205+
// take over direct control of emitting it without needing to
2206+
// go through the whole grammar, and surround it with braces
2207+
if (n.expression->is_expression_list()) {
2208+
printer.print_cpp2( "{ ", n.position() );
2209+
emit(*n.expression->get_expression_list(), false);
2210+
printer.print_cpp2( " }", n.position() );
2211+
}
2212+
// Otherwise, just emit the general expression as usual
2213+
else {
2214+
emit(*n.expression);
2215+
}
2216+
22052217
if (
22062218
function_returns.empty()
22072219
|| function_returns.back().param_list != &single_anon
@@ -3446,12 +3458,16 @@ class cppfront
34463458

34473459
//-----------------------------------------------------------------------
34483460
//
3449-
auto emit(expression_list_node const& n)
3461+
auto emit(
3462+
expression_list_node const& n,
3463+
bool parens_ok = true
3464+
)
34503465
-> void
34513466
{
34523467
auto add_parens =
34533468
should_add_expression_list_parens()
34543469
&& !n.inside_initializer
3470+
&& parens_ok
34553471
;
34563472
if (add_parens) {
34573473
printer.print_cpp2( *n.open_paren, n.position());
@@ -3520,18 +3536,35 @@ class cppfront
35203536
-> void
35213537
{
35223538
assert(n.expr);
3539+
auto generating_return = false;
35233540

35243541
if (function_body_start != source_position{}) {
35253542
emit_prolog_mem_inits(function_prolog, n.position().colno);
35263543
printer.print_cpp2(" { ", function_body_start);
35273544
emit_prolog_statements(function_prolog, n.position().colno);
35283545
if (!function_void_ret) {
35293546
printer.print_cpp2("return ", n.position());
3547+
generating_return = true;
35303548
}
35313549
}
35323550

35333551
if (!emitted) {
3534-
emit(*n.expr);
3552+
// When generating 'return' of a single expression-list, we can
3553+
// take over direct control of emitting it without needing to
3554+
// go through the whole grammar, and surround it with braces
3555+
if (
3556+
generating_return
3557+
&& n.expr->is_expression_list()
3558+
)
3559+
{
3560+
printer.print_cpp2( "{ ", n.position() );
3561+
emit(*n.expr->get_expression_list(), false);
3562+
printer.print_cpp2( " }", n.position() );
3563+
}
3564+
// Otherwise, just emit the general expression as usual
3565+
else {
3566+
emit(*n.expr);
3567+
}
35353568
if (can_have_semicolon) {
35363569
printer.print_cpp2(";", n.position());
35373570
}

source/parse.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ struct primary_expression_node
144144
std::unique_ptr<literal_node>
145145
> expr;
146146

147+
auto is_expression_list() const
148+
-> bool;
149+
150+
auto get_expression_list() const
151+
-> expression_list_node const*;
152+
147153
auto template_args_count() -> int;
148154
auto get_token() const -> token const*;
149155
auto position() const -> source_position;
@@ -188,6 +194,12 @@ struct prefix_expression_node
188194
std::vector<token const*> ops;
189195
std::unique_ptr<postfix_expression_node> expr;
190196

197+
auto is_expression_list() const
198+
-> bool;
199+
200+
auto get_expression_list() const
201+
-> expression_list_node const*;
202+
191203
auto get_postfix_expression_node() const
192204
-> postfix_expression_node *
193205
{
@@ -217,6 +229,23 @@ struct binary_expression_node
217229
};
218230
std::vector<term> terms;
219231

232+
// API
233+
//
234+
auto is_expression_list() const
235+
-> bool
236+
{
237+
return terms.empty() && expr->is_expression_list();
238+
}
239+
240+
auto get_expression_list() const
241+
-> expression_list_node const*
242+
{
243+
if (is_expression_list()) {
244+
return expr->get_expression_list();
245+
}
246+
return {};
247+
}
248+
220249
// Get left-hand postfix-expression
221250
auto get_postfix_expression_node() const
222251
-> postfix_expression_node *
@@ -325,6 +354,21 @@ struct expression_node
325354

326355
// API
327356
//
357+
auto is_expression_list() const
358+
-> bool
359+
{
360+
return expr->is_expression_list();
361+
}
362+
363+
auto get_expression_list() const
364+
-> expression_list_node const*
365+
{
366+
if (is_expression_list()) {
367+
return expr->get_expression_list();
368+
}
369+
return {};
370+
}
371+
328372
auto get_lhs_rhs_if_simple_assignment() const
329373
-> assignment_expression_lhs_rhs;
330374

@@ -408,6 +452,21 @@ struct expression_list_node
408452
}
409453
};
410454

455+
auto primary_expression_node::is_expression_list() const
456+
-> bool
457+
{
458+
return expr.index() == expression_list;
459+
}
460+
461+
auto primary_expression_node::get_expression_list() const
462+
-> expression_list_node const*
463+
{
464+
if (is_expression_list()) {
465+
return std::get<expression_list>(expr).get();
466+
}
467+
return {};
468+
}
469+
411470

412471
struct expression_statement_node
413472
{
@@ -483,6 +542,21 @@ struct postfix_expression_node
483542

484543
// API
485544
//
545+
auto is_expression_list() const
546+
-> bool
547+
{
548+
return ops.empty() && expr->is_expression_list();
549+
}
550+
551+
auto get_expression_list() const
552+
-> expression_list_node const*
553+
{
554+
if (is_expression_list()) {
555+
return expr->get_expression_list();
556+
}
557+
return {};
558+
}
559+
486560
auto get_first_token_ignoring_this() const
487561
-> token const*;
488562

@@ -506,6 +580,21 @@ struct postfix_expression_node
506580
auto visit(auto& v, int depth) -> void;
507581
};
508582

583+
auto prefix_expression_node::is_expression_list() const
584+
-> bool
585+
{
586+
return ops.empty() && expr->is_expression_list();
587+
}
588+
589+
auto prefix_expression_node::get_expression_list() const
590+
-> expression_list_node const*
591+
{
592+
if (is_expression_list()) {
593+
return expr->get_expression_list();
594+
}
595+
return {};
596+
}
597+
509598
auto prefix_expression_node::is_result_a_temporary_variable() const -> bool {
510599
if (ops.empty()) {
511600
return expr->is_result_a_temporary_variable();
@@ -833,6 +922,21 @@ struct is_as_expression_node
833922
};
834923
std::vector<term> ops;
835924

925+
auto is_expression_list() const
926+
-> bool
927+
{
928+
return ops.empty() && expr->is_expression_list();
929+
}
930+
931+
auto get_expression_list() const
932+
-> expression_list_node const*
933+
{
934+
if (is_expression_list()) {
935+
return expr->get_expression_list();
936+
}
937+
return {};
938+
}
939+
836940
auto get_postfix_expression_node() const
837941
-> postfix_expression_node *
838942
{

0 commit comments

Comments
 (0)