summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/expr.cpp33
-rw-r--r--src/hir/hir.cpp3
-rw-r--r--src/hir/type.cpp11
-rw-r--r--src/hir_expand/closures.cpp52
-rw-r--r--src/hir_expand/ufcs_everything.cpp8
-rw-r--r--src/hir_typeck/expr_check.cpp13
-rw-r--r--src/hir_typeck/static.cpp31
-rw-r--r--src/mir/from_hir.cpp33
8 files changed, 147 insertions, 37 deletions
diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp
index fdeff6b5..4fb79470 100644
--- a/src/hir/expr.cpp
+++ b/src/hir/expr.cpp
@@ -23,6 +23,7 @@ DEF_VISIT(ExprNode_Return, node,
visit_node_ptr(node.m_value);
)
DEF_VISIT(ExprNode_Let, node,
+ visit_type(node.m_type);
if( node.m_value ) {
visit_node_ptr(node.m_value);
}
@@ -76,19 +77,39 @@ DEF_VISIT(ExprNode_Deref, node,
)
DEF_VISIT(ExprNode_TupleVariant, node,
+ visit_generic_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
+
+ for(auto& ty : node.m_arg_types)
+ visit_type(ty);
+
for(auto& arg : node.m_args)
visit_node_ptr(arg);
)
DEF_VISIT(ExprNode_CallPath, node,
+ for(auto& ty : node.m_cache.m_arg_types)
+ visit_type(ty);
+ visit_path_params(node.m_cache.m_ty_impl_params);
+
+ DEBUG("DEF _CallPath: " << node.m_path);
+ visit_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
for(auto& arg : node.m_args)
visit_node_ptr(arg);
)
DEF_VISIT(ExprNode_CallValue, node,
+ for(auto& ty : node.m_arg_types)
+ visit_type(ty);
+
visit_node_ptr(node.m_value);
for(auto& arg : node.m_args)
visit_node_ptr(arg);
)
DEF_VISIT(ExprNode_CallMethod, node,
+ for(auto& ty : node.m_cache.m_arg_types)
+ visit_type(ty);
+ visit_path_params(node.m_cache.m_ty_impl_params);
+
+ visit_path(::HIR::Visitor::PathContext::VALUE, node.m_method_path);
+
visit_node_ptr(node.m_value);
for(auto& arg : node.m_args)
visit_node_ptr(arg);
@@ -98,10 +119,15 @@ DEF_VISIT(ExprNode_Field, node,
)
DEF_VISIT(ExprNode_Literal, , )
-DEF_VISIT(ExprNode_UnitVariant, , )
-DEF_VISIT(ExprNode_PathValue, , )
+DEF_VISIT(ExprNode_UnitVariant, node,
+ visit_generic_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
+)
+DEF_VISIT(ExprNode_PathValue, node,
+ visit_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
+)
DEF_VISIT(ExprNode_Variable, , )
DEF_VISIT(ExprNode_StructLiteral, node,
+ visit_generic_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
if( node.m_base_value )
visit_node_ptr(node.m_base_value);
for(auto& val : node.m_values)
@@ -121,6 +147,9 @@ DEF_VISIT(ExprNode_ArraySized, node,
)
DEF_VISIT(ExprNode_Closure, node,
+ for(auto& arg : node.m_args)
+ visit_type(arg.second);
+ visit_type(node.m_return);
if(node.m_code)
{
visit_node_ptr(node.m_code);
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index e090b795..4ff909aa 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -148,8 +148,7 @@ namespace {
return false;
),
(Closure,
- DEBUG("TODO: Compare " << left << " and " << right);
- return false;
+ return le.node == re.node;
)
)
return false;
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 45b47519..c4dfb9c3 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -140,10 +140,13 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
os << ") -> " << *e.m_rettype;
),
(Closure,
- os << "closure["<<e.node<<"](";
+ os << "closure["<<e.node<<"]";
+ #if 0
+ os << "(";
for(const auto& t : e.m_arg_types)
os << t << ", ";
os << ") -> " << *e.m_rettype;
+ #endif
)
)
}
@@ -217,7 +220,7 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
if( xe.size_val != te.size_val )
return false;
if( te.size_val == ~0u )
- assert(!"TOD: Compre array types with non-resolved sizes");
+ assert(!"TODO: Compre array types with non-resolved sizes");
return true;
),
(Slice,
@@ -586,7 +589,9 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
TODO(sp, "Function");
),
(Closure,
- TODO(sp, "Closure");
+ if( te.node != xe.node )
+ return Compare::Unequal;
+ return Compare::Equal;
)
)
throw "";
diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp
index 8fe46f0c..892b6bad 100644
--- a/src/hir_expand/closures.cpp
+++ b/src/hir_expand/closures.cpp
@@ -52,14 +52,29 @@ namespace {
const ::std::vector<unsigned int>& m_local_vars;
const ::std::vector<unsigned int>& m_captures;
+ typedef ::std::function< const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_monomorph_cb;
+ t_monomorph_cb m_monomorph_cb;
+
::HIR::ExprNodeP m_replacement;
public:
- ExprVisitor_Mutate(const ::HIR::TypeRef& closure_type, const ::std::vector<unsigned int>& local_vars, const ::std::vector<unsigned int>& captures):
+ ExprVisitor_Mutate(const ::HIR::TypeRef& closure_type, const ::std::vector<unsigned int>& local_vars, const ::std::vector<unsigned int>& captures, t_monomorph_cb mcb):
m_closure_type(closure_type),
m_local_vars(local_vars),
- m_captures(captures)
+ m_captures(captures),
+ m_monomorph_cb(mcb)
{
}
+
+ void visit_type(::HIR::TypeRef& ty) override {
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
+ auto n = m_monomorph_cb(ty).clone();
+ ty = mv$(n);
+ )
+ else {
+ ::HIR::ExprVisitorDef::visit_type(ty);
+ }
+ }
+
void visit_node_ptr(::HIR::ExprNodeP& node_ptr) override {
assert( node_ptr );
auto& node = *node_ptr;
@@ -70,6 +85,8 @@ namespace {
if( m_replacement ) {
node_ptr = mv$(m_replacement);
}
+
+ visit_type( node_ptr->m_res_type );
}
void visit(::HIR::ExprNode_Closure& node) override
{
@@ -262,6 +279,8 @@ namespace {
{
const auto& sp = node.span();
+ TRACE_FUNCTION_F("Extract closure - " << node.m_res_type);
+
// --- Determine borrow set ---
m_closure_stack.push_back( ClosureScope(node) );
@@ -279,6 +298,7 @@ namespace {
// 1. Construct closure type (saving path/index in the node)
::HIR::GenericParams params;
::HIR::PathParams constructor_path_params;
+ ::HIR::PathParams impl_path_params;
// - 0xFFFF "Self" -> 0 "Super"
constructor_path_params.m_types.push_back( ::HIR::TypeRef("Self", 0xFFFF) );
params.m_types.push_back( ::HIR::TypeParamDef { "Super", {}, false } ); // TODO: Maybe Self is sized?
@@ -298,6 +318,7 @@ namespace {
::std::vector<::HIR::TypeRef> params_placeholders;
for(unsigned int i = 0; i < params.m_types.size(); i ++) {
params_placeholders.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) );
+ impl_path_params.m_types.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) );
}
auto monomorph_cb = [&](const auto& ty)->const auto& {
@@ -342,13 +363,15 @@ namespace {
params.m_bounds.push_back( monomorph_bound(bound) );
}
-
+
+ DEBUG("--- Mutate inner code");
// 2. Iterate over the nodes and rewrite variable accesses to either renumbered locals, or field accesses
// - TODO: Monomorphise all referenced types within this.
- ExprVisitor_Mutate ev { node.m_res_type, ent.local_vars, ent.node.m_var_captures };
+ ExprVisitor_Mutate ev { node.m_res_type, ent.local_vars, ent.node.m_var_captures, monomorph_cb };
ev.visit_node_ptr( node.m_code );
// - Types of local variables
+ DEBUG("--- Build locals and captures");
::std::vector< ::HIR::TypeRef> local_types;
local_types.push_back( ::HIR::TypeRef() ); // self - filled by make_fn*
local_types.push_back( ::HIR::TypeRef() ); // args - filled by make_fn*
@@ -371,7 +394,10 @@ namespace {
}
));
+ // Mark the object pathname in the closure.
node.m_obj_path = ::HIR::GenericPath( m_module_path + m_out_types.back().first, mv$(constructor_path_params) );
+ //node.m_res_type = ::HIR::TypeRef( node.m_obj_path.clone() );
+ DEBUG("-- Object name: " << node.m_obj_path);
// - Args
::std::vector< ::HIR::Pattern> args_pat_inner;
@@ -382,13 +408,17 @@ namespace {
}
::HIR::TypeRef args_ty { mv$(args_ty_inner) };
::HIR::Pattern args_pat { {}, ::HIR::Pattern::Data::make_Tuple({ mv$(args_pat_inner) }) };
-
+ ::HIR::TypeRef ret_type = monomorphise_type_with(sp, node.m_return, monomorph_cb);
+
+ DEBUG("args_ty = " << args_ty << ", ret_type = " << ret_type);
+
::HIR::ExprPtr body_code { mv$(node.m_code) };
body_code.m_bindings = mv$(local_types);
// 3. Create trait impls
- ::HIR::TypeRef closure_type = node.m_res_type.clone();
- const ::HIR::TypeRef& ret_type = node.m_return;
+ //::HIR::TypeRef closure_type = node.m_res_type.clone();
+ ::HIR::TypeRef closure_type = ::HIR::TypeRef( ::HIR::GenericPath(node.m_obj_path.m_path.clone(), mv$(impl_path_params)) );
+
::HIR::PathParams trait_params;
trait_params.m_types.push_back( args_ty.clone() );
switch(node.m_class)
@@ -443,7 +473,7 @@ namespace {
// - Fn
m_out_impls.push_back(::std::make_pair(
::HIR::ExprNode_Closure::Class::Shared,
- H::make_fn( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(body_code) )
+ H::make_fn( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), mv$(ret_type), mv$(body_code) )
));
} break;
case ::HIR::ExprNode_Closure::Class::Mut: {
@@ -466,21 +496,21 @@ namespace {
);
m_out_impls.push_back(::std::make_pair(
::HIR::ExprNode_Closure::Class::Once,
- H::make_fnonce( params.clone(), trait_params.clone(), closure_type.clone(), mv$(args_arg), node.m_return.clone(), mv$(dispatch_node) )
+ H::make_fnonce( params.clone(), trait_params.clone(), closure_type.clone(), mv$(args_arg), ret_type.clone(), mv$(dispatch_node) )
));
}
// - FnMut (code)
m_out_impls.push_back(::std::make_pair(
::HIR::ExprNode_Closure::Class::Mut,
- H::make_fnmut( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(body_code) )
+ H::make_fnmut( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), mv$(ret_type), mv$(body_code) )
));
} break;
case ::HIR::ExprNode_Closure::Class::Once:
// - FnOnce (code)
m_out_impls.push_back(::std::make_pair(
::HIR::ExprNode_Closure::Class::Once,
- H::make_fnonce( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(body_code) )
+ H::make_fnonce( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), mv$(ret_type), mv$(body_code) )
));
break;
}
diff --git a/src/hir_expand/ufcs_everything.cpp b/src/hir_expand/ufcs_everything.cpp
index 6e7b42e5..91b6aaa3 100644
--- a/src/hir_expand/ufcs_everything.cpp
+++ b/src/hir_expand/ufcs_everything.cpp
@@ -36,6 +36,8 @@ namespace {
root->visit(*this);
if( m_replacement ) {
auto usage = root->m_usage;
+ const auto* ptr = m_replacement.get();
+ DEBUG("=> REPLACE " << ptr << " " << typeid(*ptr).name());
root.reset( m_replacement.release() );
root->m_usage = usage;
}
@@ -49,6 +51,8 @@ namespace {
node->visit(*this);
if( m_replacement ) {
auto usage = node->m_usage;
+ const auto* ptr = m_replacement.get();
+ DEBUG("=> REPLACE " << ptr << " " << typeid(*ptr).name());
node = mv$(m_replacement);
node->m_usage = usage;
}
@@ -74,8 +78,8 @@ namespace {
::HIR::TypeRef arg_tup_type;
{
::std::vector< ::HIR::TypeRef> arg_types;
- for(unsigned int i = 0; i < node.m_arg_types.size() - 1; i ++)
- arg_types.push_back( node.m_arg_types[i].clone() );
+ for(unsigned int i = 0; i < node.m_args.size(); i ++)
+ arg_types.push_back( node.m_args[i]->m_res_type.clone() );
arg_tup_type = ::HIR::TypeRef( mv$(arg_types) );
}
// - Make the trait arguments.
diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp
index bbe028d0..83051653 100644
--- a/src/hir_typeck/expr_check.cpp
+++ b/src/hir_typeck/expr_check.cpp
@@ -341,6 +341,7 @@ namespace {
ASSERT_BUG(sp, fields.size() == node.m_args.size(), "");
// Bind fields with type params (coercable)
+ // TODO: Remove use of m_arg_types (maybe assert that cache is correct?)
for( unsigned int i = 0; i < node.m_args.size(); i ++ )
{
const auto& des_ty_r = fields[i].ent;
@@ -440,6 +441,10 @@ namespace {
const auto& sp = node.span();
TRACE_FUNCTION_F(&node << " " << node.m_path << "(..., )");
+ for( auto& val : node.m_args ) {
+ val->visit( *this );
+ }
+
// Do function resolution again, this time with concrete types.
const auto& path = node.m_path;
/*const*/ auto& cache = node.m_cache;
@@ -600,8 +605,10 @@ namespace {
// Check types
for(unsigned int i = 0; i < node.m_args.size(); i ++) {
+ DEBUG("CHECK ARG " << i << " " << node.m_cache.m_arg_types[i] << " == " << node.m_args[i]->m_res_type);
check_types_equal(node.span(), node.m_cache.m_arg_types[i], node.m_args[i]->m_res_type);
}
+ DEBUG("CHECK RV " << node.m_res_type << " == " << node.m_cache.m_arg_types.back());
check_types_equal(node.span(), node.m_res_type, node.m_cache.m_arg_types.back());
cache.m_monomorph_cb = mv$(monomorph_cb);
@@ -643,14 +650,11 @@ namespace {
)
)
}
-
- for( auto& val : node.m_args ) {
- val->visit( *this );
- }
}
void visit(::HIR::ExprNode_CallValue& node) override
{
TRACE_FUNCTION_F(&node << " (...)(..., )");
+ // TODO: Don't use m_arg_types (do full resolution again)
ASSERT_BUG(node.span(), node.m_arg_types.size() > 0, "CallValue cache not populated");
for(unsigned int i = 0; i < node.m_args.size(); i ++)
{
@@ -668,6 +672,7 @@ namespace {
void visit(::HIR::ExprNode_CallMethod& node) override
{
TRACE_FUNCTION_F(&node << " (...)." << node.m_method << "(...,) - " << node.m_method_path);
+ // TODO: Don't use m_cache
ASSERT_BUG(node.span(), node.m_cache.m_arg_types.size() > 0, "CallMethod cache not populated");
ASSERT_BUG(node.span(), node.m_cache.m_arg_types.size() == 1 + node.m_args.size() + 1, "CallMethod cache mis-sized");
check_types_equal(node.m_cache.m_arg_types[0], node.m_value);
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp
index 9f56527e..8abb7174 100644
--- a/src/hir_typeck/static.cpp
+++ b/src/hir_typeck/static.cpp
@@ -397,21 +397,28 @@ void StaticTraitResolve::expand_associated_types(const Span& sp, ::HIR::TypeRef&
// - If it's a closure, then the only trait impls are those generated by typeck
TU_IFLET(::HIR::TypeRef::Data, e2.type->m_data, Closure, te,
- const auto trait_fn = this->m_crate.get_lang_item_path(sp, "fn");
- const auto trait_fn_mut = this->m_crate.get_lang_item_path(sp, "fn_mut");
- const auto trait_fn_once = this->m_crate.get_lang_item_path(sp, "fn_once");
- if( e2.trait.m_path == trait_fn || e2.trait.m_path == trait_fn_mut || e2.trait.m_path == trait_fn_once ) {
- if( e2.item == "Output" ) {
- input = te.m_rettype->clone();
- return ;
+ //if( te.node->m_obj_path == ::HIR::GenericPath() )
+ //{
+ const auto trait_fn = this->m_crate.get_lang_item_path(sp, "fn");
+ const auto trait_fn_mut = this->m_crate.get_lang_item_path(sp, "fn_mut");
+ const auto trait_fn_once = this->m_crate.get_lang_item_path(sp, "fn_once");
+ if( e2.trait.m_path == trait_fn || e2.trait.m_path == trait_fn_mut || e2.trait.m_path == trait_fn_once ) {
+ if( e2.item == "Output" ) {
+ input = te.m_rettype->clone();
+ return ;
+ }
+ else {
+ ERROR(sp, E0000, "No associated type " << e2.item << " for trait " << e2.trait);
+ }
}
else {
- ERROR(sp, E0000, "No associated type " << e2.item << " for trait " << e2.trait);
+ ERROR(sp, E0000, "No implementation of " << e2.trait << " for " << *e2.type);
}
- }
- else {
- ERROR(sp, E0000, "No implementation of " << e2.trait << " for " << *e2.type);
- }
+ //}
+ //else
+ //{
+ // // TODO: Locate impl _without_ binding params too hard?
+ //}
)
// 1. Bounds
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index ef0cf3a6..4c9d1aaf 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -845,10 +845,41 @@ namespace {
void visit(::HIR::ExprNode_CallValue& node) override
{
- BUG(node.span(), "Leftover _CallValue");
+ TRACE_FUNCTION_F("_CallValue " << node.m_value->m_res_type);
+
+ // _CallValue is ONLY valid on function pointers (all others must be desugared)
+ ASSERT_BUG(node.span(), node.m_value->m_res_type.m_data.is_Function(), "Leftover _CallValue on a non-fn()");
+ this->visit_node_ptr(node.m_value);
+ auto fcn_val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) );
+
+ ::std::vector< ::MIR::LValue> values;
+ values.reserve( node.m_args.size() );
+ for(auto& arg : node.m_args)
+ {
+ this->visit_node_ptr(arg);
+ values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) );
+ }
+
+
+ auto panic_block = m_builder.new_bb_unlinked();
+ auto next_block = m_builder.new_bb_unlinked();
+ auto res = m_builder.new_temporary( node.m_res_type );
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ next_block, panic_block,
+ res.clone(), mv$(fcn_val),
+ mv$(values)
+ }));
+
+ m_builder.set_cur_block(panic_block);
+ // TODO: Proper panic handling
+ m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
+
+ m_builder.set_cur_block( next_block );
+ m_builder.set_result( node.span(), mv$(res) );
}
void visit(::HIR::ExprNode_CallMethod& node) override
{
+ // TODO: Allow use on trait objects.
BUG(node.span(), "Leftover _CallMethod");
}
void visit(::HIR::ExprNode_Field& node) override