Skip to content

Commit 4ce56a8

Browse files
committed
Add implicit return; at end of functions with a return values list, closes #70
1 parent 18f2eb5 commit 4ce56a8

File tree

5 files changed

+60
-7
lines changed

5 files changed

+60
-7
lines changed

regression-tests/pure2-look-up-parameter-across-unnamed-function.cpp2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
f: () -> (ri : int = 0) = {
33
pred := :(e:_) -> bool = { return e == 1; };
44
ri = 42;
5-
return;
5+
// "return;" is implicit"
66
}
77

88
g: () -> (ri : int) = {

regression-tests/test-results/pure2-look-up-parameter-across-unnamed-function.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct g__ret {
2727
#line 3 "pure2-look-up-parameter-across-unnamed-function.cpp2"
2828
auto pred { [](auto const& e) -> bool{return e == 1; } };
2929
ri = 42;
30-
return { std::move(ri) };
30+
return { std::move(ri) }; // "return;" is implicit"
3131
}
3232

3333
[[nodiscard]] auto g() -> g__ret{

source/cppfront.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ class cppfront
727727
try
728728
{
729729
for (auto const& [line, entry] : tokens.get_map()) {
730-
if (!parser.parse(entry)) {
730+
if (!parser.parse(entry, tokens.get_generated())) {
731731
errors.emplace_back(
732732
source_position(line, 0),
733733
"parse failed for section starting here"

source/lex.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "load.h"
2222
#include <map>
2323
#include <climits>
24+
#include <deque>
2425

2526

2627
namespace cpp2 {
@@ -204,6 +205,18 @@ class token
204205
{
205206
}
206207

208+
token(
209+
char const* sz,
210+
source_position pos,
211+
lexeme type
212+
)
213+
: start {sz}
214+
, count {as<int16_t>(std::strlen(sz))}
215+
, pos {pos }
216+
, lex_type{type }
217+
{
218+
}
219+
207220
operator std::string_view() const
208221
{
209222
assert (start);
@@ -867,17 +880,20 @@ class tokens
867880
{
868881
std::vector<error>& errors;
869882

870-
// All non-comment tokens go here, which will be parsed in the parser
883+
// All non-comment source tokens go here, which will be parsed in the parser
871884
std::map<lineno_t, std::vector<token>> grammar_map;
872885

873-
// All comment tokens go here, which are applied in the lexer
886+
// All comment source tokens go here, which are applied in the lexer
874887
//
875888
// We could put all the tokens in the same map, but that would mean the
876889
// parsing logic would have to remember to skip comments everywhere...
877890
// simpler to keep comments separate, at the smaller cost of traversing
878891
// a second token stream when lowering to Cpp1 to re-interleave comments
879892
std::vector<comment> comments;
880893

894+
// All generated tokens go here
895+
std::deque<token> generated_tokens;
896+
881897
public:
882898
//-----------------------------------------------------------------------
883899
// Constructor
@@ -957,6 +973,15 @@ class tokens
957973
}
958974

959975

976+
//-----------------------------------------------------------------------
977+
// get_generated: Access the generated tokens
978+
//
979+
auto get_generated() -> auto&
980+
{
981+
return generated_tokens;
982+
}
983+
984+
960985
//-----------------------------------------------------------------------
961986
// debug_print
962987
//

source/parse.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,8 @@ class parser
12501250
};
12511251

12521252
// Used only for the duration of each parse() call
1253-
std::vector<token> const* tokens_ = nullptr;
1253+
std::vector<token> const* tokens_ = nullptr;
1254+
std::deque<token> * generated_tokens_ = nullptr;
12541255
int pos = 0;
12551256

12561257
public:
@@ -1277,12 +1278,14 @@ class parser
12771278
// sections in a TU to build the whole TU's parse tree
12781279
//
12791280
auto parse(
1280-
std::vector<token> const& tokens
1281+
std::vector<token> const& tokens,
1282+
std::deque<token>& generated_tokens
12811283
)
12821284
-> bool
12831285
{
12841286
// Generate parse tree for this section as if a standalone TU
12851287
tokens_ = &tokens;
1288+
generated_tokens_ = &generated_tokens;
12861289
pos = 0;
12871290
auto tu = translation_unit();
12881291

@@ -3042,6 +3045,31 @@ class parser
30423045
}
30433046
}
30443047

3048+
// If this is a function with a list of multiple/named return values
3049+
if (auto func = std::get_if<declaration_node::function>(&n->type);
3050+
func && (*func)->returns.index() == function_type_node::list)
3051+
{
3052+
assert (n->initializer && n->initializer->statement.index() == statement_node::compound);
3053+
auto& body = std::get<statement_node::compound>(n->initializer->statement);
3054+
3055+
// If the function body's end doesn't already have "return" as the last statement
3056+
// then generate "return;" as the last statement
3057+
if (body->statements.empty() || body->statements.back()->statement.index() != statement_node::return_)
3058+
{
3059+
auto pos = body->statements.back()->position();
3060+
++pos.lineno;
3061+
generated_tokens_->emplace_back( "return", pos, lexeme::Keyword);
3062+
3063+
auto ret = std::make_unique<return_statement_node>();
3064+
ret->identifier = &generated_tokens_->back();
3065+
3066+
auto stmt = std::make_unique<statement_node>();
3067+
stmt->statement = std::move(ret);
3068+
3069+
body->statements.push_back(std::move(stmt));
3070+
}
3071+
}
3072+
30453073
n->decl_end = peek(-1)->position();
30463074
return n;
30473075
}

0 commit comments

Comments
 (0)