summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-09-15 10:28:04 +0800
committerJohn Hodge <tpg@mutabah.net>2016-09-15 10:28:04 +0800
commitb150106b0fc68d52b492ffe485e3c9c3ddad1c22 (patch)
tree72b8139ae29059bc1be2b06d97868fc3bc29ec14 /src
parent1b8a291c385ef116a30ff3f643eb82d0163549f6 (diff)
downloadmrust-b150106b0fc68d52b492ffe485e3c9c3ddad1c22.tar.gz
Restructure - Don't insert automatic () statements at end of blocks
Diffstat (limited to 'src')
-rw-r--r--src/ast/expr.cpp2
-rw-r--r--src/ast/expr.hpp19
-rw-r--r--src/expand/derive.cpp32
-rw-r--r--src/expand/mod.cpp5
-rw-r--r--src/hir/expr.hpp7
-rw-r--r--src/hir/from_ast_expr.cpp10
-rw-r--r--src/hir_typeck/expr_cs.cpp44
-rw-r--r--src/macro_rules/eval.cpp3
-rw-r--r--src/main.cpp2
-rw-r--r--src/parse/common.hpp3
-rw-r--r--src/parse/expr.cpp26
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: