Skip to content

Commit

Permalink
fix(parse): allow (to omit) semicolon after _unnamed-declaration_
Browse files Browse the repository at this point in the history
  • Loading branch information
JohelEGP committed Oct 31, 2023
1 parent 083c8a0 commit 2af70b4
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
t: type = {
operator[]: (this, f) = { }
}

main: () -> int = {
(x := t()) { x[:() -> _ = 0]; }
(x := t()) { x[:() -> _ = 0;]; }

[[assert: !(:() = 0; is int) ]]

_ = :i32 = 0;
[[assert: true]]

return :i32 = 0;
}

x :== :i32 = 0;
y: i32 = 0;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

#define CPP2_IMPORT_STD Yes

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


#include "cpp2util.h"

class t;


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

class t {
public: auto operator[](auto const& f) const& -> void;

public: t() = default;
public: t(t const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(t const&) -> void = delete;
#line 3 "pure2-bugfix-for-unbraced-function-expression.cpp2"
};

[[nodiscard]] auto main() -> int;


#line 17 "pure2-bugfix-for-unbraced-function-expression.cpp2"
auto inline constexpr x = cpp2::i32{0};
extern cpp2::i32 y;

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


#line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2"
auto t::operator[](auto const& f) const& -> void{}

#line 5 "pure2-bugfix-for-unbraced-function-expression.cpp2"
[[nodiscard]] auto main() -> int{
{
auto const& x = t();
#line 6 "pure2-bugfix-for-unbraced-function-expression.cpp2"
{cpp2::assert_in_bounds(x, []() -> auto { return 0; }); }
}
{
auto const& x = t();
#line 7 "pure2-bugfix-for-unbraced-function-expression.cpp2"
{cpp2::assert_in_bounds(x, []() -> auto { return 0; }); }
}

#line 9 "pure2-bugfix-for-unbraced-function-expression.cpp2"
cpp2::Default.expects(!((cpp2::is<int>([]() -> void { 0; }))), "");

static_cast<void>(cpp2::i32{0});
cpp2::Default.expects(true, "");

return cpp2::i32{0};
}

#line 18 "pure2-bugfix-for-unbraced-function-expression.cpp2"
cpp2::i32 y {0};

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pure2-bugfix-for-unbraced-function-expression.cpp2... ok (all Cpp2, passes safety checks)

32 changes: 21 additions & 11 deletions source/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -5335,12 +5335,32 @@ class parser
!decl->has_name()
&& "ICE: declaration should have been unnamed"
);
auto simulate_double_semicolon = [&]() {
if (
peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is short function syntax
&& curr().type() != lexeme::LeftParen // not imediatelly called
&& curr().type() != lexeme::RightParen // not as a last argument to function
&& curr().type() != lexeme::Comma // not as first or in-the-middle, function argument
&& curr().type() != lexeme::Greater // not as the last argument to template
&& curr().type() != lexeme::RightBracket // not as the last index argument
&& curr() != "is" // not as the argument to is
&& curr() != "as" // not as the argument to as
&& curr() != "do" // not as `for`'s `next`.
) {
// this is a fix for a short function syntax that should have double semicolon used
// (check comment in expression_statement(bool semicolon_required))
// We simulate double semicolon by moving back to single semicolon.
next(-1);
}
};

if (auto obj = std::get_if<declaration_node::an_object>(&decl->type)) {
if ((*obj)->is_wildcard()) {
error("an unnamed object at expression scope currently cannot have a deduced type (the reason to create an unnamed object is typically to create a temporary of a named type)");
next();
return {};
}
simulate_double_semicolon();
}
else if (auto func = std::get_if<declaration_node::a_function>(&decl->type)) {
if ((*func)->returns.index() == function_type_node::list) {
Expand All @@ -5359,17 +5379,7 @@ class parser
next();
return {};
}
if (
peek(-1) && peek(-1)->type() != lexeme::RightBrace // it is short function syntax
&& curr().type() != lexeme::LeftParen // not imediatelly called
&& curr().type() != lexeme::RightParen // not as a last argument to function
&& curr().type() != lexeme::Comma // not as first or in-the-middle, function argument
) {
// this is a fix for a short function syntax that should have double semicolon used
// (check comment in expression_statement(bool semicolon_required))
// We simulate double semicolon by moving back to single semicolon.
next(-1);
}
simulate_double_semicolon();
}
else {
error("(temporary alpha limitation) an unnamed declaration at expression scope must be a function or an object");
Expand Down

0 comments on commit 2af70b4

Please sign in to comment.