Skip to content

Commit 1090a31

Browse files
committed
Allow unnamed objects (like functions) at expression scope, see #193 comment thread
Sample test case: ``` print: (x:_) = { for x do :(elem:_) = { std::cout << elem << " "; } } main: ()->int = { print( : std::vector = (5,1); ); } ```
1 parent 7606052 commit 1090a31

File tree

2 files changed

+36
-20
lines changed

2 files changed

+36
-20
lines changed

source/cppfront.cpp

+20-4
Original file line numberDiff line numberDiff line change
@@ -1655,14 +1655,30 @@ class cppfront
16551655

16561656
if (n.expr.index() == primary_expression_node::declaration)
16571657
{
1658+
// This must be an anonymous declaration
16581659
auto& decl = std::get<primary_expression_node::declaration>(n.expr);
1660+
assert(decl && !decl->identifier);
16591661

1660-
// The usual non-null assertion, plus it should be an anonymous function
1661-
assert(decl && !decl->identifier && decl->is(declaration_node::function));
1662+
// Handle an anonymous function
1663+
if (decl->is(declaration_node::function)) {
1664+
auto lambda_intro = build_capture_lambda_intro_for(decl->captures, n.position());
1665+
emit(*decl, lambda_intro);
1666+
}
1667+
// Else an anonymous object as 'typeid { initializer }'
1668+
else {
1669+
assert(decl->is(declaration_node::object));
1670+
auto& type_id = std::get<declaration_node::object>(decl->type);
1671+
1672+
printer.add_pad_in_this_line( -5 );
16621673

1663-
auto lambda_intro = build_capture_lambda_intro_for(decl->captures, n.position());
1674+
emit(*type_id);
1675+
printer.print_cpp2("{", decl->position());
16641676

1665-
emit(*decl, lambda_intro);
1677+
assert(decl->initializer);
1678+
emit(*decl->initializer, false);
1679+
1680+
printer.print_cpp2("}", decl->position());
1681+
}
16661682
}
16671683
}
16681684

source/parse.h

+16-16
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ struct declaration_node
10631063
source_position pos;
10641064
std::unique_ptr<unqualified_id_node> identifier;
10651065

1066-
enum active : std::uint8_t { function, object };
1066+
enum active : std::uint8_t { function, object, udt_type };
10671067
std::variant<
10681068
std::unique_ptr<function_type_node>,
10691069
std::unique_ptr<type_id_node>
@@ -1563,7 +1563,7 @@ class parser
15631563
}
15641564

15651565
if (curr().type() == lexeme::LeftParen
1566-
// If in the future (not now) we want to experiment with braced-expressions
1566+
// If in the future (not now) we decide to allow braced-expressions
15671567
// || curr().type() == lexeme::LeftBrace
15681568
)
15691569
{
@@ -1589,25 +1589,25 @@ class parser
15891589
return n;
15901590
}
15911591

1592-
if (auto decl = unnamed_declaration(curr().position(), true, true)) // captures are allowed
1592+
if (auto decl = unnamed_declaration(curr().position(), false, true)) // captures are allowed
15931593
{
15941594
assert (!decl->identifier && "ICE: declaration should have been unnamed");
1595-
if (!decl->is(declaration_node::function)) {
1596-
error("an unnamed declaration at expression scope must be a function");
1595+
if (decl->is(declaration_node::udt_type)) {
1596+
error("(temporary alpha limitation) an unnamed declaration at expression scope must be a function or an object");
15971597
next();
15981598
return {};
15991599
}
1600-
auto& func = std::get<declaration_node::function>(decl->type);
1601-
assert(func);
1602-
if (func->returns.index() == function_type_node::list) {
1603-
error("an unnamed function at expression scope currently cannot return multiple values");
1604-
next();
1605-
return {};
1606-
}
1607-
if (!func->contracts.empty()) {
1608-
error("an unnamed function at expression scope currently cannot have contracts");
1609-
next();
1610-
return {};
1600+
if (auto func = std::get_if<declaration_node::function>(&decl->type)) {
1601+
if ((*func)->returns.index() == function_type_node::list) {
1602+
error("an unnamed function at expression scope currently cannot return multiple values");
1603+
next();
1604+
return {};
1605+
}
1606+
if (!(*func)->contracts.empty()) {
1607+
error("an unnamed function at expression scope currently cannot have contracts");
1608+
next();
1609+
return {};
1610+
}
16111611
}
16121612

16131613
n->expr = std::move(decl);

0 commit comments

Comments
 (0)