diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-03-04 12:59:38 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-03-04 12:59:38 +0800 |
commit | bc13507c42e0e26dd280799b4f29867ee45235ac (patch) | |
tree | 5030d0f1c5c86d172b728bdcae170b16e3b735eb /src | |
parent | 9637c5a8a580acd6caec02bc34c24d13f7f76344 (diff) | |
download | mrust-bc13507c42e0e26dd280799b4f29867ee45235ac.tar.gz |
Expand - Desugar `try` into a loop
Diffstat (limited to 'src')
-rw-r--r-- | src/expand/mod.cpp | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 8e36bd95..fd188345 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -347,6 +347,10 @@ struct CExpandExpr: LList<const AST::Module*> modstack; ::std::unique_ptr<::AST::ExprNode> replacement; + // Stack of `try { ... }` blocks (the string is the loop label for the desugaring) + ::std::vector< ::std::string> m_try_stack; + unsigned m_try_index = 0; + AST::ExprNode_Block* current_block = nullptr; CExpandExpr(::AST::Crate& crate, LList<const AST::Module*> ms): @@ -548,7 +552,20 @@ struct CExpandExpr: this->modstack = mv$(prev_modstack); } void visit(::AST::ExprNode_Try& node) override { + // Desugar into + // ``` + // loop '#tryNNN { + // break '#tryNNN { ... } + // } + // ``` + // NOTE: MIR lowering and HIR typecheck need to know to skip these (OR resolve should handle naming all loop blocks) + m_try_stack.push_back(FMT("#try" << m_try_index++)); this->visit_nodelete(node, node.m_inner); + auto loop_name = mv$(m_try_stack.back()); + m_try_stack.pop_back(); + + auto break_node = AST::ExprNodeP(new AST::ExprNode_Flow(AST::ExprNode_Flow::BREAK, loop_name, mv$(node.m_inner))); + this->replacement = AST::ExprNodeP(new AST::ExprNode_Loop(loop_name, mv$(break_node))); } void visit(::AST::ExprNode_Asm& node) override { for(auto& v : node.m_output) @@ -837,8 +854,8 @@ struct CExpandExpr: ::make_vec1( ::AST::Pattern(::AST::Pattern::TagNamedTuple(), node.span(), path_Err, ::make_vec1( ::AST::Pattern(::AST::Pattern::TagBind(), node.span(), "e") )) ), nullptr, ::AST::ExprNodeP(new ::AST::ExprNode_Flow( - ::AST::ExprNode_Flow::RETURN, - "", + (m_try_stack.empty() ? ::AST::ExprNode_Flow::RETURN : ::AST::ExprNode_Flow::BREAK), // NOTE: uses `break 'tryblock` instead of return if in a try block. + (m_try_stack.empty() ? "" : m_try_stack.back()), ::AST::ExprNodeP(new ::AST::ExprNode_CallPath( ::AST::Path(path_Try_from_error), ::make_vec1( |