diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/expr.cpp | 2 | ||||
-rw-r--r-- | src/ast/expr.hpp | 19 | ||||
-rw-r--r-- | src/expand/derive.cpp | 32 | ||||
-rw-r--r-- | src/expand/mod.cpp | 5 | ||||
-rw-r--r-- | src/hir/expr.hpp | 7 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 10 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 44 | ||||
-rw-r--r-- | src/macro_rules/eval.cpp | 3 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/parse/common.hpp | 3 | ||||
-rw-r--r-- | src/parse/expr.cpp | 26 |
11 files changed, 92 insertions, 61 deletions
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 18f9ccae..780b480c 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -67,7 +67,7 @@ NODE(ExprNode_Block, { nodes.push_back( n->clone() ); if( m_local_mod ) TODO(get_pos(), "Handle cloning ExprNode_Block with a module"); - return NEWNODE(ExprNode_Block, mv$(nodes), nullptr); + return NEWNODE(ExprNode_Block, m_is_unsafe, m_yields_final_value, mv$(nodes), nullptr); }) NODE(ExprNode_Macro, { diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index e7f6750d..0d503b81 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -44,6 +44,7 @@ public: friend ::std::ostream& operator<<(::std::ostream& os, const ExprNode& node); static ::std::unique_ptr<ExprNode> from_deserialiser(Deserialiser& d); }; +typedef ::std::unique_ptr<AST::ExprNode> ExprNodeP; #define NODE_METHODS() \ void visit(NodeVisitor& nv) override;\ @@ -54,21 +55,24 @@ struct ExprNode_Block: public ExprNode { bool m_is_unsafe; + bool m_yields_final_value; ::std::unique_ptr<AST::Module> m_local_mod; - ::std::vector< ::std::unique_ptr<ExprNode> > m_nodes; + ::std::vector<ExprNodeP> m_nodes; - ExprNode_Block(): - m_is_unsafe(false) - {} - ExprNode_Block(::std::vector< ::std::unique_ptr<ExprNode> >&& nodes, ::std::unique_ptr<AST::Module> local_mod): + ExprNode_Block(::std::vector<ExprNodeP> nodes={}): m_is_unsafe(false), + m_yields_final_value(true), + m_local_mod(), + m_nodes( mv$(nodes) ) + {} + ExprNode_Block(bool is_unsafe, bool yields_final_value, ::std::vector<ExprNodeP> nodes, ::std::unique_ptr<AST::Module> local_mod): + m_is_unsafe(is_unsafe), + m_yields_final_value(yields_final_value), m_local_mod( move(local_mod) ), m_nodes( move(nodes) ) { } - void set_unsafe() { m_is_unsafe = true; } - NODE_METHODS(); }; @@ -708,7 +712,6 @@ public: friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat); }; -typedef ::std::unique_ptr<AST::ExprNode> ExprNodeP; } #endif diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index 381fc883..78707a87 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -243,7 +243,7 @@ class Deriver_Debug: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "f"), f_type ) ) ); - fcn.set_code( NEWNODE(Block, vec$(mv$(node)), ::std::unique_ptr<AST::Module>()) ); + fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); AST::GenericParams params = get_params_with_bounds(p, debug_trait, mv$(types_to_bound)); @@ -354,7 +354,7 @@ public: //nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) ); } - //code = NEWNODE(Block, mv$(nodes), nullptr); + //code = NEWNODE(Block, mv$(nodes)); code = NEWNODE(CallMethod, NEWNODE(NamedValue, AST::Path("f")), AST::PathNode("write_str",{}), @@ -375,7 +375,7 @@ public: //nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) ); } - //code = NEWNODE(Block, mv$(nodes), nullptr); + //code = NEWNODE(Block, mv$(nodes) ); code = NEWNODE(CallMethod, NEWNODE(NamedValue, AST::Path("f")), AST::PathNode("write_str",{}), @@ -419,7 +419,7 @@ class Deriver_PartialEq: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "v"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ) ) ); - fcn.set_code( NEWNODE(Block, vec$(mv$(node)), ::std::unique_ptr<AST::Module>()) ); + fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); AST::GenericParams params = get_params_with_bounds(p, trait_path, mv$(types_to_bound)); @@ -463,7 +463,7 @@ public: ) nodes.push_back( NEWNODE(Bool, true) ); - return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes), nullptr)); + return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes))); } AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override @@ -517,7 +517,7 @@ public: nodes.push_back( NEWNODE(Bool, true) ); pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a)); pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_b)); - code = NEWNODE(Block, mv$(nodes), nullptr); + code = NEWNODE(Block, mv$(nodes)); } ), (Struct, @@ -544,7 +544,7 @@ public: nodes.push_back( NEWNODE(Bool, true) ); pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true); pat_b = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_b), true); - code = NEWNODE(Block, mv$(nodes), nullptr); + code = NEWNODE(Block, mv$(nodes)); ) ) @@ -568,7 +568,7 @@ public: arms.push_back(AST::ExprNode_Match_Arm( ::make_vec1( AST::Pattern() ), nullptr, - NEWNODE(Block, {}, nullptr) + NEWNODE(Bool, false) )); } @@ -601,7 +601,7 @@ class Deriver_Eq: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ) ) ); - fcn.set_code( NEWNODE(Block, vec$(mv$(node)), ::std::unique_ptr<AST::Module>()) ); + fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); AST::GenericParams params = get_params_with_bounds(p, trait_path, mv$(types_to_bound)); @@ -640,7 +640,7 @@ public: ) ) - return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes), nullptr)); + return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes))); } AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override @@ -658,13 +658,13 @@ public: TU_MATCH(::AST::EnumVariantData, (v.m_data), (e), (Value, - code = NEWNODE(Block, {}, nullptr); + code = NEWNODE(Block); pat_a = AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(base_path + v.m_name)); ), (Tuple, if( e.m_sub_types.size() == 0 ) { - code = NEWNODE(Block, {}, nullptr); + code = NEWNODE(Block); pat_a = AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(base_path + v.m_name)); } else @@ -680,7 +680,7 @@ public: } pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a)); - code = NEWNODE(Block, mv$(nodes), nullptr); + code = NEWNODE(Block, mv$(nodes)); } ), (Struct, @@ -695,7 +695,7 @@ public: } pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true); - code = NEWNODE(Block, mv$(nodes), nullptr); + code = NEWNODE(Block, mv$(nodes)); ) ) @@ -738,7 +738,7 @@ class Deriver_Clone: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ) ) ); - fcn.set_code( NEWNODE(Block, vec$(mv$(node)), ::std::unique_ptr<AST::Module>()) ); + fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); AST::GenericParams params = get_params_with_bounds(p, trait_path, mv$(types_to_bound)); @@ -794,7 +794,7 @@ public: ) ) - return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes), nullptr)); + return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes))); } AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index e6d5d60e..1f87ad7f 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -597,12 +597,11 @@ struct CExpandExpr: // `}` for(auto& n : nodes_unsafe) n->set_pos( node.get_pos() ); - nodes.push_back(::AST::ExprNodeP(new ::AST::ExprNode_Block( mv$(nodes_unsafe), nullptr ))); - dynamic_cast< ::AST::ExprNode_Block&>(*nodes.back()).m_is_unsafe = true; + nodes.push_back(::AST::ExprNodeP(new ::AST::ExprNode_Block( true, true, mv$(nodes_unsafe), nullptr ))); } for(auto& n : nodes) n->set_pos( node.get_pos() ); - replacement.reset(new ::AST::ExprNode_Block( mv$(nodes), nullptr )); + replacement.reset(new ::AST::ExprNode_Block( mv$(nodes) )); } } }; diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 3a7839a8..a912af9c 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -68,18 +68,21 @@ struct ExprNode_Block: { bool m_is_unsafe; ::std::vector< ExprNodeP > m_nodes; + bool m_yields_final; ::HIR::SimplePath m_local_mod; t_trait_list m_traits; ExprNode_Block(Span sp): ExprNode(mv$(sp)), - m_is_unsafe(false) + m_is_unsafe(false), + m_yields_final(false) {} ExprNode_Block(Span sp, bool is_unsafe, ::std::vector<ExprNodeP> nodes): ExprNode( mv$(sp) ), m_is_unsafe(is_unsafe), - m_nodes( mv$(nodes) ) + m_nodes( mv$(nodes) ), + m_yields_final(false) {} NODE_METHODS(); diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 35d27b24..3a2cd652 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -30,14 +30,10 @@ struct LowerHIR_ExprNode_Visitor: auto rv = new ::HIR::ExprNode_Block(v.span()); for(const auto& n : v.m_nodes) { - if( n ) { - rv->m_nodes.push_back( LowerHIR_ExprNode_Inner( *n ) ); - } - else { - assert(&n == &v.m_nodes.back()); - rv->m_nodes.push_back( ::HIR::ExprNodeP( new ::HIR::ExprNode_Tuple(Span(), {}) ) ); - } + ASSERT_BUG(v.get_pos(), n, "NULL node encountered in block"); + rv->m_nodes.push_back( LowerHIR_ExprNode_Inner( *n ) ); } + rv->m_yields_final = v.m_yields_final_value; if( v.m_local_mod ) { diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index a8ad4e3a..f17f02a4 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -433,6 +433,7 @@ namespace { if( node.m_nodes.size() > 0 ) { + bool diverges = false; this->push_traits( node.m_traits ); this->push_inner_coerce(false); @@ -444,16 +445,49 @@ namespace { // - Blocks (and block-likes) are forced to () // - What if they were '({});'? Then they're left dangling snp->visit(*this); + + // If this statement yields !, then mark the block as diverging + // - TODO: Search the entire type for `!`? (What about pointers to it? or Option/Result?) + if( this->context.get_type(snp->m_res_type).m_data.is_Diverge() ) { + diverges = true; + } } this->pop_inner_coerce(); - - auto& snp = node.m_nodes.back(); - this->context.add_ivars( snp->m_res_type ); - this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type); - snp->visit(*this); + + if( node.m_yields_final ) + { + auto& snp = node.m_nodes.back(); + DEBUG("Block yields final value"); + this->context.add_ivars( snp->m_res_type ); + this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type); + snp->visit(*this); + } + else + { + auto& snp = node.m_nodes.back(); + this->context.add_ivars( snp->m_res_type ); + // - Not yielded - so don't equate the return + snp->visit(*this); + + // If a statement in this block diverges + if( diverges ) { + DEBUG("Block diverges, yield !"); + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_diverge()); + } + else { + DEBUG("Block doesn't diverge but doesn't yeild a value, yield ()"); + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit()); + } + } this->pop_traits( node.m_traits ); } + else + { + // Result should be `()` + DEBUG("Block is empty, yield ()"); + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit()); + } } void visit(::HIR::ExprNode_Return& node) override { diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index 7bcee76e..137f28c9 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -14,9 +14,6 @@ #include "pattern_checks.hpp" #include <parse/interpolated_fragment.hpp> -extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex); -extern AST::ExprNodeP Parse_Stmt(TokenStream& lex); - class ParameterMappings { TAGGED_UNION_EX(CaptureLayer, (), Vals, ( diff --git a/src/main.cpp b/src/main.cpp index 85916db5..5b2ee161 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ void init_debug_list() g_debug_disable_map.insert( "Constant Evaluate" );
g_debug_disable_map.insert( "Typecheck Outer");
- g_debug_disable_map.insert( "Typecheck Expressions" );
+ //g_debug_disable_map.insert( "Typecheck Expressions" );
g_debug_disable_map.insert( "Expand HIR Annotate" );
g_debug_disable_map.insert( "Expand HIR Closures" );
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 484b3a67..49a0bdf8 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -53,6 +53,9 @@ extern AST::Expr Parse_Expr(TokenStream& lex); extern AST::Expr Parse_ExprBlock(TokenStream& lex);
extern AST::ExprNodeP Parse_Expr0(TokenStream& lex);
extern AST::ExprNodeP Parse_ExprVal(TokenStream& lex);
+extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false);
+extern AST::ExprNodeP Parse_Stmt(TokenStream& lex);
+
extern bool Parse_IsTokValue(eTokenType tok_type);
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index b497e4a7..ba4679e0 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -21,9 +21,9 @@ using AST::ExprNodeP; static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_pos(lex.getPosition()); return ExprNodeP(en); }
#define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__))
-ExprNodeP Parse_ExprBlockNode(TokenStream& lex);
+//ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false); // common.hpp
ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence);
-ExprNodeP Parse_Stmt(TokenStream& lex);
+//ExprNodeP Parse_Stmt(TokenStream& lex); // common.hpp
ExprNodeP Parse_Expr0(TokenStream& lex);
ExprNodeP Parse_IfStmt(TokenStream& lex);
ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime);
@@ -42,11 +42,12 @@ AST::Expr Parse_ExprBlock(TokenStream& lex) return ::AST::Expr( Parse_ExprBlockNode(lex) );
}
-ExprNodeP Parse_ExprBlockNode(TokenStream& lex)
+ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/)
{
TRACE_FUNCTION;
Token tok;
+ bool yields_final_value = true;
::std::vector<ExprNodeP> nodes;
::std::unique_ptr<AST::Module> local_mod;
@@ -118,14 +119,15 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) {
DEBUG("expect_end == false, end of block");
nodes.push_back( NEWNODE(AST::ExprNode_Tuple, ::std::vector<ExprNodeP>()) );
- // NOTE: Would break, but we're in a switch
+ yields_final_value = false;
+ // NOTE: Would break out of the loop, but we're in a switch
}
break;
}
}
}
- return NEWNODE( AST::ExprNode_Block, ::std::move(nodes), mv$(local_mod) );
+ return NEWNODE( AST::ExprNode_Block, is_unsafe, yields_final_value, mv$(nodes), mv$(local_mod) );
}
/// Parse a single line from a block
@@ -199,11 +201,8 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence) return Parse_IfStmt(lex);
case TOK_RWORD_MATCH:
return Parse_Expr_Match(lex);
- case TOK_RWORD_UNSAFE: {
- auto rv = Parse_ExprBlockNode(lex);
- dynamic_cast<AST::ExprNode_Block&>(*rv).set_unsafe();
- return rv;
- }
+ case TOK_RWORD_UNSAFE:
+ return Parse_ExprBlockNode(lex, true);
case TOK_RWORD_RETURN:
case TOK_RWORD_CONTINUE:
@@ -991,11 +990,8 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return Parse_Expr_Match(lex);
case TOK_RWORD_IF:
return Parse_IfStmt(lex);
- case TOK_RWORD_UNSAFE: {
- auto rv = Parse_ExprBlockNode(lex);
- dynamic_cast<AST::ExprNode_Block&>(*rv).set_unsafe();
- return rv;
- }
+ case TOK_RWORD_UNSAFE:
+ return Parse_ExprBlockNode(lex, true);
// UFCS
case TOK_DOUBLE_LT:
|