diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 18 | ||||
-rw-r--r-- | src/hir/hir.hpp | 12 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 4 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 249 | ||||
-rw-r--r-- | src/hir_typeck/expr.hpp | 14 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 9 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 241 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 244 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 18 |
10 files changed, 523 insertions, 288 deletions
@@ -50,7 +50,7 @@ OBJ += hir/crate_ptr.o hir/type_ptr.o hir/expr_ptr.o OBJ += hir/type.o hir/path.o hir/expr.o hir/pattern.o OBJ += hir/visitor.o OBJ += hir_conv/expand_type.o hir_conv/constant_evaluation.o hir_conv/resolve_ufcs.o hir_conv/bind.o -OBJ += hir_typeck/outer.o hir_typeck/expr.o hir_typeck/expr_context.o +OBJ += hir_typeck/outer.o hir_typeck/expr.o hir_typeck/expr_context.o hir_typeck/helpers.o OBJ += hir_typeck/expr_cs.o PCHS := ast/ast.hpp diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 8a9d25fc..5003e1f9 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -653,6 +653,14 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); }; } + +namespace { + template<typename T> + ::HIR::VisEnt<T> new_visent(bool pub, T v) { + return ::HIR::VisEnt<T> { pub, mv$(v) }; + } +} + ::HIR::Struct LowerHIR_Struct(const ::AST::Struct& ent) { ::HIR::Struct::Data data; @@ -674,7 +682,7 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); (Struct, ::HIR::Struct::Data::Data_Named fields; for(const auto& field : e.ents) - fields.push_back( ::std::make_pair( field.m_name, ::HIR::VisEnt< ::HIR::TypeRef> { field.m_is_public, LowerHIR_Type(field.m_type) } ) ); + fields.push_back( ::std::make_pair( field.m_name, new_visent(field.m_is_public, LowerHIR_Type(field.m_type)) ) ); data = ::HIR::Struct::Data::make_Named( mv$(fields) ); ) ) @@ -702,16 +710,16 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Unit({})) ); } else { - ::std::vector< ::HIR::TypeRef> types; + ::HIR::Enum::Variant::Data_Tuple types; for(const auto& st : e.m_sub_types) - types.push_back( LowerHIR_Type(st) ); + types.push_back( new_visent(true, LowerHIR_Type(st)) ); variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Tuple(mv$(types))) ); } ), (Struct, - ::std::vector< ::std::pair< ::std::string, ::HIR::TypeRef> > ents; + ::HIR::Enum::Variant::Data_Struct ents; for( const auto& ent : e.m_fields ) - ents.push_back( ::std::make_pair( ent.m_name, LowerHIR_Type(ent.m_type) ) ); + ents.push_back( ::std::make_pair( ent.m_name, new_visent(true, LowerHIR_Type(ent.m_type)) ) ); variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Struct(mv$(ents))) ); ) ) diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index e1163b49..22e32a11 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -95,14 +95,18 @@ struct TypeAlias GenericParams m_params; ::HIR::TypeRef m_type; }; + +typedef ::std::vector< VisEnt<::HIR::TypeRef> > t_tuple_fields; +typedef ::std::vector< ::std::pair< ::std::string, VisEnt<::HIR::TypeRef> > > t_struct_fields; + class Enum { public: TAGGED_UNION(Variant, Unit, (Unit, struct{}), (Value, ::HIR::ExprPtr), - (Tuple, ::std::vector<::HIR::TypeRef>), - (Struct, ::std::vector< ::std::pair< ::std::string, ::HIR::TypeRef> >) + (Tuple, t_tuple_fields), + (Struct, t_struct_fields) ); enum class Repr { @@ -127,8 +131,8 @@ public: }; TAGGED_UNION(Data, Unit, (Unit, struct {}), - (Tuple, ::std::vector< VisEnt<::HIR::TypeRef> >), - (Named, ::std::vector< ::std::pair< ::std::string, VisEnt<::HIR::TypeRef> > >) + (Tuple, t_tuple_fields), + (Named, t_struct_fields) ); GenericParams m_params; diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index cb168347..e903c25f 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -197,12 +197,12 @@ void ::HIR::Visitor::visit_enum(::HIR::PathChain p, ::HIR::Enum& item) ), (Tuple, for(auto& ty : v) { - this->visit_type(ty); + this->visit_type(ty.ent); } ), (Struct, for(auto& field : v) { - this->visit_type(field.second); + this->visit_type(field.second.ent); } ) ) diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 482249d4..b61144ac 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -5,252 +5,11 @@ #include <hir/hir.hpp> #include <hir/visitor.hpp> #include <algorithm> // std::find_if +#include "helpers.hpp" #include "expr.hpp" namespace typeck { - - bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); - - bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl) - { - for(const auto& ty : tpl.m_types) - if( monomorphise_type_needed(ty) ) - return true; - return false; - } - bool monomorphise_path_needed(const ::HIR::Path& tpl) - { - TU_MATCH(::HIR::Path::Data, (tpl.m_data), (e), - (Generic, - return monomorphise_pathparams_needed(e.m_params); - ), - (UfcsInherent, - return monomorphise_type_needed(*e.type) || monomorphise_pathparams_needed(e.params); - ), - (UfcsKnown, - return monomorphise_type_needed(*e.type) || monomorphise_pathparams_needed(e.trait.m_params) || monomorphise_pathparams_needed(e.params); - ), - (UfcsUnknown, - return monomorphise_type_needed(*e.type) || monomorphise_pathparams_needed(e.params); - ) - ) - throw ""; - } - bool monomorphise_traitpath_needed(const ::HIR::TraitPath& tpl) - { - if( monomorphise_pathparams_needed(tpl.m_path.m_params) ) return true; - for(const auto& assoc : tpl.m_type_bounds) - if( monomorphise_type_needed(assoc.second) ) - return true; - return false; - } - bool monomorphise_type_needed(const ::HIR::TypeRef& tpl) - { - TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e), - (Infer, - assert(!"ERROR: _ type found in monomorphisation target"); - ), - (Diverge, - return false; - ), - (Primitive, - return false; - ), - (Path, - return monomorphise_path_needed(e.path); - ), - (Generic, - return true; - ), - (TraitObject, - if( monomorphise_traitpath_needed(e.m_trait) ) - return true; - for(const auto& trait : e.m_markers) - if( monomorphise_pathparams_needed(trait.m_params) ) - return true; - return false; - ), - (Array, - return monomorphise_type_needed(*e.inner); - ), - (Slice, - return monomorphise_type_needed(*e.inner); - ), - (Tuple, - for(const auto& ty : e) { - if( monomorphise_type_needed(ty) ) - return true; - } - return false; - ), - (Borrow, - return monomorphise_type_needed(*e.inner); - ), - (Pointer, - return monomorphise_type_needed(*e.inner); - ), - (Function, - for(const auto& ty : e.m_arg_types) { - if( monomorphise_type_needed(ty) ) - return true; - } - return monomorphise_type_needed(*e.m_rettype); - ), - (Closure, - for(const auto& ty : e.m_arg_types) { - if( monomorphise_type_needed(ty) ) - return true; - } - return monomorphise_type_needed(*e.m_rettype); - ) - ) - throw ""; - } - - ::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer) - { - ::HIR::PathParams rv; - for( const auto& ty : tpl.m_types) - rv.m_types.push_back( monomorphise_type_with(sp, ty, callback) ); - return rv; - } - ::HIR::GenericPath monomorphise_genericpath_with(const Span& sp, const ::HIR::GenericPath& tpl, t_cb_generic callback, bool allow_infer) - { - return ::HIR::GenericPath( tpl.m_path, monomorphise_path_params_with(sp, tpl.m_params, callback, allow_infer) ); - } - ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer) - { - ::HIR::TraitPath rv { - monomorphise_genericpath_with(sp, tpl.m_path, callback, allow_infer), - tpl.m_hrls, - {}, - tpl.m_trait_ptr - }; - - for(const auto& assoc : tpl.m_type_bounds) - rv.m_type_bounds.insert(::std::make_pair( assoc.first, monomorphise_type_with(sp, assoc.second, callback, allow_infer) )); - - return rv; - } - ::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer) - { - ::HIR::TypeRef rv; - TRACE_FUNCTION_FR("tpl = " << tpl, rv); - TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e), - (Infer, - if( allow_infer ) { - rv = ::HIR::TypeRef(e); - } - else { - BUG(sp, "_ type found in monomorphisation target"); - } - ), - (Diverge, - rv = ::HIR::TypeRef(e); - ), - (Primitive, - rv = ::HIR::TypeRef(e); - ), - (Path, - TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2), - (Generic, - rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::Data_Path { - monomorphise_genericpath_with(sp, e2, callback, allow_infer), - e.binding.clone() - } ); - ), - (UfcsKnown, - rv = ::HIR::TypeRef( ::HIR::Path::Data::make_UfcsKnown({ - box$( monomorphise_type_with(sp, *e2.type, callback, allow_infer) ), - monomorphise_genericpath_with(sp, e2.trait, callback, allow_infer), - e2.item, - monomorphise_path_params_with(sp, e2.params, callback, allow_infer) - }) ); - ), - (UfcsUnknown, - TODO(sp, "UfcsUnknown"); - ), - (UfcsInherent, - TODO(sp, "UfcsInherent"); - ) - ) - ), - (Generic, - rv = callback(tpl).clone(); - ), - (TraitObject, - ::HIR::TypeRef::Data::Data_TraitObject to; - to.m_trait = monomorphise_traitpath_with(sp, e.m_trait, callback, allow_infer); - for(const auto& trait : e.m_markers) - { - to.m_markers.push_back( monomorphise_genericpath_with(sp, trait, callback, allow_infer) ); - } - to.m_lifetime = e.m_lifetime; - rv = ::HIR::TypeRef( mv$(to) ); - ), - (Array, - if( e.size_val == ~0u ) { - BUG(sp, "Attempting to clone array with unknown size - " << tpl); - } - rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Array({ - box$( monomorphise_type_with(sp, *e.inner, callback) ), - ::HIR::ExprPtr(), - e.size_val - }) ); - ), - (Slice, - rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Slice({ box$(monomorphise_type_with(sp, *e.inner, callback)) }) ); - ), - (Tuple, - ::std::vector< ::HIR::TypeRef> types; - for(const auto& ty : e) { - types.push_back( monomorphise_type_with(sp, ty, callback) ); - } - rv = ::HIR::TypeRef( mv$(types) ); - ), - (Borrow, - rv = ::HIR::TypeRef::new_borrow(e.type, monomorphise_type_with(sp, *e.inner, callback)); - ), - (Pointer, - rv = ::HIR::TypeRef::new_pointer(e.type, monomorphise_type_with(sp, *e.inner, callback)); - ), - (Function, - ::HIR::FunctionType ft; - ft.is_unsafe = e.is_unsafe; - ft.m_abi = e.m_abi; - ft.m_rettype = box$( monomorphise_type_with(sp, *e.m_rettype, callback) ); - for( const auto& arg : e.m_arg_types ) - ft.m_arg_types.push_back( monomorphise_type_with(sp, arg, callback) ); - rv = ::HIR::TypeRef( mv$(ft) ); - ), - (Closure, - ::HIR::TypeRef::Data::Data_Closure oe; - oe.node = e.node; - oe.m_rettype = box$( monomorphise_type_with(sp, *e.m_rettype, callback) ); - for(const auto& a : e.m_arg_types) - oe.m_arg_types.push_back( monomorphise_type_with(sp, a, callback) ); - rv = ::HIR::TypeRef(::HIR::TypeRef::Data::make_Closure( mv$(oe) )); - ) - ) - return rv; - } - - ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl) - { - DEBUG("tpl = " << tpl); - return monomorphise_type_with(sp, tpl, [&](const auto& gt)->const auto& { - const auto& e = gt.m_data.as_Generic(); - if( e.name == "Self" ) - TODO(sp, "Handle 'Self' when monomorphising"); - //if( e.binding >= params_def.m_types.size() ) { - //} - if( e.binding >= params.m_types.size() ) { - BUG(sp, "Generic param out of input range - " << e.binding << " '"<<e.name<<"' >= " << params.m_types.size()); - } - return params.m_types[e.binding]; - }, false); - } void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct) { @@ -1394,11 +1153,11 @@ namespace typeck { arg_types.reserve( fields.size() ); for(const auto& fld : fields) { - if( monomorphise_type_needed(fld) ) { - arg_types.push_back( this->context.expand_associated_types(sp, monomorphise_type_with(sp, fld, monomorph_cb)) ); + if( monomorphise_type_needed(fld.ent) ) { + arg_types.push_back( this->context.expand_associated_types(sp, monomorphise_type_with(sp, fld.ent, monomorph_cb)) ); } else { - arg_types.push_back( fld.clone() ); + arg_types.push_back( fld.ent.clone() ); } } arg_types.push_back( ::HIR::TypeRef( ::HIR::GenericPath(type_path, path_params.clone()) ) ); diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp index 6953d0e2..1eaeea66 100644 --- a/src/hir_typeck/expr.hpp +++ b/src/hir_typeck/expr.hpp @@ -7,19 +7,9 @@ #define IDENT_CR ([](const auto& v)->const auto&{return v;}) -namespace typeck { - -// TODO/NOTE - This is identical to ::HIR::t_cb_resolve_type -typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_generic; +#include "helpers.hpp" -extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); -extern bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl); -extern bool monomorphise_path_needed(const ::HIR::Path& tpl); - -extern ::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer); -extern ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer); -extern ::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer=true); -extern ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl); +namespace typeck { extern void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct); diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 8c7d9c17..be733ddc 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -3,6 +3,7 @@ #include "expr.hpp" #include <hir/hir.hpp> #include <algorithm> // std::find_if +#include "helpers.hpp" struct FmtType { const typeck::TypecheckContext& ctxt; @@ -741,13 +742,13 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, } for( unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { - if( monomorphise_type_needed(tup_var[i]) ) { - auto var_ty = monomorphise_type(sp, enm.m_params, gp.m_params, tup_var[i]); + if( monomorphise_type_needed(tup_var[i].ent) ) { + auto var_ty = monomorphise_type(sp, enm.m_params, gp.m_params, tup_var[i].ent); this->add_binding(sp, e.sub_patterns[i], var_ty); } else { // SAFE: Can't have a _ (monomorphise_type_needed checks for that) - this->add_binding(sp, e.sub_patterns[i], const_cast< ::HIR::TypeRef&>(tup_var[i])); + this->add_binding(sp, e.sub_patterns[i], const_cast< ::HIR::TypeRef&>(tup_var[i].ent)); } } ) @@ -812,7 +813,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, if( f_idx == tup_var.size() ) { ERROR(sp, E0000, "Enum variant " << e.path << " doesn't have a field " << field_pat.first); } - const ::HIR::TypeRef& field_type = tup_var[f_idx].second; + const ::HIR::TypeRef& field_type = tup_var[f_idx].second.ent; if( monomorphise_type_needed(field_type) ) { auto field_type_mono = monomorphise_type(sp, enm.m_params, gp.m_params, field_type); this->add_binding(sp, field_pat.second, field_type_mono); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 25be3d8a..1a1a4751 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -11,6 +11,7 @@ #include <hir/visitor.hpp> #include <algorithm> // std::find_if +#include "helpers.hpp" #include "expr.hpp" // PLAN: Build up a set of conditions that are easier to solve @@ -428,7 +429,39 @@ public: // - Create ivars in path, and set result type const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path); this->context.equate_types(node.span(), node.m_res_type, ty); - // TODO: Bind fields with type params (coercable) + + const ::HIR::t_tuple_fields* fields_ptr = nullptr; + TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e), + (Unbound, ), + (Opaque, ), + (Enum, + const auto& var_name = node.m_path.m_path.m_components.back(); + const auto& enm = *e; + auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; }); + assert(it != enm.m_variants.end()); + fields_ptr = &it->second.as_Tuple(); + ), + (Struct, + fields_ptr = &e->m_data.as_Tuple(); + ) + ) + assert(fields_ptr); + const ::HIR::t_tuple_fields& fields = *fields_ptr; + if( fields.size() != node.m_args.size() ) { + ERROR(node.span(), E0000, ""); + } + + // Bind fields with type params (coercable) + for( unsigned int i = 0; i < node.m_args.size(); i ++ ) + { + const auto& des_ty_r = fields[i].ent; + if( monomorphise_type_needed(des_ty_r) ) { + TODO(node.span(), "Monomorphise tuple variant type"); + } + else { + this->context.equate_types_coerce(node.span(), des_ty_r, node.m_args[i]); + } + } for( auto& val : node.m_args ) { val->visit( *this ); @@ -444,12 +477,54 @@ public: // - Create ivars in path, and set result type const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path); this->context.equate_types(node.span(), node.m_res_type, ty); - // TODO: Bind fields with type params (coercable) + + const ::HIR::t_struct_fields* fields_ptr = nullptr; + TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e), + (Unbound, ), + (Opaque, ), + (Enum, + const auto& var_name = node.m_path.m_path.m_components.back(); + const auto& enm = *e; + auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; }); + assert(it != enm.m_variants.end()); + fields_ptr = &it->second.as_Struct(); + ), + (Struct, + fields_ptr = &e->m_data.as_Named(); + ) + ) + assert(fields_ptr); + const ::HIR::t_struct_fields& fields = *fields_ptr; + + // Bind fields with type params (coercable) + for( auto& val : node.m_values) + { + const auto& name = val.first; + auto it = ::std::find_if(fields.begin(), fields.end(), [&](const auto& v)->bool{ return v.first == name; }); + assert(it != fields.end()); + const auto& des_ty_r = it->second.ent; + + if( monomorphise_type_needed(des_ty_r) ) { + TODO(node.span(), "Monomorphise struct variant type"); + } + else { + this->context.equate_types_coerce(node.span(), des_ty_r, val.second); + } + } for( auto& val : node.m_values ) { val.second->visit( *this ); } } + void visit(::HIR::ExprNode_UnitVariant& node) override + { + TRACE_FUNCTION_F(node.m_path << " [" << (node.m_is_struct ? "struct" : "enum") << "]"); + + // - Create ivars in path, and set result type + const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path); + this->context.equate_types(node.span(), node.m_res_type, ty); + } + void visit(::HIR::ExprNode_CallPath& node) override { TRACE_FUNCTION_F(node.m_path << "(...)"); @@ -487,7 +562,9 @@ public: this->context.add_ivars( val->m_res_type ); } - // TODO: Locate method and link arguments + // Resolution can't be done until lefthand type is know. + // > Has to be done during iteraton + this->context.add_revisit( node ); node.m_value->visit( *this ); for( auto& val : node.m_args ) { @@ -511,7 +588,12 @@ public: this->context.add_ivars( val->m_res_type ); } - // TODO: Cleanly equate into tuple (can it coerce?) + ::std::vector< ::HIR::TypeRef> tuple_tys; + for(const auto& val : node.m_vals ) { + // Can these coerce? Assuming not + tuple_tys.push_back( val->m_res_type.clone() ); + } + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(mv$(tuple_tys))); for( auto& val : node.m_vals ) { val->visit( *this ); @@ -524,7 +606,12 @@ public: this->context.add_ivars( val->m_res_type ); } - // TODO: Cleanly equate into array (with coercions) + // Cleanly equate into array (with coercions) + // - Result type already set, just need to extract ivar + const auto& inner_ty = *node.m_res_type.m_data.as_Array().inner; + for( auto& val : node.m_vals ) { + this->context.equate_types_coerce(node.span(), inner_ty, val); + } for( auto& val : node.m_vals ) { val->visit( *this ); @@ -536,7 +623,15 @@ public: this->context.add_ivars( node.m_val->m_res_type ); this->context.add_ivars( node.m_size->m_res_type ); - // TODO: Cleanly equate into array (TODO: with coercions?) + // Create result type (can't be known until after const expansion) + // - Should it be created in const expansion? + auto ty = ::HIR::TypeRef::new_array( ::HIR::TypeRef(), node.m_size_val ); + this->context.add_ivars(ty); + this->context.equate_types(node.span(), node.m_res_type, ty); + // Equate with coercions + const auto& inner_ty = *ty.m_data.as_Array().inner; + this->context.equate_types_coerce(node.span(), inner_ty, node.m_val); + this->context.equate_types(node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), node.m_size->m_res_type); node.m_val->visit( *this ); node.m_size->visit( *this ); @@ -552,6 +647,7 @@ public: DEBUG(" (: " << e.m_type << " = " << e.m_value << ")"); ), (Boolean, + DEBUG(" ( " << (e ? "true" : "false") << ")"); ), (String, ), @@ -559,19 +655,134 @@ public: ) ) } - void visit(::HIR::ExprNode_UnitVariant& node) override - { - TRACE_FUNCTION_F(node.m_path << " [" << (node.m_is_struct ? "struct" : "enum") << "]"); - - // TODO: Infer/bind path - // TODO: Result type - } void visit(::HIR::ExprNode_PathValue& node) override { + const auto& sp = node.span(); TRACE_FUNCTION_F(node.m_path); - // TODO: Infer/bind path - // TODO: Bind type + this->add_ivars_path(node.span(), node.m_path); + + TU_MATCH(::HIR::Path::Data, (node.m_path.m_data), (e), + (Generic, + switch(node.m_target) { + case ::HIR::ExprNode_PathValue::UNKNOWN: + BUG(sp, "Unknown target PathValue encountered with Generic path"); + case ::HIR::ExprNode_PathValue::FUNCTION: { + const auto& f = this->context.m_crate.get_function_by_path(sp, e.m_path); + ::HIR::FunctionType ft { + f.m_unsafe, + f.m_abi, + box$( f.m_return.clone() ), + {} + }; + for( const auto& arg : f.m_args ) + ft.m_arg_types.push_back( arg.second.clone() ); + auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) ); + this->context.equate_types(sp, node.m_res_type, ty); + } break; + case ::HIR::ExprNode_PathValue::STATIC: { + const auto& v = this->context.m_crate.get_static_by_path(sp, e.m_path); + DEBUG("static v.m_type = " << v.m_type); + this->context.equate_types(sp, node.m_res_type, v.m_type); + } break; + case ::HIR::ExprNode_PathValue::CONSTANT: { + const auto& v = this->context.m_crate.get_constant_by_path(sp, e.m_path); + DEBUG("const"<<v.m_params.fmt_args()<<" v.m_type = " << v.m_type); + if( v.m_params.m_types.size() > 0 ) { + TODO(sp, "Support generic constants in typeck"); + } + this->context.equate_types(sp, node.m_res_type, v.m_type); + } break; + } + ), + (UfcsUnknown, + BUG(sp, "Encountered UfcsUnknown"); + ), + (UfcsKnown, + TODO(sp, "Look up associated constants/statics (trait)"); + ), + (UfcsInherent, + // TODO: If ivars are valid within the type of this UFCS, then resolution has to be deferred until iteration + // - If they're not valid, then resolution can be done here. + TODO(sp, "Handle associated constants/functions in type - Can the type be infer?"); + + #if 0 + // - Locate function (and impl block) + const ::HIR::Function* fcn_ptr = nullptr; + const ::HIR::TypeImpl* impl_ptr = nullptr; + this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& { + if( ty.m_data.is_Infer() ) + return this->context.get_type(ty); + else + return ty; + }, + [&](const auto& impl) { + DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type); + auto it = impl.m_methods.find(e.item); + if( it == impl.m_methods.end() ) + return false; + fcn_ptr = &it->second; + impl_ptr = &impl; + return true; + }); + if( !fcn_ptr ) { + ERROR(sp, E0000, "Failed to locate function " << path); + } + assert(impl_ptr); + fix_param_count(sp, this->context, path, fcn_ptr->m_params, e.params); + + // If the impl block has parameters, figure out what types they map to + // - The function params are already mapped (from fix_param_count) + ::HIR::PathParams impl_params; + if( impl_ptr->m_params.m_types.size() > 0 ) { + impl_params.m_types.resize( impl_ptr->m_params.m_types.size() ); + impl_ptr->m_type.match_generics(sp, *e.type, this->context.callback_resolve_infer(), [&](auto idx, const auto& ty) { + assert( idx < impl_params.m_types.size() ); + impl_params.m_types[idx] = ty.clone(); + }); + for(const auto& ty : impl_params.m_types) + assert( !( ty.m_data.is_Infer() && ty.m_data.as_Infer().index == ~0u) ); + } + + // Create monomorphise callback + const auto& fcn_params = e.params; + auto monomorph_cb = [&](const auto& gt)->const auto& { + const auto& ge = gt.m_data.as_Generic(); + if( ge.binding == 0xFFFF ) { + return this->context.get_type(*e.type); + } + else if( ge.binding < 256 ) { + auto idx = ge.binding; + if( idx >= impl_params.m_types.size() ) { + BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << impl_params.m_types.size()); + } + return this->context.get_type(impl_params.m_types[idx]); + } + else if( ge.binding < 512 ) { + auto idx = ge.binding - 256; + if( idx >= fcn_params.m_types.size() ) { + BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << fcn_params.m_types.size()); + } + return this->context.get_type(fcn_params.m_types[idx]); + } + else { + BUG(sp, "Generic bounding out of total range"); + } + }; + + ::HIR::FunctionType ft { + fcn_ptr->m_unsafe, fcn_ptr->m_abi, + box$( monomorphise_type_with(sp, fcn_ptr->m_return, monomorph_cb) ), + {} + }; + for(const auto& arg : fcn_ptr->m_args) + ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) ); + auto ty = ::HIR::TypeRef(mv$(ft)); + + this->context.apply_equality(node.span(), node.m_res_type, ty); + #endif + ) + ) } void visit(::HIR::ExprNode_Variable& node) override { diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp new file mode 100644 index 00000000..2829726e --- /dev/null +++ b/src/hir_typeck/helpers.cpp @@ -0,0 +1,244 @@ + +#include "helpers.hpp" + +bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); + +bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl) +{ + for(const auto& ty : tpl.m_types) + if( monomorphise_type_needed(ty) ) + return true; + return false; +} +bool monomorphise_path_needed(const ::HIR::Path& tpl) +{ + TU_MATCH(::HIR::Path::Data, (tpl.m_data), (e), + (Generic, + return monomorphise_pathparams_needed(e.m_params); + ), + (UfcsInherent, + return monomorphise_type_needed(*e.type) || monomorphise_pathparams_needed(e.params); + ), + (UfcsKnown, + return monomorphise_type_needed(*e.type) || monomorphise_pathparams_needed(e.trait.m_params) || monomorphise_pathparams_needed(e.params); + ), + (UfcsUnknown, + return monomorphise_type_needed(*e.type) || monomorphise_pathparams_needed(e.params); + ) + ) + throw ""; +} +bool monomorphise_traitpath_needed(const ::HIR::TraitPath& tpl) +{ + if( monomorphise_pathparams_needed(tpl.m_path.m_params) ) return true; + for(const auto& assoc : tpl.m_type_bounds) + if( monomorphise_type_needed(assoc.second) ) + return true; + return false; +} +bool monomorphise_type_needed(const ::HIR::TypeRef& tpl) +{ + TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e), + (Infer, + assert(!"ERROR: _ type found in monomorphisation target"); + ), + (Diverge, + return false; + ), + (Primitive, + return false; + ), + (Path, + return monomorphise_path_needed(e.path); + ), + (Generic, + return true; + ), + (TraitObject, + if( monomorphise_traitpath_needed(e.m_trait) ) + return true; + for(const auto& trait : e.m_markers) + if( monomorphise_pathparams_needed(trait.m_params) ) + return true; + return false; + ), + (Array, + return monomorphise_type_needed(*e.inner); + ), + (Slice, + return monomorphise_type_needed(*e.inner); + ), + (Tuple, + for(const auto& ty : e) { + if( monomorphise_type_needed(ty) ) + return true; + } + return false; + ), + (Borrow, + return monomorphise_type_needed(*e.inner); + ), + (Pointer, + return monomorphise_type_needed(*e.inner); + ), + (Function, + for(const auto& ty : e.m_arg_types) { + if( monomorphise_type_needed(ty) ) + return true; + } + return monomorphise_type_needed(*e.m_rettype); + ), + (Closure, + for(const auto& ty : e.m_arg_types) { + if( monomorphise_type_needed(ty) ) + return true; + } + return monomorphise_type_needed(*e.m_rettype); + ) + ) + throw ""; +} + +::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer) +{ + ::HIR::PathParams rv; + for( const auto& ty : tpl.m_types) + rv.m_types.push_back( monomorphise_type_with(sp, ty, callback) ); + return rv; +} +::HIR::GenericPath monomorphise_genericpath_with(const Span& sp, const ::HIR::GenericPath& tpl, t_cb_generic callback, bool allow_infer) +{ + return ::HIR::GenericPath( tpl.m_path, monomorphise_path_params_with(sp, tpl.m_params, callback, allow_infer) ); +} +::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer) +{ + ::HIR::TraitPath rv { + monomorphise_genericpath_with(sp, tpl.m_path, callback, allow_infer), + tpl.m_hrls, + {}, + tpl.m_trait_ptr + }; + + for(const auto& assoc : tpl.m_type_bounds) + rv.m_type_bounds.insert(::std::make_pair( assoc.first, monomorphise_type_with(sp, assoc.second, callback, allow_infer) )); + + return rv; +} +::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer) +{ + ::HIR::TypeRef rv; + TRACE_FUNCTION_FR("tpl = " << tpl, rv); + TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e), + (Infer, + if( allow_infer ) { + rv = ::HIR::TypeRef(e); + } + else { + BUG(sp, "_ type found in monomorphisation target"); + } + ), + (Diverge, + rv = ::HIR::TypeRef(e); + ), + (Primitive, + rv = ::HIR::TypeRef(e); + ), + (Path, + TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2), + (Generic, + rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::Data_Path { + monomorphise_genericpath_with(sp, e2, callback, allow_infer), + e.binding.clone() + } ); + ), + (UfcsKnown, + rv = ::HIR::TypeRef( ::HIR::Path::Data::make_UfcsKnown({ + box$( monomorphise_type_with(sp, *e2.type, callback, allow_infer) ), + monomorphise_genericpath_with(sp, e2.trait, callback, allow_infer), + e2.item, + monomorphise_path_params_with(sp, e2.params, callback, allow_infer) + }) ); + ), + (UfcsUnknown, + TODO(sp, "UfcsUnknown"); + ), + (UfcsInherent, + TODO(sp, "UfcsInherent"); + ) + ) + ), + (Generic, + rv = callback(tpl).clone(); + ), + (TraitObject, + ::HIR::TypeRef::Data::Data_TraitObject to; + to.m_trait = monomorphise_traitpath_with(sp, e.m_trait, callback, allow_infer); + for(const auto& trait : e.m_markers) + { + to.m_markers.push_back( monomorphise_genericpath_with(sp, trait, callback, allow_infer) ); + } + to.m_lifetime = e.m_lifetime; + rv = ::HIR::TypeRef( mv$(to) ); + ), + (Array, + if( e.size_val == ~0u ) { + BUG(sp, "Attempting to clone array with unknown size - " << tpl); + } + rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Array({ + box$( monomorphise_type_with(sp, *e.inner, callback) ), + ::HIR::ExprPtr(), + e.size_val + }) ); + ), + (Slice, + rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Slice({ box$(monomorphise_type_with(sp, *e.inner, callback)) }) ); + ), + (Tuple, + ::std::vector< ::HIR::TypeRef> types; + for(const auto& ty : e) { + types.push_back( monomorphise_type_with(sp, ty, callback) ); + } + rv = ::HIR::TypeRef( mv$(types) ); + ), + (Borrow, + rv = ::HIR::TypeRef::new_borrow(e.type, monomorphise_type_with(sp, *e.inner, callback)); + ), + (Pointer, + rv = ::HIR::TypeRef::new_pointer(e.type, monomorphise_type_with(sp, *e.inner, callback)); + ), + (Function, + ::HIR::FunctionType ft; + ft.is_unsafe = e.is_unsafe; + ft.m_abi = e.m_abi; + ft.m_rettype = box$( monomorphise_type_with(sp, *e.m_rettype, callback) ); + for( const auto& arg : e.m_arg_types ) + ft.m_arg_types.push_back( monomorphise_type_with(sp, arg, callback) ); + rv = ::HIR::TypeRef( mv$(ft) ); + ), + (Closure, + ::HIR::TypeRef::Data::Data_Closure oe; + oe.node = e.node; + oe.m_rettype = box$( monomorphise_type_with(sp, *e.m_rettype, callback) ); + for(const auto& a : e.m_arg_types) + oe.m_arg_types.push_back( monomorphise_type_with(sp, a, callback) ); + rv = ::HIR::TypeRef(::HIR::TypeRef::Data::make_Closure( mv$(oe) )); + ) + ) + return rv; +} + +::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl) +{ + DEBUG("tpl = " << tpl); + return monomorphise_type_with(sp, tpl, [&](const auto& gt)->const auto& { + const auto& e = gt.m_data.as_Generic(); + if( e.name == "Self" ) + TODO(sp, "Handle 'Self' when monomorphising"); + //if( e.binding >= params_def.m_types.size() ) { + //} + if( e.binding >= params.m_types.size() ) { + BUG(sp, "Generic param out of input range - " << e.binding << " '"<<e.name<<"' >= " << params.m_types.size()); + } + return params.m_types[e.binding]; + }, false); +} diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp new file mode 100644 index 00000000..ea14fd68 --- /dev/null +++ b/src/hir_typeck/helpers.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include <hir/type.hpp> +#include <hir/hir.hpp> + +// TODO/NOTE - This is identical to ::HIR::t_cb_resolve_type +typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_generic; + +extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); +extern bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl); +extern bool monomorphise_path_needed(const ::HIR::Path& tpl); +extern bool monomorphise_traitpath_needed(const ::HIR::TraitPath& tpl); +extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); +extern ::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer); +extern ::HIR::GenericPath monomorphise_genericpath_with(const Span& sp, const ::HIR::GenericPath& tpl, t_cb_generic callback, bool allow_infer); +extern ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer); +extern ::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer=true); +extern ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl); |