diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expand/mod.cpp | 2 | ||||
-rw-r--r-- | src/hir/dump.cpp | 12 | ||||
-rw-r--r-- | src/hir/expr.cpp | 5 | ||||
-rw-r--r-- | src/hir/expr.hpp | 32 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 13 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 3 | ||||
-rw-r--r-- | src/hir_expand/annotate_value_usage.cpp | 15 | ||||
-rw-r--r-- | src/hir_typeck/expr_check.cpp | 21 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 77 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 130 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 1 |
11 files changed, 308 insertions, 3 deletions
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 1f87ad7f..179bc37b 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -537,6 +537,7 @@ struct CExpandExpr: replacement.reset(new ::AST::ExprNode_Match( mv$(node.m_value), mv$(arms) )); } + /* else if( node.m_type == ::AST::ExprNode_UniOp::BOX ) { // TODO: Should this be a desugar, or a HIR/MIR operation? @@ -603,6 +604,7 @@ struct CExpandExpr: n->set_pos( node.get_pos() ); replacement.reset(new ::AST::ExprNode_Block( mv$(nodes) )); } + */ } }; diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp index 5291b948..b24d37c6 100644 --- a/src/hir/dump.cpp +++ b/src/hir/dump.cpp @@ -453,6 +453,18 @@ namespace { this->visit_node_ptr(node.m_value); m_os << ")"; } + void visit(::HIR::ExprNode_Emplace& node) override + { + if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) { + return node.m_value->visit(*this); + } + m_os << "("; + this->visit_node_ptr(node.m_place); + m_os << " <- "; + this->visit_node_ptr(node.m_value); + m_os << ")"; + m_os << "/*" << (node.m_type == ::HIR::ExprNode_Emplace::Type::Boxer ? "box" : "place") << "*/"; + } void visit(::HIR::ExprNode_TupleVariant& node) override { m_os << node.m_path; diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index a7a5c31b..6c13f270 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -78,6 +78,11 @@ DEF_VISIT(ExprNode_Index, node, DEF_VISIT(ExprNode_Deref, node, visit_node_ptr(node.m_value); ) +DEF_VISIT(ExprNode_Emplace, node, + if( node.m_place ) + visit_node_ptr(node.m_place); + visit_node_ptr(node.m_value); +) DEF_VISIT(ExprNode_TupleVariant, node, visit_generic_path(::HIR::Visitor::PathContext::VALUE, node.m_path); diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index a912af9c..ba1066b9 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -354,6 +354,10 @@ struct ExprNode_Cast: NODE_METHODS(); }; +// Magical pointer unsizing operation: +// - `&[T; n] -> &[T]` +// - `&T -> &Trait` +// - `Box<T> -> Box<Trait>` struct ExprNode_Unsize: public ExprNode { @@ -380,6 +384,7 @@ struct ExprNode_Index: NODE_METHODS(); }; +// unary `*` struct ExprNode_Deref: public ExprNode { @@ -392,6 +397,31 @@ struct ExprNode_Deref: NODE_METHODS(); }; +/// `box` and `in`/`<-` +struct ExprNode_Emplace: + public ExprNode +{ + /// This influences the ops trait used + enum class Type { + Noop, // Hack to allow coercion - acts as a no-op node + Placer, + Boxer, + }; + + Type m_type; + ExprNodeP m_place; + ExprNodeP m_value; + + ExprNode_Emplace(Span sp, Type ty, ::HIR::ExprNodeP place, ::HIR::ExprNodeP val): + ExprNode( mv$(sp) ), + m_type(ty), + m_place( mv$(place) ), + m_value( mv$(val) ) + { + } + + NODE_METHODS(); +}; struct ExprNode_TupleVariant: public ExprNode @@ -751,6 +781,7 @@ public: NV(ExprNode_Unsize) // Coercion NV(ExprNode_Index) NV(ExprNode_Deref) + NV(ExprNode_Emplace) NV(ExprNode_TupleVariant); NV(ExprNode_CallPath); @@ -794,6 +825,7 @@ public: NV(ExprNode_Unsize) NV(ExprNode_Index) NV(ExprNode_Deref) + NV(ExprNode_Emplace) NV(ExprNode_TupleVariant); NV(ExprNode_CallPath); diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 3a2cd652..01f35cf4 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -188,9 +188,16 @@ struct LowerHIR_ExprNode_Visitor: ::HIR::ExprNode_UniOp::Op op; switch(v.m_type) { - case ::AST::ExprNode_UniOp::BOX: - BUG(v.get_pos(), "Encounterd box operator (should have been expanded in AST)"); - break; + case ::AST::ExprNode_UniOp::BOX: { + // TODO: Emit a call to `<_ as "core"::default::Default>::default()` in place of the nullptr + auto path_Default = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"default", "Default"}) ); + m_rv.reset(new ::HIR::ExprNode_Emplace(v.span(), + ::HIR::ExprNode_Emplace::Type::Boxer, + //::HIR::ExprNodeP(new ::HIR::ExprNode_CallPath(v.span(), ::HIR::Path(::HIR::TypeRef(), mv$(path_Default), "default"), {} )), + ::HIR::ExprNodeP(new ::HIR::ExprNode_Tuple(v.span(), {})), + LowerHIR_ExprNode_Inner(*v.m_value) + )); + } break; case ::AST::ExprNode_UniOp::QMARK: BUG(v.get_pos(), "Encounterd question mark operator (should have been expanded in AST)"); break; diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index b4f5e3e2..1d1349f5 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -416,6 +416,9 @@ namespace { void visit(::HIR::ExprNode_Deref& node) override { badnode(node); } + void visit(::HIR::ExprNode_Emplace& node) override { + badnode(node); + } void visit(::HIR::ExprNode_TupleVariant& node) override { TODO(node.span(), "ExprNode_TupleVariant"); diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp index 139814ef..bf893b22 100644 --- a/src/hir_expand/annotate_value_usage.cpp +++ b/src/hir_expand/annotate_value_usage.cpp @@ -237,6 +237,21 @@ namespace { } } + void visit(::HIR::ExprNode_Emplace& node) override + { + if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) { + if( node.m_place ) + this->visit_node_ptr(node.m_place); + this->visit_node_ptr(node.m_value); + } + else { + auto _ = push_usage( ::HIR::ValueUsage::Move ); + if( node.m_place ) + this->visit_node_ptr(node.m_place); + this->visit_node_ptr(node.m_value); + } + } + void visit(::HIR::ExprNode_Field& node) override { // If taking this field by value, but the type is Copy - pretend it's a borrow. diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index ec632d56..b517e421 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -333,6 +333,27 @@ namespace { node.m_value->visit( *this ); } + void visit(::HIR::ExprNode_Emplace& node) override + { + switch( node.m_type ) + { + case ::HIR::ExprNode_Emplace::Type::Noop: + assert( !node.m_place ); + + check_types_equal(node.span(), node.m_res_type, node.m_value->m_res_type); + break; + case ::HIR::ExprNode_Emplace::Type::Boxer: + // TODO: Check trait and associated type + break; + case ::HIR::ExprNode_Emplace::Type::Placer: + // TODO: Check trait + break; + } + + if( node.m_place ) + this->visit_node_ptr(node.m_place); + this->visit_node_ptr(node.m_value); + } void visit(::HIR::ExprNode_TupleVariant& node) override { TRACE_FUNCTION_F(&node << " " << node.m_path << "(...,) [" << (node.m_is_struct ? "struct" : "enum") << "]"); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 2cfd6fc4..af42bc07 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -804,6 +804,17 @@ namespace { node.m_value->visit( *this ); } + void visit(::HIR::ExprNode_Emplace& node) override + { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << " ... <- ... "); + this->context.add_ivars( node.m_place->m_res_type ); + this->context.add_ivars( node.m_value->m_res_type ); + + this->context.add_revisit(node); + node.m_place->visit( *this ); + node.m_value->visit( *this ); + } void add_ivars_generic_path(const Span& sp, ::HIR::GenericPath& gp) { for(auto& ty : gp.m_params.m_types) @@ -1761,6 +1772,72 @@ namespace { ) this->m_completed = true; } + void visit(::HIR::ExprNode_Emplace& node) override { + const auto& sp = node.span(); + const auto& exp_ty = this->context.get_type(node.m_res_type); + const auto& data_ty = node.m_value->m_res_type; + auto node_ty = node.m_type; + TRACE_FUNCTION_F("_Emplace: exp_ty=" << exp_ty); + if( exp_ty.m_data.is_Infer() ) { + // If the expected result type is still an ivar, nothing can be done + return ; + } + // Assert that the expected result is a Path::Generic type. + if( ! exp_ty.m_data.is_Path() ) { + ERROR(sp, E0000, "box/in can only produce GenericPath types, got " << exp_ty); + } + const auto& path = exp_ty.m_data.as_Path().path; + if( ! path.m_data.is_Generic() ) { + ERROR(sp, E0000, "box/in can only produce GenericPath types, got " << exp_ty); + } + const auto& gpath = path.m_data.as_Generic(); + + const ::HIR::TypeRef* inner_ty; + if( gpath.m_params.m_types.size() > 0 ) + { + // TODO: If there's only one, check if it's a valid coercion target, if not don't bother making the coercion. + + // Take a copy of the type with all type parameters replaced with new ivars + auto newpath = ::HIR::GenericPath(gpath.m_path); + for( const auto& t : gpath.m_params.m_types ) + { + (void)t; + newpath.m_params.m_types.push_back( this->context.m_ivars.new_ivar_tr() ); + } + auto newty = ::HIR::TypeRef::new_path( mv$(newpath), exp_ty.m_data.as_Path().binding.clone() ); + + // Turn this revisit into a coercion point with the new result type + // - Mangle this node to be a passthrough to a copy of itself. + + node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Emplace(node.span(), node.m_type, mv$(node.m_place), mv$(node.m_value)) ); + node.m_type = ::HIR::ExprNode_Emplace::Type::Noop; + node.m_value->m_res_type = mv$(newty); + inner_ty = &node.m_value->m_res_type; + + this->context.equate_types_coerce(sp, exp_ty, node.m_value); + } + else + { + inner_ty = &exp_ty; + } + + // Insert a trait bound on the result type to impl `Placer/Boxer` + switch( node_ty ) + { + case ::HIR::ExprNode_Emplace::Type::Noop: + BUG(sp, "Encountered Noop _Emplace in typecheck"); + case ::HIR::ExprNode_Emplace::Type::Boxer: + //this->context.equate_types_assoc(sp, {}, ::HIR::SimplePath("core", { "ops", "Boxer" }), ::make_vec1(data_ty.clone()), *inner_ty, ""); + this->context.equate_types_assoc(sp, data_ty, ::HIR::SimplePath("core", { "ops", "Boxed" }), {}, *inner_ty, "Data"); + break; + case ::HIR::ExprNode_Emplace::Type::Placer: + // TODO: Search for `Placer<T>`, not `Placer` + this->context.equate_types_assoc(sp, {}, ::HIR::SimplePath("core", { "ops", "Placer" }), ::make_vec1(data_ty.clone()), *inner_ty, ""); + break; + } + + this->m_completed = true; + } void visit(::HIR::ExprNode_TupleVariant& node) override { no_revisit(node); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 59714d8b..a281cbaa 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1027,6 +1027,136 @@ namespace { m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) ); } + void visit(::HIR::ExprNode_Emplace& node) override + { + if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) { + return node.m_value->visit(*this); + } + //auto path_Placer = ::HIR::SimplePath("core", {"ops", "Placer"}); + auto path_BoxPlace = ::HIR::SimplePath("core", {"ops", "BoxPlace"}); + auto path_Place = ::HIR::SimplePath("core", {"ops", "Place"}); + auto path_Boxed = ::HIR::SimplePath("core", {"ops", "Boxed"}); + //auto path_InPlace = ::HIR::SimplePath("core", {"ops", "InPlace"}); + + const auto& data_ty = node.m_value->m_res_type; + + // 1. Obtain the type of the `place` variable + ::HIR::TypeRef place_type; + switch( node.m_type ) + { + case ::HIR::ExprNode_Emplace::Type::Noop: + throw ""; + case ::HIR::ExprNode_Emplace::Type::Boxer: { + place_type = ::HIR::TypeRef::new_path( ::HIR::Path(node.m_res_type.clone(), ::HIR::GenericPath(path_Boxed), "Place", {}), {} ); + m_builder.resolve().expand_associated_types( node.span(), place_type ); + break; } + case ::HIR::ExprNode_Emplace::Type::Placer: + TODO(node.span(), "_Emplace - Placer"); + break; + } + + // 2. Initialise the place + auto place = m_builder.new_temporary( place_type ); + auto place__panic = m_builder.new_bb_unlinked(); + auto place__ok = m_builder.new_bb_unlinked(); + switch( node.m_type ) + { + case ::HIR::ExprNode_Emplace::Type::Noop: + throw ""; + case ::HIR::ExprNode_Emplace::Type::Boxer: { + auto fcn_ty_data = ::HIR::FunctionType { false, "", box$( place_type.clone() ), {} }; + ::HIR::PathParams trait_params; + trait_params.m_types.push_back( data_ty.clone() ); + auto fcn_path = ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_BoxPlace, mv$(trait_params)), "make_place", {}); + auto fcn_val = m_builder.new_temporary( ::HIR::TypeRef(mv$(fcn_ty_data)) ); + m_builder.push_stmt_assign( node.span(), fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(mv$(fcn_path)) ) ); + m_builder.end_block(::MIR::Terminator::make_Call({ + place__ok, place__panic, + place.clone(), mv$(fcn_val), + {} + })); + break; } + case ::HIR::ExprNode_Emplace::Type::Placer: + TODO(node.span(), "_Emplace - Placer"); + break; + } + + // TODO: Proper panic handling, including scope destruction + m_builder.set_cur_block(place__panic); + // TODO: Drop `place` + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); + m_builder.set_cur_block(place__ok); + + // 2. Get `place_raw` + auto place_raw__type = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone()); + auto place_raw = m_builder.new_temporary( place_raw__type ); + auto place_raw__panic = m_builder.new_bb_unlinked(); + auto place_raw__ok = m_builder.new_bb_unlinked(); + { + auto place_refmut__type = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, place_type.clone()); + auto place_refmut = m_builder.lvalue_or_temp(node.span(), place_refmut__type, ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Unique, place.clone() })); + auto fcn_ty_data = ::HIR::FunctionType { false, "", box$( place_raw__type.clone() ), ::make_vec1(mv$(place_refmut__type)) }; + // <typeof(place) as ops::Place>::pointer + auto fcn_path = ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_Place), "pointer", {}); + auto fcn_val = m_builder.new_temporary( ::HIR::TypeRef(mv$(fcn_ty_data)) ); + m_builder.push_stmt_assign( node.span(), fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(mv$(fcn_path)) ) ); + m_builder.end_block(::MIR::Terminator::make_Call({ + place_raw__ok, place_raw__panic, + place_raw.clone(), mv$(fcn_val), + ::make_vec1( mv$(place_refmut) ) + })); + } + + // TODO: Proper panic handling, including scope destruction + m_builder.set_cur_block(place_raw__panic); + // TODO: Drop `place` + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); + m_builder.set_cur_block(place_raw__ok); + + + // 3. Get the value and assign it into `place_raw` + node.m_value->visit(*this); + auto val = m_builder.get_result(node.span()); + m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Deref({ box$(place_raw.clone()) }), mv$(val) ); + + // 3. Return a call to `finalize` + ::HIR::Path finalize_path(::HIR::GenericPath {}); + switch( node.m_type ) + { + case ::HIR::ExprNode_Emplace::Type::Noop: + throw ""; + case ::HIR::ExprNode_Emplace::Type::Boxer: + finalize_path = ::HIR::Path(node.m_res_type.clone(), ::HIR::GenericPath(path_Boxed), "finalize"); + break; + case ::HIR::ExprNode_Emplace::Type::Placer: + TODO(node.span(), "_Emplace - Placer"); + break; + } + + auto res = m_builder.new_temporary( node.m_res_type ); + auto res__panic = m_builder.new_bb_unlinked(); + auto res__ok = m_builder.new_bb_unlinked(); + { + auto fcn_ty_data = ::HIR::FunctionType { true, "", box$(node.m_res_type.clone()), ::make_vec1(mv$(place_type)) }; + auto fcn_val = m_builder.new_temporary( ::HIR::TypeRef(mv$(fcn_ty_data)) ); + m_builder.push_stmt_assign( node.span(), fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(mv$(finalize_path)) ) ); + m_builder.end_block(::MIR::Terminator::make_Call({ + res__ok, res__panic, + res.clone(), mv$(fcn_val), + ::make_vec1( mv$(place) ) + })); + } + + // TODO: Proper panic handling, including scope destruction + m_builder.set_cur_block(res__panic); + // TODO: Should this drop the value written to the rawptr? + // - No, becuase it's likely invalid now. Goodbye! + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); + m_builder.set_cur_block(res__ok); + + m_builder.set_result( node.span(), mv$(res) ); + } + void visit(::HIR::ExprNode_TupleVariant& node) override { TRACE_FUNCTION_F("_TupleVariant"); diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index c5d770af..c915cfcc 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -118,6 +118,7 @@ public: const ::HIR::SimplePath* lang_Box() const { return m_lang_Box; } const ::HIR::Crate& crate() const { return m_resolve.m_crate; } + const StaticTraitResolve& resolve() const { return m_resolve; } //::HIR::TypeRef* is_type_owned_box(::HIR::TypeRef& ty) const { //} |