diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-10 10:33:33 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-10 18:10:57 +0000 |
commit | ae273ffac99cb75d832a11a83fd63291bb74cbdc (patch) | |
tree | a3d9a44ebe75c96fac728c8f4ed3d0796664ed29 /gcc/rust/resolve | |
parent | 016c40bedc7e3f53e2c413895f77c0d9f723eb3c (diff) | |
download | gcc-ae273ffac99cb75d832a11a83fd63291bb74cbdc.zip gcc-ae273ffac99cb75d832a11a83fd63291bb74cbdc.tar.gz gcc-ae273ffac99cb75d832a11a83fd63291bb74cbdc.tar.bz2 |
Support Break without label and expression
This reuses GENERICS LOOP_EXPR and EXIT_EXPR to implement the infinite
loop.
Addresses: #106 #108
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 51 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 2 |
2 files changed, 52 insertions, 1 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index e8ee8b3..9cfa04d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -243,9 +243,60 @@ public: void visit (AST::LoopExpr &expr) { + if (expr.has_loop_label ()) + { + auto label = expr.get_loop_label (); + if (label.get_lifetime ().get_lifetime_type () + != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + auto label_name = label.get_lifetime ().get_lifetime_name (); + auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); + resolver->get_label_scope ().insert ( + label_name, label_lifetime_node_id, label.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (label.get_locus (), + "label redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); + resolver->insert_new_definition (label_lifetime_node_id, + Definition{label_lifetime_node_id, + label.get_node_id ()}); + } ResolveExpr::go (expr.get_loop_block ().get (), expr.get_node_id ()); } + void visit (AST::BreakExpr &expr) + { + if (expr.has_label ()) + { + auto label = expr.get_label (); + if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + NodeId resolved_node = UNKNOWN_NODEID; + if (!resolver->get_label_scope ().lookup (label.get_lifetime_name (), + &resolved_node)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to resolve label"); + return; + } + resolver->insert_resolved_label (label.get_node_id (), resolved_node); + } + + if (expr.has_break_expr ()) + ResolveExpr::go (expr.get_break_expr ().get (), expr.get_node_id ()); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 0ed2bfb..213d141 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -252,7 +252,7 @@ Resolver::insert_resolved_label (NodeId refId, NodeId defId) auto it = resolved_labels.find (refId); rust_assert (it == resolved_labels.end ()); - resolved_types[refId] = defId; + resolved_labels[refId] = defId; get_label_scope ().append_reference_for_def (refId, defId); } |