diff options
-rw-r--r-- | src/ast/expr.hpp | 1 | ||||
-rw-r--r-- | src/hir/expr.cpp | 5 | ||||
-rw-r--r-- | src/hir/expr.hpp | 102 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 36 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 102 | ||||
-rw-r--r-- | src/hir_conv/resolve_ufcs.cpp | 188 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 95 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 83 |
8 files changed, 394 insertions, 218 deletions
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index bddada90..98314824 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -33,6 +33,7 @@ public: void set_pos(Position p) { m_pos = ::std::move(p); } const Position& get_pos() const { return m_pos; } + Span span() const { return m_pos; } void set_attrs(MetaItems&& mi) { m_attrs = mv$(mi); diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index a56e608a..3d48f9d4 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -5,11 +5,6 @@ ::HIR::ExprNode::~ExprNode() { } -const Span& ::HIR::ExprNode::span() const -{ - static Span rv = Span(); - return rv; -} #define DEF_VISIT(nt, n, code) void ::HIR::nt::visit(ExprVisitor& nv) { nv.visit_node(*this); nv.visit(*this); } void ::HIR::ExprVisitorDef::visit(::HIR::nt& n) { code } diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 72bc2070..b15db07c 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -14,14 +14,17 @@ class ExprVisitor; class ExprNode { public: + Span m_span; ::HIR::TypeRef m_res_type; - const Span& span() const; + const Span& span() const { return m_span; } virtual void visit(ExprVisitor& v) = 0; - ExprNode() + ExprNode(Span sp): + m_span( mv$(sp) ) {} - ExprNode(::HIR::TypeRef ty): + ExprNode(Span sp, ::HIR::TypeRef ty): + m_span( mv$(sp) ), m_res_type( mv$(ty) ) {} virtual ~ExprNode(); @@ -39,10 +42,12 @@ struct ExprNode_Block: ::std::vector< ExprNodeP > m_nodes; ::std::vector< ::HIR::SimplePath> m_traits; - ExprNode_Block(): + ExprNode_Block(Span sp): + ExprNode(mv$(sp)), m_is_unsafe(false) {} - ExprNode_Block(bool is_unsafe, ::std::vector<ExprNodeP> nodes): + ExprNode_Block(Span sp, bool is_unsafe, ::std::vector<ExprNodeP> nodes): + ExprNode( mv$(sp) ), m_is_unsafe(is_unsafe), m_nodes( mv$(nodes) ) {} @@ -54,8 +59,8 @@ struct ExprNode_Return: { ::HIR::ExprNodeP m_value; - ExprNode_Return(::HIR::ExprNodeP value): - ExprNode(::HIR::TypeRef::Data::make_Diverge({})), + ExprNode_Return(Span sp, ::HIR::ExprNodeP value): + ExprNode(mv$(sp), ::HIR::TypeRef::new_diverge()), m_value( mv$(value) ) { } @@ -68,8 +73,8 @@ struct ExprNode_Loop: ::std::string m_label; ::HIR::ExprNodeP m_code; - ExprNode_Loop(::std::string label, ::HIR::ExprNodeP code): - ExprNode(::HIR::TypeRef(TypeRef::TagUnit{})), + ExprNode_Loop(Span sp, ::std::string label, ::HIR::ExprNodeP code): + ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()), m_label( mv$(label) ), m_code( mv$(code) ) {} @@ -83,8 +88,8 @@ struct ExprNode_LoopControl: bool m_continue; //::HIR::ExprNodeP m_value; - ExprNode_LoopControl(::std::string label, bool cont): - ExprNode(::HIR::TypeRef::Data::make_Diverge({})), + ExprNode_LoopControl(Span sp, ::std::string label, bool cont): + ExprNode(mv$(sp), ::HIR::TypeRef::new_diverge()), m_label( mv$(label) ), m_continue( cont ) {} @@ -98,8 +103,8 @@ struct ExprNode_Let: ::HIR::TypeRef m_type; ::HIR::ExprNodeP m_value; - ExprNode_Let(::HIR::Pattern pat, ::HIR::TypeRef ty, ::HIR::ExprNodeP val): - ExprNode(::HIR::TypeRef(TypeRef::TagUnit{})), + ExprNode_Let(Span sp, ::HIR::Pattern pat, ::HIR::TypeRef ty, ::HIR::ExprNodeP val): + ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()), m_pattern( mv$(pat) ), m_type( mv$(ty) ), m_value( mv$(val) ) @@ -121,7 +126,8 @@ struct ExprNode_Match: ::HIR::ExprNodeP m_value; ::std::vector<Arm> m_arms; - ExprNode_Match(::HIR::ExprNodeP val, ::std::vector<Arm> arms): + ExprNode_Match(Span sp, ::HIR::ExprNodeP val, ::std::vector<Arm> arms): + ExprNode( mv$(sp) ), m_value( mv$(val) ), m_arms( mv$(arms) ) {} @@ -136,7 +142,8 @@ struct ExprNode_If: ::HIR::ExprNodeP m_true; ::HIR::ExprNodeP m_false; - ExprNode_If(::HIR::ExprNodeP cond, ::HIR::ExprNodeP true_code, ::HIR::ExprNodeP false_code): + ExprNode_If(Span sp, ::HIR::ExprNodeP cond, ::HIR::ExprNodeP true_code, ::HIR::ExprNodeP false_code): + ExprNode( mv$(sp) ), m_cond( mv$(cond) ), m_true( mv$(true_code) ), m_false( mv$(false_code) ) @@ -160,8 +167,8 @@ struct ExprNode_Assign: ExprNodeP m_slot; ExprNodeP m_value; - ExprNode_Assign(Op op, ::HIR::ExprNodeP slot, ::HIR::ExprNodeP value): - ExprNode(::HIR::TypeRef(TypeRef::TagUnit{})), + ExprNode_Assign(Span sp, Op op, ::HIR::ExprNodeP slot, ::HIR::ExprNodeP value): + ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()), m_op(op), m_slot( mv$(slot) ), m_value( mv$(value) ) @@ -193,8 +200,8 @@ struct ExprNode_BinOp: ::HIR::ExprNodeP m_left; ::HIR::ExprNodeP m_right; - ExprNode_BinOp() {} - ExprNode_BinOp(Op op, ::HIR::ExprNodeP left, ::HIR::ExprNodeP right): + ExprNode_BinOp(Span sp, Op op, ::HIR::ExprNodeP left, ::HIR::ExprNodeP right): + ExprNode( mv$(sp) ), m_op(op), m_left( mv$(left) ), m_right( mv$(right) ) @@ -227,7 +234,8 @@ struct ExprNode_UniOp: Op m_op; ::HIR::ExprNodeP m_value; - ExprNode_UniOp(Op op, ::HIR::ExprNodeP value): + ExprNode_UniOp(Span sp, Op op, ::HIR::ExprNodeP value): + ExprNode( mv$(sp) ), m_op(op), m_value( mv$(value) ) {} @@ -239,8 +247,8 @@ struct ExprNode_Cast: { ::HIR::ExprNodeP m_value; - ExprNode_Cast(::HIR::ExprNodeP value, ::HIR::TypeRef dst_type): - ExprNode( mv$(dst_type) ), + ExprNode_Cast(Span sp, ::HIR::ExprNodeP value, ::HIR::TypeRef dst_type): + ExprNode( mv$(sp), mv$(dst_type) ), m_value( mv$(value) ) {} @@ -251,8 +259,8 @@ struct ExprNode_Unsize: { ::HIR::ExprNodeP m_value; - ExprNode_Unsize(::HIR::ExprNodeP value, ::HIR::TypeRef dst_type): - ExprNode( mv$(dst_type) ), + ExprNode_Unsize(Span sp, ::HIR::ExprNodeP value, ::HIR::TypeRef dst_type): + ExprNode( mv$(sp), mv$(dst_type) ), m_value( mv$(value) ) {} @@ -264,7 +272,8 @@ struct ExprNode_Index: ::HIR::ExprNodeP m_val; ::HIR::ExprNodeP m_index; - ExprNode_Index(::HIR::ExprNodeP val, ::HIR::ExprNodeP index): + ExprNode_Index(Span sp, ::HIR::ExprNodeP val, ::HIR::ExprNodeP index): + ExprNode(mv$(sp)), m_val( mv$(val) ), m_index( mv$(index) ) {} @@ -276,7 +285,8 @@ struct ExprNode_Deref: { ::HIR::ExprNodeP m_val; - ExprNode_Deref(::HIR::ExprNodeP val): + ExprNode_Deref(Span sp, ::HIR::ExprNodeP val): + ExprNode(mv$(sp)), m_val( mv$(val) ) {} @@ -289,7 +299,8 @@ struct ExprNode_CallPath: ::HIR::Path m_path; ::std::vector<ExprNodeP> m_args; - ExprNode_CallPath(::HIR::Path path, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode_CallPath(Span sp, ::HIR::Path path, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode(mv$(sp)), m_path( mv$(path) ), m_args( mv$(args) ) {} @@ -302,7 +313,8 @@ struct ExprNode_CallValue: ::HIR::ExprNodeP m_val; ::std::vector<ExprNodeP> m_args; - ExprNode_CallValue(::HIR::ExprNodeP val, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode_CallValue(Span sp, ::HIR::ExprNodeP val, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode(mv$(sp)), m_val( mv$(val) ), m_args( mv$(args) ) {} @@ -317,8 +329,8 @@ struct ExprNode_CallMethod: ::HIR::PathParams m_params; ::std::vector< ::HIR::ExprNodeP> m_args; - ExprNode_CallMethod() {} - ExprNode_CallMethod(::HIR::ExprNodeP val, ::std::string method_name, ::HIR::PathParams params, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode_CallMethod(Span sp, ::HIR::ExprNodeP val, ::std::string method_name, ::HIR::PathParams params, ::std::vector< ::HIR::ExprNodeP> args): + ExprNode( mv$(sp) ), m_val( mv$(val) ), m_method( mv$(method_name) ), m_params( mv$(params) ), @@ -334,7 +346,8 @@ struct ExprNode_Field: ::HIR::ExprNodeP m_val; ::std::string m_field; - ExprNode_Field(::HIR::ExprNodeP val, ::std::string field): + ExprNode_Field(Span sp, ::HIR::ExprNodeP val, ::std::string field): + ExprNode(mv$(sp)), m_val( mv$(val) ), m_field( mv$(field) ) {} @@ -361,7 +374,8 @@ struct ExprNode_Literal: Data m_data; - ExprNode_Literal(Data data): + ExprNode_Literal(Span sp, Data data): + ExprNode( mv$(sp) ), m_data( mv$(data) ) { TU_MATCH(Data, (m_data), (e), @@ -404,7 +418,8 @@ struct ExprNode_PathValue: { ::HIR::Path m_path; - ExprNode_PathValue(::HIR::Path path): + ExprNode_PathValue(Span sp, ::HIR::Path path): + ExprNode(mv$(sp)), m_path( mv$(path) ) {} @@ -416,7 +431,8 @@ struct ExprNode_Variable: ::std::string m_name; unsigned int m_slot; - ExprNode_Variable(::std::string name, unsigned int slot): + ExprNode_Variable(Span sp, ::std::string name, unsigned int slot): + ExprNode(mv$(sp)), m_name( mv$(name) ), m_slot( slot ) {} @@ -433,12 +449,13 @@ struct ExprNode_StructLiteral: ::HIR::ExprNodeP m_base_value; t_values m_values; - ExprNode_StructLiteral(::HIR::GenericPath path, ::HIR::ExprNodeP base_value, t_values values): + ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, ::HIR::ExprNodeP base_value, t_values values): + ExprNode( mv$(sp) ), m_path( mv$(path) ), m_base_value( mv$(base_value) ), m_values( mv$(values) ) { - // TODO: set m_res_type based on path + // TODO: set m_res_type based on path? } NODE_METHODS(); @@ -448,7 +465,8 @@ struct ExprNode_Tuple: { ::std::vector< ::HIR::ExprNodeP> m_vals; - ExprNode_Tuple(::std::vector< ::HIR::ExprNodeP> vals): + ExprNode_Tuple(Span sp, ::std::vector< ::HIR::ExprNodeP> vals): + ExprNode(mv$(sp)), m_vals( mv$(vals) ) {} @@ -459,8 +477,8 @@ struct ExprNode_ArrayList: { ::std::vector< ::HIR::ExprNodeP> m_vals; - ExprNode_ArrayList(::std::vector< ::HIR::ExprNodeP> vals): - ExprNode( ::HIR::TypeRef::Data::make_Array({ + ExprNode_ArrayList(Span sp, ::std::vector< ::HIR::ExprNodeP> vals): + ExprNode( mv$(sp), ::HIR::TypeRef::Data::make_Array({ box$( ::HIR::TypeRef() ), ::HIR::ExprPtr(), vals.size() @@ -477,7 +495,8 @@ struct ExprNode_ArraySized: ::HIR::ExprNodeP m_size; // TODO: Has to be constant size_t m_size_val; - ExprNode_ArraySized(::HIR::ExprNodeP val, ::HIR::ExprNodeP size): + ExprNode_ArraySized(Span sp, ::HIR::ExprNodeP val, ::HIR::ExprNodeP size): + ExprNode(mv$(sp)), m_val( mv$(val) ), m_size( mv$(size) ), m_size_val( ~0u ) @@ -495,7 +514,8 @@ struct ExprNode_Closure: ::HIR::TypeRef m_return; ::HIR::ExprNodeP m_code; - ExprNode_Closure(args_t args, ::HIR::TypeRef rv, ::HIR::ExprNodeP code): + ExprNode_Closure(Span sp, args_t args, ::HIR::TypeRef rv, ::HIR::ExprNodeP code): + ExprNode(mv$(sp)), m_args( ::std::move(args) ), m_return( ::std::move(rv) ), m_code( ::std::move(code) ) diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 7d755d63..0329f3fa 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -384,18 +384,25 @@ throw "BUG: Encountered non-Absolute path when creating ::HIR::GenericPath"; } } +::HIR::PathParams LowerHIR_PathParams(const Span& sp, const ::AST::PathParams& src_params) +{ + ::HIR::PathParams params; + + // TODO: Lifetime params (not encoded in ::HIR::PathNode as yet) + //for(const auto& param : src_params.m_lifetimes) { + //} + + for(const auto& param : src_params.m_types) { + params.m_types.push_back( LowerHIR_Type(param) ); + } + + return params; +} ::HIR::GenericPath LowerHIR_GenericPath(const Span& sp, const ::AST::Path& path) { TU_IFLET(::AST::Path::Class, path.m_class, Absolute, e, auto simpepath = LowerHIR_SimplePath(sp, path, true); - ::HIR::PathParams params; - const auto& src_params = e.nodes.back().args(); - //for(const auto& param : src_params.m_lifetimes) { - //} - for(const auto& param : src_params.m_types) { - params.m_types.push_back( LowerHIR_Type(param) ); - } - // TODO: Lifetime params (not encoded in AST::PathNode as yet) + ::HIR::PathParams params = LowerHIR_PathParams(sp, e.nodes.back().args()); auto rv = ::HIR::GenericPath(mv$(simpepath), mv$(params)); DEBUG(path << " => " << rv); return rv; @@ -428,12 +435,17 @@ (UFCS, if( e.nodes.size() != 1 ) TODO(sp, "Handle UFCS with multiple nodes - " << path); + auto params = LowerHIR_PathParams(sp, e.nodes.front().args()); if( ! e.trait ) { + auto type = box$( LowerHIR_Type(*e.type) ); + if( type->m_data.is_Generic() ) { + BUG(sp, "Generics can't be used with UfcsInherent - " << path); + } return ::HIR::Path(::HIR::Path::Data::make_UfcsInherent({ - box$( LowerHIR_Type(*e.type) ), + mv$(type), e.nodes[0].name(), - {} + mv$(params) })); } else if( ! e.trait->is_valid() ) @@ -441,7 +453,7 @@ return ::HIR::Path(::HIR::Path::Data::make_UfcsUnknown({ box$( LowerHIR_Type(*e.type) ), e.nodes[0].name(), - {} + mv$(params) })); } else @@ -450,7 +462,7 @@ box$(LowerHIR_Type(*e.type)), LowerHIR_GenericPath(sp, *e.trait), e.nodes[0].name(), - {} + mv$(params) })); } ) diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index c48a6ee9..40f27d5a 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -22,14 +22,14 @@ struct LowerHIR_ExprNode_Visitor: ::std::unique_ptr< ::HIR::ExprNode> m_rv; virtual void visit(::AST::ExprNode_Block& v) override { - auto rv = new ::HIR::ExprNode_Block(); + 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 { - rv->m_nodes.push_back( ::HIR::ExprNodeP( new ::HIR::ExprNode_Tuple({}) ) ); + rv->m_nodes.push_back( ::HIR::ExprNodeP( new ::HIR::ExprNode_Tuple(Span(), {}) ) ); } } @@ -48,20 +48,20 @@ struct LowerHIR_ExprNode_Visitor: { case ::AST::ExprNode_Flow::RETURN: if( v.m_value ) - m_rv.reset( new ::HIR::ExprNode_Return( LowerHIR_ExprNode_Inner(*v.m_value) ) ); + m_rv.reset( new ::HIR::ExprNode_Return( v.span(), LowerHIR_ExprNode_Inner(*v.m_value) ) ); else - m_rv.reset( new ::HIR::ExprNode_Return( ::HIR::ExprNodeP(new ::HIR::ExprNode_Tuple({})) ) ); + m_rv.reset( new ::HIR::ExprNode_Return( v.span(), ::HIR::ExprNodeP(new ::HIR::ExprNode_Tuple(v.span(), {})) ) ); break; case ::AST::ExprNode_Flow::CONTINUE: case ::AST::ExprNode_Flow::BREAK: if( v.m_value ) TODO(v.get_pos(), "Handle break/continue values in HIR"); - m_rv.reset( new ::HIR::ExprNode_LoopControl( v.m_target, (v.m_type == ::AST::ExprNode_Flow::CONTINUE) ) ); + m_rv.reset( new ::HIR::ExprNode_LoopControl( v.span(), v.m_target, (v.m_type == ::AST::ExprNode_Flow::CONTINUE) ) ); break; } } virtual void visit(::AST::ExprNode_LetBinding& v) override { - m_rv.reset( new ::HIR::ExprNode_Let( + m_rv.reset( new ::HIR::ExprNode_Let( v.span(), LowerHIR_Pattern( v.m_pat ), LowerHIR_Type( v.m_type ), LowerHIR_ExprNode_Inner_Opt( v.m_value.get() ) @@ -90,7 +90,7 @@ struct LowerHIR_ExprNode_Visitor: throw ""; } }; - m_rv.reset( new ::HIR::ExprNode_Assign( + m_rv.reset( new ::HIR::ExprNode_Assign( v.span(), H::get_op(v.m_op), LowerHIR_ExprNode_Inner( *v.m_slot ), LowerHIR_ExprNode_Inner( *v.m_value ) @@ -115,18 +115,18 @@ struct LowerHIR_ExprNode_Visitor: if( v.m_left ) { if( v.m_right ) { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(mv$(path_Range), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_Range), nullptr, mv$(values)) ); } else { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(mv$(path_RangeFrom), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeFrom), nullptr, mv$(values)) ); } } else { if( v.m_right ) { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(mv$(path_RangeTo), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeTo), nullptr, mv$(values)) ); } else { - m_rv.reset( new ::HIR::ExprNode_PathValue(mv$(path_RangeFull)) ); + m_rv.reset( new ::HIR::ExprNode_PathValue(v.span(), mv$(path_RangeFull)) ); } } break; } @@ -140,13 +140,13 @@ struct LowerHIR_ExprNode_Visitor: ::HIR::ExprNode_StructLiteral::t_values values; values.push_back( ::std::make_pair( ::std::string("start"), LowerHIR_ExprNode_Inner( *v.m_left ) ) ); values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral(mv$(path_RangeInclusive_NonEmpty), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeInclusive_NonEmpty), nullptr, mv$(values)) ); } else { ::HIR::ExprNode_StructLiteral::t_values values; values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral(mv$(path_RangeToInclusive), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeToInclusive), nullptr, mv$(values)) ); } break; } case ::AST::ExprNode_BinOp::PLACE_IN: @@ -173,7 +173,7 @@ struct LowerHIR_ExprNode_Visitor: case ::AST::ExprNode_BinOp::SHR: op = ::HIR::ExprNode_BinOp::Op::Shr; if(0) case ::AST::ExprNode_BinOp::SHL: op = ::HIR::ExprNode_BinOp::Op::Shl; - m_rv.reset( new ::HIR::ExprNode_BinOp( + m_rv.reset( new ::HIR::ExprNode_BinOp( v.span(), op, LowerHIR_ExprNode_Inner( *v.m_left ), LowerHIR_ExprNode_Inner( *v.m_right ) @@ -197,7 +197,7 @@ struct LowerHIR_ExprNode_Visitor: case ::AST::ExprNode_UniOp::REFMUT: op = ::HIR::ExprNode_UniOp::Op::RefMut; if(0) case ::AST::ExprNode_UniOp::INVERT: op = ::HIR::ExprNode_UniOp::Op::Invert; if(0) case ::AST::ExprNode_UniOp::NEGATE: op = ::HIR::ExprNode_UniOp::Op::Negate; - m_rv.reset( new ::HIR::ExprNode_UniOp( + m_rv.reset( new ::HIR::ExprNode_UniOp( v.span(), op, LowerHIR_ExprNode_Inner( *v.m_value ) ) ); @@ -205,7 +205,7 @@ struct LowerHIR_ExprNode_Visitor: } } virtual void visit(::AST::ExprNode_Cast & v) override { - m_rv.reset( new ::HIR::ExprNode_Cast( + m_rv.reset( new ::HIR::ExprNode_Cast( v.span(), LowerHIR_ExprNode_Inner( *v.m_value ), LowerHIR_Type(v.m_type) ) ); @@ -217,14 +217,14 @@ struct LowerHIR_ExprNode_Visitor: args.push_back( LowerHIR_ExprNode_Inner(*arg) ); TU_IFLET(::AST::Path::Class, v.m_path.m_class, Local, e, - m_rv.reset( new ::HIR::ExprNode_CallValue( - ::HIR::ExprNodeP(new ::HIR::ExprNode_Variable( e.name, v.m_path.binding().as_Variable().slot )), + m_rv.reset( new ::HIR::ExprNode_CallValue( v.span(), + ::HIR::ExprNodeP(new ::HIR::ExprNode_Variable( v.span(), e.name, v.m_path.binding().as_Variable().slot )), mv$(args) ) ); ) else { - m_rv.reset( new ::HIR::ExprNode_CallPath( + m_rv.reset( new ::HIR::ExprNode_CallPath( v.span(), LowerHIR_Path(Span(v.get_pos()), v.m_path), mv$( args ) ) ); @@ -240,7 +240,7 @@ struct LowerHIR_ExprNode_Visitor: for(const auto& param : v.m_method.args().m_types) params.m_types.push_back( LowerHIR_Type(param) ); - m_rv.reset( new ::HIR::ExprNode_CallMethod( + m_rv.reset( new ::HIR::ExprNode_CallMethod( v.span(), LowerHIR_ExprNode_Inner(*v.m_val), v.m_method.name(), mv$(params), @@ -252,7 +252,7 @@ struct LowerHIR_ExprNode_Visitor: for(const auto& arg : v.m_args) args.push_back( LowerHIR_ExprNode_Inner(*arg) ); - m_rv.reset( new ::HIR::ExprNode_CallValue( + m_rv.reset( new ::HIR::ExprNode_CallValue( v.span(), LowerHIR_ExprNode_Inner(*v.m_val), mv$(args) ) ); @@ -261,7 +261,7 @@ struct LowerHIR_ExprNode_Visitor: switch( v.m_type ) { case ::AST::ExprNode_Loop::LOOP: - m_rv.reset( new ::HIR::ExprNode_Loop( + m_rv.reset( new ::HIR::ExprNode_Loop( v.span(), v.m_label, LowerHIR_ExprNode_Inner(*v.m_code) ) ); @@ -270,16 +270,16 @@ struct LowerHIR_ExprNode_Visitor: case ::AST::ExprNode_Loop::WHILE: { ::std::vector< ::HIR::ExprNodeP> code; // - if `m_cond` { () } else { break `m_label` } - code.push_back( ::HIR::ExprNodeP(new ::HIR::ExprNode_If( + code.push_back( ::HIR::ExprNodeP(new ::HIR::ExprNode_If( v.span(), LowerHIR_ExprNode_Inner(*v.m_cond), - ::HIR::ExprNodeP( new ::HIR::ExprNode_Tuple({}) ), - ::HIR::ExprNodeP( new ::HIR::ExprNode_LoopControl(v.m_label, false) ) + ::HIR::ExprNodeP( new ::HIR::ExprNode_Tuple(v.span(), {}) ), + ::HIR::ExprNodeP( new ::HIR::ExprNode_LoopControl(v.span(), v.m_label, false) ) )) ); code.push_back( LowerHIR_ExprNode_Inner(*v.m_code) ); - m_rv.reset( new ::HIR::ExprNode_Loop( + m_rv.reset( new ::HIR::ExprNode_Loop( v.span(), v.m_label, - ::HIR::ExprNodeP(new ::HIR::ExprNode_Block(false, mv$(code))) + ::HIR::ExprNodeP(new ::HIR::ExprNode_Block( v.span(), false, mv$(code))) ) ); assert( m_rv->m_res_type.m_data.is_Tuple() ); break; } @@ -296,12 +296,12 @@ struct LowerHIR_ExprNode_Visitor: arms.push_back(::HIR::ExprNode_Match::Arm { ::make_vec1( ::HIR::Pattern() ), ::HIR::ExprNodeP(), - ::HIR::ExprNodeP( new ::HIR::ExprNode_LoopControl(v.m_label, false) ) + ::HIR::ExprNodeP( new ::HIR::ExprNode_LoopControl( v.span(), v.m_label, false) ) }); - m_rv.reset( new ::HIR::ExprNode_Loop( + m_rv.reset( new ::HIR::ExprNode_Loop( v.span(), v.m_label, - ::HIR::ExprNodeP(new ::HIR::ExprNode_Match( + ::HIR::ExprNodeP(new ::HIR::ExprNode_Match( v.span(), LowerHIR_ExprNode_Inner(*v.m_cond), mv$(arms) )) @@ -385,13 +385,13 @@ struct LowerHIR_ExprNode_Visitor: arms.push_back( mv$(new_arm) ); } - m_rv.reset( new ::HIR::ExprNode_Match( + m_rv.reset( new ::HIR::ExprNode_Match( v.span(), LowerHIR_ExprNode_Inner(*v.m_val), mv$(arms) )); } virtual void visit(::AST::ExprNode_If& v) override { - m_rv.reset( new ::HIR::ExprNode_If( + m_rv.reset( new ::HIR::ExprNode_If( v.span(), LowerHIR_ExprNode_Inner(*v.m_cond), LowerHIR_ExprNode_Inner(*v.m_true), LowerHIR_ExprNode_Inner_Opt(&*v.m_false) @@ -410,9 +410,9 @@ struct LowerHIR_ExprNode_Visitor: arms.push_back(::HIR::ExprNode_Match::Arm { ::make_vec1( ::HIR::Pattern() ), ::HIR::ExprNodeP(), - v.m_false ? LowerHIR_ExprNode_Inner(*v.m_false) : ::HIR::ExprNodeP( new ::HIR::ExprNode_Tuple({}) ) + v.m_false ? LowerHIR_ExprNode_Inner(*v.m_false) : ::HIR::ExprNodeP(new ::HIR::ExprNode_Tuple(v.span(), {})) }); - m_rv.reset( new ::HIR::ExprNode_Match( + m_rv.reset( new ::HIR::ExprNode_Match( v.span(), LowerHIR_ExprNode_Inner(*v.m_value), mv$(arms) )); @@ -444,7 +444,7 @@ struct LowerHIR_ExprNode_Visitor: } } }; - m_rv.reset( new ::HIR::ExprNode_Literal( + m_rv.reset( new ::HIR::ExprNode_Literal( v.span(), ::HIR::ExprNode_Literal::Data::make_Integer({ H::get_type( Span(v.get_pos()), v.m_datatype ), v.m_value @@ -461,19 +461,19 @@ struct LowerHIR_ExprNode_Visitor: default: BUG(v.get_pos(), "Unknown type for float literal"); } - m_rv.reset( new ::HIR::ExprNode_Literal( ::HIR::ExprNode_Literal::Data::make_Float({ - ct, v.m_value - }) ) ); + m_rv.reset( new ::HIR::ExprNode_Literal( v.span(), + ::HIR::ExprNode_Literal::Data::make_Float({ ct, v.m_value }) + ) ); } virtual void visit(::AST::ExprNode_Bool& v) override { - m_rv.reset( new ::HIR::ExprNode_Literal( ::HIR::ExprNode_Literal::Data::make_Boolean( v.m_value ) ) ); + m_rv.reset( new ::HIR::ExprNode_Literal( v.span(), ::HIR::ExprNode_Literal::Data::make_Boolean( v.m_value ) ) ); } virtual void visit(::AST::ExprNode_String& v) override { - m_rv.reset( new ::HIR::ExprNode_Literal( ::HIR::ExprNode_Literal::Data::make_String( v.m_value ) ) ); + m_rv.reset( new ::HIR::ExprNode_Literal( v.span(), ::HIR::ExprNode_Literal::Data::make_String( v.m_value ) ) ); } virtual void visit(::AST::ExprNode_ByteString& v) override { ::std::vector<char> dat { v.m_value.begin(), v.m_value.end() }; - m_rv.reset( new ::HIR::ExprNode_Literal( ::HIR::ExprNode_Literal::Data::make_ByteString( mv$(dat) ) ) ); + m_rv.reset( new ::HIR::ExprNode_Literal( v.span(), ::HIR::ExprNode_Literal::Data::make_ByteString( mv$(dat) ) ) ); } virtual void visit(::AST::ExprNode_Closure& v) override { ::HIR::ExprNode_Closure::args_t args; @@ -483,7 +483,7 @@ struct LowerHIR_ExprNode_Visitor: LowerHIR_Type( arg.second ) ) ); } - m_rv.reset( new ::HIR::ExprNode_Closure( + m_rv.reset( new ::HIR::ExprNode_Closure( v.span(), mv$(args), LowerHIR_Type(v.m_return), LowerHIR_ExprNode_Inner(*v.m_code) @@ -493,7 +493,7 @@ struct LowerHIR_ExprNode_Visitor: ::HIR::ExprNode_StructLiteral::t_values values; for(const auto& val : v.m_values) values.push_back( ::std::make_pair(val.first, LowerHIR_ExprNode_Inner(*val.second)) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral( + m_rv.reset( new ::HIR::ExprNode_StructLiteral( v.span(), LowerHIR_GenericPath(v.get_pos(), v.m_path), LowerHIR_ExprNode_Inner_Opt(v.m_base_value.get()), mv$(values) @@ -502,7 +502,7 @@ struct LowerHIR_ExprNode_Visitor: virtual void visit(::AST::ExprNode_Array& v) override { if( v.m_size ) { - m_rv.reset( new ::HIR::ExprNode_ArraySized( + m_rv.reset( new ::HIR::ExprNode_ArraySized( v.span(), LowerHIR_ExprNode_Inner( *v.m_values.at(0) ), // TODO: Should this size be a full expression on its own? LowerHIR_ExprNode_Inner( *v.m_size ) @@ -513,14 +513,14 @@ struct LowerHIR_ExprNode_Visitor: ::std::vector< ::HIR::ExprNodeP> vals; for(const auto& val : v.m_values) vals.push_back( LowerHIR_ExprNode_Inner(*val) ); - m_rv.reset( new ::HIR::ExprNode_ArrayList( mv$(vals) ) ); + m_rv.reset( new ::HIR::ExprNode_ArrayList( v.span(), mv$(vals) ) ); } } virtual void visit(::AST::ExprNode_Tuple& v) override { ::std::vector< ::HIR::ExprNodeP> vals; for(const auto& val : v.m_values) vals.push_back( LowerHIR_ExprNode_Inner(*val ) ); - m_rv.reset( new ::HIR::ExprNode_Tuple( mv$(vals) ) ); + m_rv.reset( new ::HIR::ExprNode_Tuple( v.span(), mv$(vals) ) ); } virtual void visit(::AST::ExprNode_NamedValue& v) override { TU_IFLET(::AST::Path::Class, v.m_path.m_class, Local, e, @@ -528,27 +528,27 @@ struct LowerHIR_ExprNode_Visitor: BUG(v.get_pos(), "Named value was a local, but wasn't bound - " << v.m_path); } auto slot = v.m_path.binding().as_Variable().slot; - m_rv.reset( new ::HIR::ExprNode_Variable( e.name, slot ) ); + m_rv.reset( new ::HIR::ExprNode_Variable( v.span(), e.name, slot ) ); ) else { - m_rv.reset( new ::HIR::ExprNode_PathValue( LowerHIR_Path(Span(v.get_pos()), v.m_path) ) ); + m_rv.reset( new ::HIR::ExprNode_PathValue( v.span(), LowerHIR_Path(Span(v.get_pos()), v.m_path) ) ); } } virtual void visit(::AST::ExprNode_Field& v) override { - m_rv.reset( new ::HIR::ExprNode_Field( + m_rv.reset( new ::HIR::ExprNode_Field( v.span(), LowerHIR_ExprNode_Inner(*v.m_obj), v.m_name )); } virtual void visit(::AST::ExprNode_Index& v) override { - m_rv.reset( new ::HIR::ExprNode_Index( + m_rv.reset( new ::HIR::ExprNode_Index( v.span(), LowerHIR_ExprNode_Inner(*v.m_obj), LowerHIR_ExprNode_Inner(*v.m_idx) )); } virtual void visit(::AST::ExprNode_Deref& v) override { - m_rv.reset( new ::HIR::ExprNode_Deref( + m_rv.reset( new ::HIR::ExprNode_Deref( v.span(), LowerHIR_ExprNode_Inner(*v.m_value) )); } diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index 14b0233a..295de1b0 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -16,9 +16,16 @@ namespace { ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits; + const ::HIR::GenericParams* m_impl_params; + const ::HIR::GenericParams* m_item_params; + const ::HIR::Trait* m_current_trait; + public: Visitor(const ::HIR::Crate& crate): - m_crate(crate) + m_crate(crate), + m_impl_params(nullptr), + m_item_params(nullptr), + m_current_trait(nullptr) {} void visit_module(::HIR::Module& mod) override @@ -30,6 +37,18 @@ namespace { m_traits.pop_back(); } + void visit_function(::HIR::Function& fcn) override { + m_item_params = &fcn.m_params; + ::HIR::Visitor::visit_function(fcn); + m_item_params = nullptr; + } + void visit_trait(::HIR::Trait& trait) override { + m_current_trait = &trait; + m_impl_params = &trait.m_params; + ::HIR::Visitor::visit_trait(trait); + m_impl_params = nullptr; + m_current_trait = nullptr; + } void visit_expr(::HIR::ExprPtr& expr) override { @@ -91,86 +110,139 @@ namespace { } } + bool locate_trait_item_in_bounds(::HIR::Visitor::PathContext pc, const ::HIR::TypeRef& tr, const ::std::string& name, const ::HIR::GenericParams& params) { + DEBUG("TODO: Search for trait impl for " << tr << " with " << name << " in params"); + return false; + } + void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override { + DEBUG("p = " << p); TU_IFLET(::HIR::Path::Data, p.m_data, UfcsUnknown, e, DEBUG("UfcsUnknown - p=" << p); - // 1. Search all impls of in-scope traits for this method on this type - for( const auto& trait_info : m_traits ) - { - const auto& trait_path = *trait_info.first; - const auto& trait = *trait_info.second; - - switch( pc ) + + this->visit_type( *e.type ); + this->visit_path_params( e.params ); + + // TODO: Search for matching impls in current generic blocks + if( m_item_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, e.item, *m_item_params) ) { + return ; + } + if( m_impl_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, e.item, *m_impl_params) ) { + return ; + } + + TU_IFLET(::HIR::TypeRef::Data, e.type->m_data, Generic, te, + // If processing a trait, and the type is 'Self', search for the type/method on the trait + // - TODO: This could be encoded by a `Self: Trait` bound in the generics, but that may have knock-on issues? + if( te.name == "Self" && m_current_trait ) { + switch(pc) + { + case ::HIR::Visitor::PathContext::VALUE: { + auto it1 = m_current_trait->m_values.find( e.item ); + if( it1 != m_current_trait->m_values.end() ) { + TODO(Span(), "Found in Self trait - need path to trait"); + // TODO: What's the easiest way to get the path to this trait? + //auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} ); + //p.m_data = mv$(new_data); + //DEBUG("- Resolved, replace with " << p); + + return ; + } + } break; + case ::HIR::Visitor::PathContext::TRAIT: + break; + case ::HIR::Visitor::PathContext::TYPE: { + auto it1 = m_current_trait->m_types.find( e.item ); + if( it1 != m_current_trait->m_types.end() ) { + TODO(Span(), "Found in Self trait - need path to trait"); + return ; + } + } break; + } + } + ERROR(Span(), E0000, "Failed to find impl with '" << e.item << "' for " << *e.type); + return ; + ) + else { + // 1. Search all impls of in-scope traits for this method on this type + for( const auto& trait_info : m_traits ) { - case ::HIR::Visitor::PathContext::VALUE: { - auto it1 = trait.m_values.find( e.item ); - if( it1 == trait.m_values.end() ) { - continue ; + const auto& trait_path = *trait_info.first; + const auto& trait = *trait_info.second; + + switch( pc ) + { + case ::HIR::Visitor::PathContext::VALUE: { + auto it1 = trait.m_values.find( e.item ); + if( it1 == trait.m_values.end() ) { + continue ; + } + // Found it, just keep going (don't care about details here) + } break; + case ::HIR::Visitor::PathContext::TRAIT: + case ::HIR::Visitor::PathContext::TYPE: { + auto it1 = trait.m_types.find( e.item ); + if( it1 == trait.m_types.end() ) { + continue ; + } + // Found it, just keep going (don't care about details here) + } break; } - // Found it, just keep going (don't care about details here) - } break; - case ::HIR::Visitor::PathContext::TRAIT: - case ::HIR::Visitor::PathContext::TYPE: { - auto it1 = trait.m_types.find( e.item ); - if( it1 == trait.m_types.end() ) { + + auto trait_impl_it = m_crate.m_trait_impls.equal_range( trait_path ); + if( trait_impl_it.first == trait_impl_it.second ) { continue ; } - // Found it, just keep going (don't care about details here) - } break; - } - - auto trait_impl_it = m_crate.m_trait_impls.equal_range( trait_path ); - if( trait_impl_it.first == trait_impl_it.second ) { - continue ; + for( auto it = trait_impl_it.first; it != trait_impl_it.second; it ++ ) + { + const auto& impl = it->second; + if( !impl.matches_type(*e.type) ) { + continue ; + } + + auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} ); + p.m_data = mv$(new_data); + DEBUG("- Resolved, replace with " << p); + return ; + } } - for( auto it = trait_impl_it.first; it != trait_impl_it.second; it ++ ) + + // 2. No trait matched, search for inherent impl + for( const auto& impl : m_crate.m_type_impls ) { - const auto& impl = it->second; if( !impl.matches_type(*e.type) ) { continue ; } + DEBUG("- matched impl " << *e.type); + // TODO: Search for item + switch( pc ) + { + case ::HIR::Visitor::PathContext::VALUE: { + auto it1 = impl.m_methods.find( e.item ); + if( it1 == impl.m_methods.end() ) { + continue ; + } + // Found it, just keep going (don't care about details here) + } break; + case ::HIR::Visitor::PathContext::TRAIT: + case ::HIR::Visitor::PathContext::TYPE: + continue ; + } - auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} ); + auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} ); p.m_data = mv$(new_data); DEBUG("- Resolved, replace with " << p); return ; } } - // 2. No trait matched, search for inherent impl - for( const auto& impl : m_crate.m_type_impls ) - { - if( !impl.matches_type(*e.type) ) { - continue ; - } - DEBUG("- matched impl " << *e.type); - // TODO: Search for item - switch( pc ) - { - case ::HIR::Visitor::PathContext::VALUE: { - auto it1 = impl.m_methods.find( e.item ); - if( it1 == impl.m_methods.end() ) { - continue ; - } - // Found it, just keep going (don't care about details here) - } break; - case ::HIR::Visitor::PathContext::TRAIT: - case ::HIR::Visitor::PathContext::TYPE: { - continue ; - // Found it, just keep going (don't care about details here) - } break; - } - - auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} ); - p.m_data = mv$(new_data); - DEBUG("- Resolved, replace with " << p); - return ; - } - // Couldn't find it DEBUG("Failed to find impl with '" << e.item << "' for " << *e.type); ) + else { + ::HIR::Visitor::visit_path(p, pc); + } } diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 48a7a439..c2c2abb9 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -147,11 +147,27 @@ namespace { {} bool is_alias() const { return alias != ~0u; } }; + static const ::std::string EMPTY_STRING; + struct Variable + { + ::std::string name; + ::HIR::TypeRef type; + + Variable() + {} + Variable(const ::std::string& name, ::HIR::TypeRef type): + name( name ), + type( mv$(type) ) + {} + Variable(Variable&&) = default; + + Variable& operator=(Variable&&) = default; + }; class TypecheckContext { - ::std::vector< ::HIR::TypeRef> m_locals; - ::std::vector< IVar > m_ivars; + ::std::vector< Variable> m_locals; + ::std::vector< IVar> m_ivars; bool m_has_changed; public: TypecheckContext(): @@ -175,7 +191,7 @@ namespace { } i = 0; for(const auto& v : m_locals) { - DEBUG("VAR " << i << " = " << v); + DEBUG("VAR " << i << " '"<<v.name<<"' = " << v.type); i ++; } } @@ -190,20 +206,20 @@ namespace { } /// Adds a local variable binding (type is mutable so it can be inferred if required) - void add_local(unsigned int index, ::HIR::TypeRef type) + void add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type) { if( m_locals.size() <= index ) m_locals.resize(index+1); - m_locals[index] = mv$(type); + m_locals[index] = Variable(name, mv$(type)); } - const ::HIR::TypeRef& get_var_type(unsigned int index) + const ::HIR::TypeRef& get_var_type(const Span& sp, unsigned int index) { if( index >= m_locals.size() ) { this->dump(); - BUG(Span(), "Local index out of range " << index << " >= " << m_locals.size()); + BUG(sp, "Local index out of range " << index << " >= " << m_locals.size()); } - return m_locals.at(index); + return m_locals.at(index).type; } /// Add (and bind) all '_' types in `type` @@ -262,13 +278,13 @@ namespace { switch( pb.m_type ) { case ::HIR::PatternBinding::Type::Move: - this->add_local( pb.m_slot, mv$(type) ); + this->add_local( pb.m_slot, pb.m_name, mv$(type) ); break; case ::HIR::PatternBinding::Type::Ref: - this->add_local( pb.m_slot, ::HIR::TypeRef::Data::make_Borrow( {::HIR::BorrowType::Shared, box$(mv$(type))} ) ); + this->add_local( pb.m_slot, pb.m_name, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, mv$(type)) ); break; case ::HIR::PatternBinding::Type::MutRef: - this->add_local( pb.m_slot, ::HIR::TypeRef::Data::make_Borrow( {::HIR::BorrowType::Unique, box$(mv$(type))} ) ); + this->add_local( pb.m_slot, pb.m_name, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, mv$(type)) ); break; } } @@ -370,7 +386,7 @@ namespace { for(auto& sp : e.trailing) this->add_binding( sp, *te.inner ); if( e.extra_bind.is_valid() ) { - this->add_local( e.extra_bind.m_slot, type.clone() ); + this->add_local( e.extra_bind.m_slot, e.extra_bind.m_name, type.clone() ); } ) ) @@ -858,7 +874,21 @@ namespace { } ), (TraitObject, - TODO(sp, "Recurse in apply_equality TraitObject - " << l_t << " and " << r_t); + if( l_e.m_traits.size() != r_e.m_traits.size() ) { + // TODO: Possibly allow inferrence reducing the set? + ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t << " - trait counts differ"); + } + // NOTE: Lifetime is ignored + // TODO: Is this list sorted for consistency? + for(unsigned int i = 0; i < l_e.m_traits.size(); i ++ ) + { + auto& l_p = l_e.m_traits[i]; + auto& r_p = r_e.m_traits[i]; + if( l_p.m_path != r_p.m_path ) { + ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t); + } + // TODO: Equality of params + } ), (Array, this->apply_equality(sp, *l_e.inner, *r_e.inner); @@ -896,7 +926,8 @@ namespace { const auto& left_slice = l_e.inner->m_data.as_Slice(); TU_IFLET(::HIR::TypeRef::Data, r_e.inner->m_data, Array, right_array, this->apply_equality(sp, *left_slice.inner, *right_array.inner); - *node_ptr_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Unsize( mv$(*node_ptr_ptr), l_t.clone() )); + auto span = (**node_ptr_ptr).span(); + *node_ptr_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Unsize( mv$(span), mv$(*node_ptr_ptr), l_t.clone() )); (*node_ptr_ptr)->m_res_type = l_t.clone(); return ; ) @@ -1073,9 +1104,10 @@ namespace { void visit(::HIR::ExprNode_Match& node) override { - ::HIR::ExprVisitorDef::visit(node); TRACE_FUNCTION_F("match ..."); + this->context.add_ivars(node.m_value->m_res_type); + for(auto& arm : node.m_arms) { DEBUG("ARM " << arm.m_patterns); @@ -1084,19 +1116,28 @@ namespace { this->context.add_binding(pat, node.m_value->m_res_type); } } + + ::HIR::ExprVisitorDef::visit(node); } void visit(::HIR::ExprNode_Tuple& node) override { - // - Remove the ivar created by the generic visitor - this->context.dump(); - this->context.del_ivar( node.m_res_type.m_data.as_Infer().index ); + // Only delete and apply if the return type is an ivar + // - Can happen with `match (a, b)` + TU_IFLET(::HIR::TypeRef::Data, node.m_res_type.m_data, Infer, e, + // - Remove the ivar created by the generic visitor + this->context.dump(); + this->context.del_ivar( e.index ); + ) ::HIR::ExprVisitorDef::visit(node); - ::std::vector< ::HIR::TypeRef> types; - for( const auto& sn : node.m_vals ) - types.push_back( sn->m_res_type.clone() ); - node.m_res_type = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Tuple(mv$(types)) ); + if( node.m_res_type.m_data.is_Infer() ) + { + ::std::vector< ::HIR::TypeRef> types; + for( const auto& sn : node.m_vals ) + types.push_back( sn->m_res_type.clone() ); + node.m_res_type = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Tuple(mv$(types)) ); + } } void visit(::HIR::ExprNode_Closure& node) override { @@ -1112,8 +1153,10 @@ namespace { // - Variable: Bind to same ivar void visit(::HIR::ExprNode_Variable& node) override { - this->context.del_ivar( node.m_res_type.m_data.as_Infer().index ); - node.m_res_type = this->context.get_var_type(node.m_slot).clone(); + TU_IFLET(::HIR::TypeRef::Data, node.m_res_type.m_data, Infer, e, + this->context.del_ivar( e.index ); + ) + node.m_res_type = this->context.get_var_type(node.span(), node.m_slot).clone(); } }; @@ -1177,6 +1220,7 @@ namespace { // - Assign: both sides equal void visit(::HIR::ExprNode_Assign& node) override { + TRACE_FUNCTION_F("... = ..."); if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) { this->context.apply_equality(node.span(), node.m_slot->m_res_type, node.m_value->m_res_type, @@ -1242,8 +1286,9 @@ namespace { void visit(::HIR::ExprNode_Variable& node) override { // TODO: How to apply deref coercions here? + TRACE_FUNCTION_F("var #"<<node.m_slot<<" '"<<node.m_name<<"'"); this->context.apply_equality(node.span(), - node.m_res_type, this->context.get_var_type(node.m_slot) + node.m_res_type, this->context.get_var_type(node.span(), node.m_slot) ); } // - Struct literal: Semi-known types diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index 86d35ca7..95eef7fa 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -56,7 +56,7 @@ struct Context Context(const ::AST::Crate& crate, const ::AST::Module& mod): m_crate(crate), m_mod(mod), - m_var_count(0), + m_var_count(~0u), m_block_level(0), m_frozen_bind_set( false ) {} @@ -96,6 +96,28 @@ struct Context m_name_context.pop_back(); } + class RootBlockScope { + friend class Context; + Context& ctxt; + unsigned int old_varcount; + RootBlockScope(Context& ctxt, unsigned int val): + ctxt(ctxt), + old_varcount(ctxt.m_var_count) + { + ctxt.m_var_count = val; + } + public: + ~RootBlockScope() { + ctxt.m_var_count = old_varcount; + } + }; + RootBlockScope enter_rootblock() { + return RootBlockScope(*this, 0); + } + RootBlockScope clear_rootblock() { + return RootBlockScope(*this, ~0u); + } + void push_self(const TypeRef& tr) { m_name_context.push_back( Ent::make_ConcreteSelf(&tr) ); } @@ -131,6 +153,9 @@ struct Context m_block_level += 1; } unsigned int push_var(const Span& sp, const ::std::string& name) { + if( m_var_count == ~0u ) { + BUG(sp, "Assigning local when there's no variable context"); + } // TODO: Handle avoiding duplicate bindings in a pattern if( m_frozen_bind_set ) { @@ -155,6 +180,7 @@ struct Context } m_name_context.back().as_VarBlock().variables.push_back( Named<unsigned int> { name, m_var_count } ); m_var_count += 1; + assert( m_var_count >= m_name_context.back().as_VarBlock().variables.size() ); return m_var_count - 1; } } @@ -428,7 +454,7 @@ struct Context void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::LookupMode mode, ::AST::Path& path); void Resolve_Absolute_Type(Context& context, TypeRef& type); void Resolve_Absolute_Expr(Context& context, ::AST::Expr& expr); -void Resolve_Absolute_Expr(Context& context, ::AST::ExprNode& node); +void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node); void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pattern& pat); void Resolve_Absolute_Mod(const ::AST::Crate& crate, ::AST::Module& mod); void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod ); @@ -695,7 +721,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context:: if( e.nodes.size() > 1 ) { if( p.m_class.is_Local() ) { - p = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(sp, mv$(p)) ); + p = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(sp, mv$(p)), ::AST::Path() ); } if( ! e.nodes[0].args().is_empty() ) { @@ -830,8 +856,8 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type) (Array, Resolve_Absolute_Type(context, *e.inner); if( e.size ) { - // TODO: Prevent variables from being picked as the array size - Resolve_Absolute_Expr(context, *e.size); + auto _h = context.enter_rootblock(); + Resolve_Absolute_ExprNode(context, *e.size); } ), (Generic, @@ -871,15 +897,13 @@ void Resolve_Absolute_Expr(Context& context, ::AST::Expr& expr) { if( expr.is_valid() ) { - auto ov = context.m_var_count; - context.m_var_count = 0; - Resolve_Absolute_Expr(context, expr.node()); - context.m_var_count = ov; + Resolve_Absolute_ExprNode(context, expr.node()); } } -void Resolve_Absolute_Expr(Context& context, ::AST::ExprNode& node) +void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node) { TRACE_FUNCTION_F(""); + struct NV: public AST::NodeVisitorDef { @@ -893,6 +917,7 @@ void Resolve_Absolute_Expr(Context& context, ::AST::ExprNode& node) void visit(AST::ExprNode_Block& node) override { DEBUG("ExprNode_Block"); if( node.m_local_mod ) { + auto _h = context.clear_rootblock(); this->context.push( *node.m_local_mod ); // Clone just the module stack part of the current context @@ -1068,7 +1093,6 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa if( pat.binding().is_valid() ) { if( !pat.data().is_Any() && ! allow_refutable ) TODO(pat.span(), "Resolve_Absolute_Pattern - Encountered bound destructuring pattern"); - // TODO: Record the local variable number in the binding pat.binding().m_slot = context.push_var( pat.span(), pat.binding().m_name ); DEBUG("- Binding #" << pat.binding().m_slot << " '" << pat.binding().m_name << "'"); } @@ -1086,7 +1110,6 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa } else { pat = ::AST::Pattern(::AST::Pattern::TagBind(), mv$(name)); - // TODO: Record the local variable number in the binding pat.binding().m_slot = context.push_var( pat.span(), pat.binding().m_name ); DEBUG("- Binding #" << pat.binding().m_slot << " '" << pat.binding().m_name << "' (was MaybeBind)"); } @@ -1176,15 +1199,18 @@ void Resolve_Absolute_ImplItems(Context& item_context, ::AST::NamedList< ::AST: for(auto& arg : e.args()) Resolve_Absolute_Type( item_context, arg.second ); - item_context.push_block(); - for(auto& arg : e.args()) { - Resolve_Absolute_Pattern( item_context, false, arg.first ); + { + auto _h = item_context.enter_rootblock(); + item_context.push_block(); + for(auto& arg : e.args()) { + Resolve_Absolute_Pattern( item_context, false, arg.first ); + } + + Resolve_Absolute_Expr( item_context, e.code() ); + + item_context.pop_block(); } - Resolve_Absolute_Expr( item_context, e.code() ); - - item_context.pop_block(); - item_context.pop( e.params() ); ), (Static, @@ -1223,6 +1249,7 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod ) { TU_MATCH(::AST::EnumVariantData, (variant.m_data), (s), (Value, + auto _h = item_context.enter_rootblock(); Resolve_Absolute_Expr(item_context, s.m_value); ), (Tuple, @@ -1297,20 +1324,24 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod ) for(auto& arg : e.args()) Resolve_Absolute_Type( item_context, arg.second ); - item_context.push_block(); - for(auto& arg : e.args()) { - Resolve_Absolute_Pattern( item_context, false, arg.first ); + { + auto _h = item_context.enter_rootblock(); + item_context.push_block(); + for(auto& arg : e.args()) { + Resolve_Absolute_Pattern( item_context, false, arg.first ); + } + + Resolve_Absolute_Expr( item_context, e.code() ); + + item_context.pop_block(); } - Resolve_Absolute_Expr( item_context, e.code() ); - - item_context.pop_block(); - item_context.pop( e.params() ); ), (Static, DEBUG("Static - " << i.name); Resolve_Absolute_Type( item_context, e.type() ); + auto _h = item_context.enter_rootblock(); Resolve_Absolute_Expr( item_context, e.value() ); ) ) |