Skip to content

Commit

Permalink
Allow else if, closes #366
Browse files Browse the repository at this point in the history
Also, reject `=` assignment expressions in `if` conditions. They're already disallowed in loop conditions, and it's an oversight that they were not already disallowed in `if` conditions... the `if` condition is supposed to take *logical-or-expression* (the conditional expression production) like the loop conditions do.
  • Loading branch information
hsutter committed Apr 22, 2023
1 parent 72004cd commit 65bd0a5
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 19 deletions.
25 changes: 25 additions & 0 deletions regression-tests/pure2-initialization-safety-with-else-if.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
main: (args) = {
p : *int;

a := 1;
b := 2;
c := 3;
d := 4;

if args.size() == 3 {
p = a&;
} else if true {
if args.size() == 2 {
p = c&;
} else if b > 0 {
p = a&;
}
else {
p = d&;
}
} else {
p = c&;
}

std::cout << p* << std::endl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pure2-initialization-safety-with-else-if.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

#define CPP2_USE_MODULES Yes

//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"



//=== Cpp2 type definitions and function declarations ===========================

#line 1 "pure2-initialization-safety-with-else-if.cpp2"
auto main(int const argc_, char const* const* const argv_) -> int;


//=== Cpp2 function definitions =================================================

#line 1 "pure2-initialization-safety-with-else-if.cpp2"
auto main(int const argc_, char const* const* const argv_) -> int{
auto args = cpp2::make_args(argc_, argv_);
#line 2 "pure2-initialization-safety-with-else-if.cpp2"
cpp2::deferred_init<int*> p;

auto a {1};
auto b {2};
auto c {3};
auto d {4};

if (CPP2_UFCS_0(size, args)==3) {
p.construct(&a);
}else {if (true) {
if (CPP2_UFCS_0(size, args)==2) {
p.construct(&c);
}else {if (cpp2::cmp_greater(std::move(b),0)) {
p.construct(&a);
}
else {
p.construct(&d);
}}
}else {
p.construct(&c);
}}

std::cout << *cpp2::assert_not_null(std::move(p.value())) << std::endl;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pure2-initialization-safety-with-else-if.cpp2... ok (all Cpp2, passes safety checks)

64 changes: 45 additions & 19 deletions source/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -1160,13 +1160,13 @@ struct compound_statement_node

struct selection_statement_node
{
bool is_constexpr = false;
token const* identifier = {};
source_position else_pos;
std::unique_ptr<expression_node> expression;
std::unique_ptr<compound_statement_node> true_branch;
std::unique_ptr<compound_statement_node> false_branch;
bool has_source_false_branch = false;
bool is_constexpr = false;
token const* identifier = {};
source_position else_pos;
std::unique_ptr<logical_or_expression_node> expression;
std::unique_ptr<compound_statement_node> true_branch;
std::unique_ptr<compound_statement_node> false_branch;
bool has_source_false_branch = false;

auto position() const
-> source_position
Expand Down Expand Up @@ -4596,8 +4596,8 @@ class parser


//G selection-statement:
//G 'if' 'constexpr'? expression compound-statement
//G 'if' 'constexpr'? expression compound-statement 'else' compound-statement
//G 'if' 'constexpr'? logical-or-expression compound-statement
//G 'if' 'constexpr'? logical-or-expression compound-statement 'else' compound-statement
//G
auto selection_statement()
-> std::unique_ptr<selection_statement_node>
Expand All @@ -4622,7 +4622,7 @@ class parser
next();
}

if (auto e = expression()) {
if (auto e = logical_or_expression()) {
n->expression = std::move(e);
}
else {
Expand Down Expand Up @@ -4657,12 +4657,16 @@ class parser
n->else_pos = curr().position();
next();

if (curr().type() != lexeme::LeftBrace) {
if (
curr().type() != lexeme::LeftBrace
&& curr() != "if"
)
{
error("an else branch body must be enclosed with { }");
return {};
}

if (auto s = compound_statement()) {
if (auto s = compound_statement( source_position{}, true )) {
n->false_branch = std::move(s);
n->has_source_false_branch = true;
}
Expand Down Expand Up @@ -5181,16 +5185,25 @@ class parser
//G statement-seq statement
//G
auto compound_statement(
source_position equal_sign = source_position{}
source_position equal_sign = source_position{},
bool allow_single_unbraced_statement = false
)
-> std::unique_ptr<compound_statement_node>
{
if (curr().type() != lexeme::LeftBrace) {
bool is_braced = curr().type() == lexeme::LeftBrace;
if (
!is_braced
&& !allow_single_unbraced_statement
)
{
return {};
}

auto n = std::make_unique<compound_statement_node>();
if (peek(1)) {
if (!is_braced) {
n->body_indent = curr().position().colno-1;
}
else if (peek(1)) {
n->body_indent = peek(1)->position().colno-1;
}

Expand All @@ -5207,9 +5220,19 @@ class parser
else {
n->open_brace = curr().position();
}
next();

while (curr().type() != lexeme::RightBrace) {
if (is_braced) {
next();
}

while (
curr().type() != lexeme::RightBrace
&& (
is_braced
|| std::ssize(n->statements) < 1
)
)
{
if (
(
is_literal(curr().type())
Expand All @@ -5229,8 +5252,11 @@ class parser
n->statements.push_back( std::move(s) );
}

n->close_brace = curr().position();
next();
if (is_braced) {
assert(curr().type() == lexeme::RightBrace);
n->close_brace = curr().position();
next();
}
return n;
}

Expand Down

0 comments on commit 65bd0a5

Please sign in to comment.