Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for nested functions #523

Merged
merged 1 commit into from Jun 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions gcc/rust/backend/rust-compile-base.h
Expand Up @@ -210,6 +210,9 @@ class HIRCompileBase : public HIR::HIRVisitor
void compile_function_body (Bfunction *fndecl,
std::unique_ptr<HIR::BlockExpr> &function_body,
bool has_return_type);

bool compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl,
std::vector<Bvariable *> &locals);
};

} // namespace Compile
Expand Down
44 changes: 6 additions & 38 deletions gcc/rust/backend/rust-compile-implitem.h
Expand Up @@ -183,26 +183,10 @@ class CompileInherentImplItem : public HIRCompileBase
}

std::vector<Bvariable *> locals;
rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool {
Resolver::Definition d;
bool ok = ctx->get_resolver ()->lookup_definition (n, &d);
rust_assert (ok);

HIR::Stmt *decl = nullptr;
ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
rust_assert (ok);

Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
locals.push_back (compiled);

return true;
});

bool toplevel_item
= function.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID;
Bblock *enclosing_scope
= toplevel_item ? NULL : ctx->peek_enclosing_scope ();
bool ok = compile_locals_for_block (*rib, fndecl, locals);
rust_assert (ok);

Bblock *enclosing_scope = NULL;
HIR::BlockExpr *function_body = function.get_definition ().get ();
Location start_location = function_body->get_locus ();
Location end_location = function_body->get_closing_locus ();
Expand Down Expand Up @@ -409,26 +393,10 @@ class CompileInherentImplItem : public HIRCompileBase
}

std::vector<Bvariable *> locals;
rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool {
Resolver::Definition d;
bool ok = ctx->get_resolver ()->lookup_definition (n, &d);
rust_assert (ok);

HIR::Stmt *decl = nullptr;
ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
rust_assert (ok);

Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
locals.push_back (compiled);

return true;
});

bool toplevel_item
= method.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID;
Bblock *enclosing_scope
= toplevel_item ? NULL : ctx->peek_enclosing_scope ();
bool ok = compile_locals_for_block (*rib, fndecl, locals);
rust_assert (ok);

Bblock *enclosing_scope = NULL;
HIR::BlockExpr *function_body = method.get_function_body ().get ();
Location start_location = function_body->get_locus ();
Location end_location = function_body->get_closing_locus ();
Expand Down
22 changes: 3 additions & 19 deletions gcc/rust/backend/rust-compile-item.h
Expand Up @@ -213,26 +213,10 @@ class CompileItem : public HIRCompileBase
}

std::vector<Bvariable *> locals;
rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool {
Resolver::Definition d;
bool ok = ctx->get_resolver ()->lookup_definition (n, &d);
rust_assert (ok);

HIR::Stmt *decl = nullptr;
ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
rust_assert (ok);

Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
locals.push_back (compiled);

return true;
});

bool toplevel_item
= function.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID;
Bblock *enclosing_scope
= toplevel_item ? NULL : ctx->peek_enclosing_scope ();
bool ok = compile_locals_for_block (*rib, fndecl, locals);
rust_assert (ok);

Bblock *enclosing_scope = NULL;
HIR::BlockExpr *function_body = function.get_definition ().get ();
Location start_location = function_body->get_locus ();
Location end_location = function_body->get_closing_locus ();
Expand Down
51 changes: 37 additions & 14 deletions gcc/rust/backend/rust-compile.cc
Expand Up @@ -212,20 +212,8 @@ CompileBlock::visit (HIR::BlockExpr &expr)
}

std::vector<Bvariable *> locals;
rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool {
Resolver::Definition d;
bool ok = ctx->get_resolver ()->lookup_definition (n, &d);
rust_assert (ok);

HIR::Stmt *decl = nullptr;
ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
rust_assert (ok);

Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
locals.push_back (compiled);

return true;
});
bool ok = compile_locals_for_block (*rib, fndecl, locals);
rust_assert (ok);

Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
Bblock *new_block
Expand Down Expand Up @@ -415,6 +403,41 @@ HIRCompileBase::compile_function_body (
}
}

bool
HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl,
std::vector<Bvariable *> &locals)
{
rib.iterate_decls ([&] (NodeId n, Location) mutable -> bool {
Resolver::Definition d;
bool ok = ctx->get_resolver ()->lookup_definition (n, &d);
rust_assert (ok);

HIR::Stmt *decl = nullptr;
ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
rust_assert (ok);

// if its a function we extract this out side of this fn context
// and it is not a local to this function
bool is_item = ctx->get_mappings ()->lookup_hir_item (
decl->get_mappings ().get_crate_num (),
decl->get_mappings ().get_hirid ())
!= nullptr;
if (is_item)
{
HIR::Item *item = static_cast<HIR::Item *> (decl);
CompileItem::compile (item, ctx, true);
return true;
}

Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx);
locals.push_back (compiled);

return true;
});

return true;
}

// Mr Mangle time

static const std::string kMangledSymbolPrefix = "_ZN";
Expand Down
85 changes: 85 additions & 0 deletions gcc/rust/hir/rust-ast-lower-stmt.h
Expand Up @@ -230,6 +230,91 @@ class ASTLoweringStmt : public ASTLoweringBase
empty.get_locus ());
}

void visit (AST::Function &function) override
{
// ignore for now and leave empty
std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
HIR::WhereClause where_clause (std::move (where_clause_items));
HIR::FunctionQualifiers qualifiers (
HIR::FunctionQualifiers::AsyncConstStatus::NONE, false);
HIR::Visibility vis = HIR::Visibility::create_public ();

// need
std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
if (function.has_generics ())
{
generic_params = lower_generic_params (function.get_generic_params ());
}

Identifier function_name = function.get_function_name ();
Location locus = function.get_locus ();

std::unique_ptr<HIR::Type> return_type
= function.has_return_type () ? std::unique_ptr<HIR::Type> (
ASTLoweringType::translate (function.get_return_type ().get ()))
: nullptr;

std::vector<HIR::FunctionParam> function_params;
for (auto &param : function.get_function_params ())
{
auto translated_pattern = std::unique_ptr<HIR::Pattern> (
ASTLoweringPattern::translate (param.get_pattern ().get ()));
auto translated_type = std::unique_ptr<HIR::Type> (
ASTLoweringType::translate (param.get_type ().get ()));

auto crate_num = mappings->get_current_crate ();
Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
mappings->get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);

auto hir_param
= HIR::FunctionParam (mapping, std::move (translated_pattern),
std::move (translated_type),
param.get_locus ());
function_params.push_back (hir_param);
}

bool terminated = false;
std::unique_ptr<HIR::BlockExpr> function_body
= std::unique_ptr<HIR::BlockExpr> (
ASTLoweringBlock::translate (function.get_definition ().get (),
&terminated));

auto crate_num = mappings->get_current_crate ();
Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
mappings->get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);

mappings->insert_location (crate_num,
function_body->get_mappings ().get_hirid (),
function.get_locus ());

auto fn
= new HIR::Function (mapping, std::move (function_name),
std::move (qualifiers), std::move (generic_params),
std::move (function_params), std::move (return_type),
std::move (where_clause), std::move (function_body),
std::move (vis), function.get_outer_attrs (), locus);

mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
fn);
mappings->insert_hir_stmt (mapping.get_crate_num (), mapping.get_hirid (),
fn);
mappings->insert_location (crate_num, mapping.get_hirid (),
function.get_locus ());

// add the mappings for the function params at the end
for (auto &param : fn->get_function_params ())
{
mappings->insert_hir_param (mapping.get_crate_num (),
param.get_mappings ().get_hirid (), &param);
mappings->insert_location (crate_num, mapping.get_hirid (),
param.get_locus ());
}

translated = fn;
}

private:
ASTLoweringStmt () : translated (nullptr), terminated (false) {}

Expand Down
55 changes: 55 additions & 0 deletions gcc/rust/resolve/rust-ast-resolve-stmt.h
Expand Up @@ -129,6 +129,61 @@ class ResolveStmt : public ResolverBase
resolver->get_type_scope ().pop ();
}

void visit (AST::Function &function) override
{
auto path = ResolveFunctionItemToCanonicalPath::resolve (function);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
resolver->insert_new_definition (function.get_node_id (),
Definition{function.get_node_id (),
function.get_node_id ()});

NodeId scope_node_id = function.get_node_id ();
resolver->get_name_scope ().push (scope_node_id);
resolver->get_type_scope ().push (scope_node_id);
resolver->get_label_scope ().push (scope_node_id);
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
resolver->push_new_label_rib (resolver->get_type_scope ().peek ());

if (function.has_generics ())
{
for (auto &generic : function.get_generic_params ())
ResolveGenericParam::go (generic.get (), function.get_node_id ());
}

if (function.has_return_type ())
ResolveType::go (function.get_return_type ().get (),
function.get_node_id ());

// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto &param : function.get_function_params ())
{
ResolveType::go (param.get_type ().get (), param.get_node_id ());
PatternDeclaration::go (param.get_pattern ().get (),
param.get_node_id ());

// the mutability checker needs to verify for immutable decls the number
// of assignments are <1. This marks an implicit assignment
resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (),
param.get_node_id ());
}

// resolve the function body
ResolveExpr::go (function.get_definition ().get (),
function.get_node_id ());

resolver->get_name_scope ().pop ();
resolver->get_type_scope ().pop ();
resolver->get_label_scope ().pop ();
}

private:
ResolveStmt (NodeId parent) : ResolverBase (parent) {}
};
Expand Down
5 changes: 2 additions & 3 deletions gcc/rust/resolve/rust-ast-resolve.cc
Expand Up @@ -499,9 +499,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
else
{
rust_error_at (expr->get_locus (),
"unknown root segment in path %s lookup %s",
expr->as_string ().c_str (),
root_ident_seg.as_string ().c_str ());
"Cannot find path %<%s%> in this scope",
expr->as_string ().c_str ());
return;
}

Expand Down