-
Notifications
You must be signed in to change notification settings - Fork 165
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
2688 labelled block #2689
2688 labelled block #2689
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -11,6 +11,36 @@ namespace AST { | |||||||||
* "has_whatever" pairs with | ||||||||||
* optional types (std::optional or boost::optional)? */ | ||||||||||
|
||||||||||
// Loop label expression AST node used with break and continue expressions | ||||||||||
// TODO: inline? | ||||||||||
class LoopLabel /*: public Node*/ | ||||||||||
{ | ||||||||||
Lifetime label; // or type LIFETIME_OR_LABEL | ||||||||||
location_t locus; | ||||||||||
|
||||||||||
NodeId node_id; | ||||||||||
|
||||||||||
public: | ||||||||||
std::string as_string () const; | ||||||||||
|
||||||||||
LoopLabel (Lifetime loop_label, location_t locus = UNDEF_LOCATION) | ||||||||||
: label (std::move (loop_label)), locus (locus), | ||||||||||
node_id (Analysis::Mappings::get ()->get_next_node_id ()) | ||||||||||
{} | ||||||||||
|
||||||||||
// Returns whether the LoopLabel is in an error state. | ||||||||||
bool is_error () const { return label.is_error (); } | ||||||||||
|
||||||||||
// Creates an error state LoopLabel. | ||||||||||
static LoopLabel error () { return LoopLabel (Lifetime::error ()); } | ||||||||||
|
||||||||||
location_t get_locus () const { return locus; } | ||||||||||
|
||||||||||
Lifetime &get_lifetime () { return label; } | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
or
Suggested change
|
||||||||||
|
||||||||||
NodeId get_node_id () const { return node_id; } | ||||||||||
}; | ||||||||||
|
||||||||||
// AST node for an expression with an accompanying block - abstract | ||||||||||
class ExprWithBlock : public Expr | ||||||||||
{ | ||||||||||
|
@@ -2396,6 +2426,7 @@ class BlockExpr : public ExprWithBlock | |||||||||
std::vector<Attribute> inner_attrs; | ||||||||||
std::vector<std::unique_ptr<Stmt> > statements; | ||||||||||
std::unique_ptr<Expr> expr; | ||||||||||
LoopLabel label; | ||||||||||
location_t start_locus; | ||||||||||
location_t end_locus; | ||||||||||
bool marked_for_strip = false; | ||||||||||
|
@@ -2412,19 +2443,21 @@ class BlockExpr : public ExprWithBlock | |||||||||
BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements, | ||||||||||
std::unique_ptr<Expr> block_expr, | ||||||||||
std::vector<Attribute> inner_attribs, | ||||||||||
std::vector<Attribute> outer_attribs, location_t start_locus, | ||||||||||
location_t end_locus) | ||||||||||
std::vector<Attribute> outer_attribs, LoopLabel label, | ||||||||||
location_t start_locus, location_t end_locus) | ||||||||||
: outer_attrs (std::move (outer_attribs)), | ||||||||||
inner_attrs (std::move (inner_attribs)), | ||||||||||
statements (std::move (block_statements)), expr (std::move (block_expr)), | ||||||||||
start_locus (start_locus), end_locus (end_locus) | ||||||||||
label (std::move (label)), start_locus (start_locus), | ||||||||||
end_locus (end_locus) | ||||||||||
{} | ||||||||||
|
||||||||||
// Copy constructor with clone | ||||||||||
BlockExpr (BlockExpr const &other) | ||||||||||
: ExprWithBlock (other), outer_attrs (other.outer_attrs), | ||||||||||
inner_attrs (other.inner_attrs), start_locus (other.start_locus), | ||||||||||
end_locus (other.end_locus), marked_for_strip (other.marked_for_strip) | ||||||||||
inner_attrs (other.inner_attrs), label (other.label), | ||||||||||
start_locus (other.start_locus), end_locus (other.end_locus), | ||||||||||
marked_for_strip (other.marked_for_strip) | ||||||||||
{ | ||||||||||
// guard to protect from null pointer dereference | ||||||||||
if (other.expr != nullptr) | ||||||||||
|
@@ -2524,6 +2557,9 @@ class BlockExpr : public ExprWithBlock | |||||||||
outer_attrs = std::move (new_attrs); | ||||||||||
} | ||||||||||
|
||||||||||
bool has_label () { return !label.is_error (); } | ||||||||||
LoopLabel &get_label () { return label; } | ||||||||||
|
||||||||||
protected: | ||||||||||
/* Use covariance to implement clone function as returning this object rather | ||||||||||
* than base */ | ||||||||||
|
@@ -3352,36 +3388,6 @@ class UnsafeBlockExpr : public ExprWithBlock | |||||||||
} | ||||||||||
}; | ||||||||||
|
||||||||||
// Loop label expression AST node used with break and continue expressions | ||||||||||
// TODO: inline? | ||||||||||
class LoopLabel /*: public Node*/ | ||||||||||
{ | ||||||||||
Lifetime label; // or type LIFETIME_OR_LABEL | ||||||||||
location_t locus; | ||||||||||
|
||||||||||
NodeId node_id; | ||||||||||
|
||||||||||
public: | ||||||||||
std::string as_string () const; | ||||||||||
|
||||||||||
LoopLabel (Lifetime loop_label, location_t locus = UNDEF_LOCATION) | ||||||||||
: label (std::move (loop_label)), locus (locus), | ||||||||||
node_id (Analysis::Mappings::get ()->get_next_node_id ()) | ||||||||||
{} | ||||||||||
|
||||||||||
// Returns whether the LoopLabel is in an error state. | ||||||||||
bool is_error () const { return label.is_error (); } | ||||||||||
|
||||||||||
// Creates an error state LoopLabel. | ||||||||||
static LoopLabel error () { return LoopLabel (Lifetime::error ()); } | ||||||||||
|
||||||||||
location_t get_locus () const { return locus; } | ||||||||||
|
||||||||||
Lifetime &get_lifetime () { return label; } | ||||||||||
|
||||||||||
NodeId get_node_id () const { return node_id; } | ||||||||||
}; | ||||||||||
|
||||||||||
// Base loop expression AST node - aka LoopExpr | ||||||||||
class BaseLoopExpr : public ExprWithBlock | ||||||||||
{ | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,34 @@ | |
namespace Rust { | ||
namespace HIR { | ||
|
||
// Loop label expression HIR node used with break and continue expressions | ||
// TODO: inline? | ||
class LoopLabel /*: public Node*/ | ||
{ | ||
Lifetime label; // or type LIFETIME_OR_LABEL | ||
|
||
location_t locus; | ||
|
||
Analysis::NodeMapping mappings; | ||
|
||
public: | ||
std::string as_string () const; | ||
|
||
LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, | ||
location_t locus) | ||
: label (std::move (loop_label)), locus (locus), mappings (mapping) | ||
{} | ||
|
||
// Returns whether the LoopLabel is in an error state. | ||
bool is_error () const { return label.is_error (); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here, should be |
||
|
||
location_t get_locus () const { return locus; } | ||
|
||
Analysis::NodeMapping &get_mappings () { return mappings; } | ||
|
||
Lifetime &get_lifetime () { return label; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
}; | ||
|
||
// HIR node for an expression with an accompanying block - abstract | ||
class ExprWithBlock : public Expr | ||
{ | ||
|
@@ -2121,6 +2149,7 @@ class BlockExpr : public ExprWithBlock, public WithInnerAttrs | |
std::vector<std::unique_ptr<Stmt> > statements; | ||
std::unique_ptr<Expr> expr; | ||
bool tail_reachable; | ||
LoopLabel label; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good to me, but probably not in this PR - the same logic is used for loops (was taken from there) and it would make more sense to change it everywhere at once, otherwise it is more confusing. Agree @P-E-P ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right. Let's merge this then 👍 |
||
location_t start_locus; | ||
location_t end_locus; | ||
|
||
|
@@ -2140,19 +2169,19 @@ class BlockExpr : public ExprWithBlock, public WithInnerAttrs | |
std::vector<std::unique_ptr<Stmt> > block_statements, | ||
std::unique_ptr<Expr> block_expr, bool tail_reachable, | ||
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs, | ||
location_t start_locus, location_t end_locus) | ||
LoopLabel label, location_t start_locus, location_t end_locus) | ||
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)), | ||
WithInnerAttrs (std::move (inner_attribs)), | ||
statements (std::move (block_statements)), expr (std::move (block_expr)), | ||
tail_reachable (tail_reachable), start_locus (start_locus), | ||
end_locus (end_locus) | ||
tail_reachable (tail_reachable), label (std::move (label)), | ||
start_locus (start_locus), end_locus (end_locus) | ||
{} | ||
|
||
// Copy constructor with clone | ||
BlockExpr (BlockExpr const &other) | ||
: ExprWithBlock (other), /*statements(other.statements),*/ | ||
WithInnerAttrs (other.inner_attrs), start_locus (other.start_locus), | ||
end_locus (other.end_locus) | ||
WithInnerAttrs (other.inner_attrs), label (other.label), | ||
start_locus (other.start_locus), end_locus (other.end_locus) | ||
{ | ||
// guard to protect from null pointer dereference | ||
if (other.expr != nullptr) | ||
|
@@ -2211,6 +2240,9 @@ class BlockExpr : public ExprWithBlock, public WithInnerAttrs | |
return ExprType::Block; | ||
} | ||
|
||
bool has_label () const { return !label.is_error (); } | ||
LoopLabel &get_label () { return label; } | ||
|
||
protected: | ||
/* Use covariance to implement clone function as returning this object rather | ||
* than base */ | ||
|
@@ -2835,34 +2867,6 @@ class UnsafeBlockExpr : public ExprWithBlock | |
} | ||
}; | ||
|
||
// Loop label expression HIR node used with break and continue expressions | ||
// TODO: inline? | ||
class LoopLabel /*: public Node*/ | ||
{ | ||
Lifetime label; // or type LIFETIME_OR_LABEL | ||
|
||
location_t locus; | ||
|
||
Analysis::NodeMapping mappings; | ||
|
||
public: | ||
std::string as_string () const; | ||
|
||
LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label, | ||
location_t locus) | ||
: label (std::move (loop_label)), locus (locus), mappings (mapping) | ||
{} | ||
|
||
// Returns whether the LoopLabel is in an error state. | ||
bool is_error () const { return label.is_error (); } | ||
|
||
location_t get_locus () const { return locus; } | ||
|
||
Analysis::NodeMapping &get_mappings () { return mappings; } | ||
|
||
Lifetime &get_lifetime () { return label; } | ||
}; | ||
|
||
// Base loop expression HIR node - aka LoopExpr | ||
class BaseLoopExpr : public ExprWithBlock | ||
{ | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -303,6 +303,28 @@ ResolveExpr::visit (AST::BlockExpr &expr) | |||||
resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); | ||||||
resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); | ||||||
|
||||||
if (expr.has_label ()) | ||||||
{ | ||||||
auto label = expr.get_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"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
for consistency :) |
||||||
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 ( | ||||||
CanonicalPath::new_seg (label.get_node_id (), label_name), | ||||||
label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, | ||||||
[&] (const CanonicalPath &, NodeId, location_t locus) -> void { | ||||||
rust_error_at (label.get_locus (), "label redefined multiple times"); | ||||||
rust_error_at (locus, "was defined here"); | ||||||
}); | ||||||
} | ||||||
|
||||||
for (auto &s : expr.get_statements ()) | ||||||
{ | ||||||
if (s->is_item ()) | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from an API point of view, I'm not sure if
LoopLabel::error
here is very nice. something likeempty
would probably be better? sorry for nitpicking haha