summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/hir/from_ast.cpp18
-rw-r--r--src/hir/hir.hpp12
-rw-r--r--src/hir/visitor.cpp4
-rw-r--r--src/hir_typeck/expr.cpp249
-rw-r--r--src/hir_typeck/expr.hpp14
-rw-r--r--src/hir_typeck/expr_context.cpp9
-rw-r--r--src/hir_typeck/expr_cs.cpp241
-rw-r--r--src/hir_typeck/helpers.cpp244
-rw-r--r--src/hir_typeck/helpers.hpp18
10 files changed, 523 insertions, 288 deletions
diff --git a/Makefile b/Makefile
index 2ca07883..543bd465 100644
--- a/Makefile
+++ b/Makefile
@@ -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);