summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expand/mod.cpp2
-rw-r--r--src/hir/dump.cpp12
-rw-r--r--src/hir/expr.cpp5
-rw-r--r--src/hir/expr.hpp32
-rw-r--r--src/hir/from_ast_expr.cpp13
-rw-r--r--src/hir_conv/constant_evaluation.cpp3
-rw-r--r--src/hir_expand/annotate_value_usage.cpp15
-rw-r--r--src/hir_typeck/expr_check.cpp21
-rw-r--r--src/hir_typeck/expr_cs.cpp77
-rw-r--r--src/mir/from_hir.cpp130
-rw-r--r--src/mir/from_hir.hpp1
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 {
//}