summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-09-04 14:48:01 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-09-04 14:48:01 +0800
commit097f036747d0b99c6d9d2744190c614c02bbb388 (patch)
tree84f4f0be1e964ace4145eecb5113d207fe0b617b
parent3e511bbd5af436e1c757ee68f8af409c0e66ed43 (diff)
downloadmrust-097f036747d0b99c6d9d2744190c614c02bbb388.tar.gz
All - Placement new (<-) syntax
-rw-r--r--src/hir/from_ast_expr.cpp9
-rw-r--r--src/hir_typeck/expr_cs.cpp134
-rw-r--r--src/mir/from_hir.cpp37
-rw-r--r--src/parse/eTokenType.enum.h1
-rw-r--r--src/parse/expr.cpp23
-rw-r--r--src/parse/lex.cpp1
-rw-r--r--src/parse/token.cpp5
7 files changed, 129 insertions, 81 deletions
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index 46cb03b5..a98140d7 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -124,7 +124,11 @@ struct LowerHIR_ExprNode_Visitor:
BUG(v.span(), "Unexpected RANGE_INC binop");
break; }
case ::AST::ExprNode_BinOp::PLACE_IN:
- TODO(v.span(), "Desugar placement syntax");
+ m_rv.reset(new ::HIR::ExprNode_Emplace(v.span(),
+ ::HIR::ExprNode_Emplace::Type::Placer,
+ LowerHIR_ExprNode_Inner(*v.m_left),
+ LowerHIR_ExprNode_Inner(*v.m_right)
+ ));
break;
case ::AST::ExprNode_BinOp::CMPEQU : op = ::HIR::ExprNode_BinOp::Op::CmpEqu ; if(0)
@@ -160,11 +164,8 @@ struct LowerHIR_ExprNode_Visitor:
switch(v.m_type)
{
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)
));
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index cb40e6b4..48888930 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -2270,78 +2270,94 @@ namespace {
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;
+ const auto& data_ty = this->context.get_type(node.m_value->m_res_type);
+ const auto& placer_ty = this->context.get_type(node.m_place->m_res_type);
auto node_ty = node.m_type;
- TRACE_FUNCTION_F("_Emplace: exp_ty=" << exp_ty);
+ TRACE_FUNCTION_F("_Emplace: exp_ty=" << exp_ty << ", data_ty=" << data_ty << ", placer_ty" << placer_ty);
- if( exp_ty.m_data.is_Infer() ) {
- // If the expected result type is still an ivar, nothing can be done
-
- // HACK: Add a possibility of the result type being ``Box<`data_ty`>``
- // - This only happens if the `owned_box` lang item is present and this node is a `box` operation
- const auto& lang_Boxed = this->context.m_lang_Box;
- if( ! lang_Boxed.m_components.empty() && node_ty == ::HIR::ExprNode_Emplace::Type::Boxer )
+ switch(node_ty)
+ {
+ case ::HIR::ExprNode_Emplace::Type::Noop:
+ BUG(sp, "No-op _Emplace in typeck?");
+ break;
+ case ::HIR::ExprNode_Emplace::Type::Placer: {
+ if( placer_ty.m_data.is_Infer() )
{
- // NOTE: `owned_box` shouldn't point to anything but a struct
- const auto& str = this->context.m_crate.get_struct_by_path(sp, lang_Boxed);
- // TODO: Store this type to avoid having to construct it every pass
- auto boxed_ty = ::HIR::TypeRef::new_path( ::HIR::GenericPath(lang_Boxed, {data_ty.clone()}), &str );
- this->context.possible_equate_type_coerce_from( exp_ty.m_data.as_Infer().index, boxed_ty );
+ // Can't do anything, the place is still unknown
+ DEBUG("Place unknown, wait");
+ return ;
}
- 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.
+ // Where P = `placer_ty` and D = `data_ty`
+ // Result type is <<P as Placer<D>>::Place as InPlace<D>>::Owner
+ const auto& lang_Placer = this->context.m_crate.get_lang_item_path(sp, "placer_trait");
+ const auto& lang_InPlace = this->context.m_crate.get_lang_item_path(sp, "in_place_trait");
+ // - Bound P: Placer<D>
+ this->context.equate_types_assoc(sp, {}, lang_Placer, ::make_vec1(data_ty.clone()), placer_ty, "");
+ // -
+ auto place_ty = ::HIR::TypeRef( ::HIR::Path(placer_ty.clone(), ::HIR::GenericPath(lang_Placer, ::HIR::PathParams(data_ty.clone())), "Place") );
+ this->context.equate_types_assoc(sp, node.m_res_type, lang_InPlace, ::make_vec1(data_ty.clone()), place_ty, "Owner");
+ break; }
+ case ::HIR::ExprNode_Emplace::Type::Boxer: {
+ const ::HIR::TypeRef* inner_ty;
+ if( exp_ty.m_data.is_Infer() ) {
+ // If the expected result type is still an ivar, nothing can be done
+
+ // HACK: Add a possibility of the result type being ``Box<`data_ty`>``
+ // - This only happens if the `owned_box` lang item is present and this node is a `box` operation
+ const auto& lang_Boxed = this->context.m_lang_Box;
+ if( ! lang_Boxed.m_components.empty() )
+ {
+ // NOTE: `owned_box` shouldn't point to anything but a struct
+ const auto& str = this->context.m_crate.get_struct_by_path(sp, lang_Boxed);
+ // TODO: Store this type to avoid having to construct it every pass
+ auto boxed_ty = ::HIR::TypeRef::new_path( ::HIR::GenericPath(lang_Boxed, {data_ty.clone()}), &str );
+ this->context.possible_equate_type_coerce_from( exp_ty.m_data.as_Infer().index, boxed_ty );
+ }
+ 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();
- // 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 )
+ if( gpath.m_params.m_types.size() > 0 )
{
- (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() );
+ // TODO: If there's only one, check if it's a valid coercion target, if not don't bother making the coercion.
- // Turn this revisit into a coercion point with the new result type
- // - Mangle this node to be a passthrough to a copy of itself.
+ // 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() );
- 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;
+ // Turn this revisit into a coercion point with the new result type
+ // - Mangle this node to be a passthrough to a copy of itself.
- this->context.equate_types_coerce(sp, exp_ty, node.m_value);
- }
- else
- {
- inner_ty = &exp_ty;
- }
+ 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;
- // 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_coerce(sp, exp_ty, node.m_value);
+ }
+ else
+ {
+ inner_ty = &exp_ty;
+ }
+
+ // Insert a trait bound on the result type to impl `Placer/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, this->context.m_crate.get_lang_item_path(sp, "boxed_trait"), {}, *inner_ty, "Data");
- break;
- case ::HIR::ExprNode_Emplace::Type::Placer:
- // TODO: Search for `Placer<T>`, not `Placer`
- this->context.equate_types_assoc(sp, {}, this->context.m_crate.get_lang_item_path(sp, "placer_trait"), ::make_vec1(data_ty.clone()), *inner_ty, "");
- break;
+ break; }
}
this->m_completed = true;
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 7707de23..2dc4d5b0 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -1531,28 +1531,30 @@ namespace {
if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) {
return node.m_value->visit(*this);
}
- //const auto& path_Placer = m_builder.crate().get_lang_item_path(node.span(), "placer_trait");
+ const auto& path_Placer = m_builder.crate().get_lang_item_path(node.span(), "placer_trait");
const auto& path_Boxed = m_builder.crate().get_lang_item_path(node.span(), "boxed_trait");
const auto& path_Place = m_builder.crate().get_lang_item_path(node.span(), "place_trait");
const auto& path_BoxPlace = m_builder.crate().get_lang_item_path(node.span(), "box_place_trait");
- //const auto& path_InPlace = m_builder.crate().get_lang_item_path(node.span(), "in_place_trait");
+ const auto& path_InPlace = m_builder.crate().get_lang_item_path(node.span(), "in_place_trait");
const auto& data_ty = node.m_value->m_res_type;
+ ::HIR::PathParams trait_params_data;
+ trait_params_data.m_types.push_back( data_ty.clone() );
// 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: {
+ 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; }
+ break;
case ::HIR::ExprNode_Emplace::Type::Placer:
- TODO(node.span(), "_Emplace - Placer");
+ place_type = ::HIR::TypeRef::new_path( ::HIR::Path(node.m_place->m_res_type.clone(), ::HIR::GenericPath(path_Placer, trait_params_data.clone()), "Place", {}), {} );
break;
}
+ m_builder.resolve().expand_associated_types( node.span(), place_type );
// 2. Initialise the place
auto place = m_builder.new_temporary( place_type );
@@ -1563,17 +1565,26 @@ namespace {
case ::HIR::ExprNode_Emplace::Type::Noop:
throw "";
case ::HIR::ExprNode_Emplace::Type::Boxer: {
- ::HIR::PathParams trait_params;
- trait_params.m_types.push_back( data_ty.clone() );
m_builder.end_block(::MIR::Terminator::make_Call({
place__ok, place__panic,
- place.clone(), ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_BoxPlace, mv$(trait_params)), "make_place", {}),
+ place.clone(), ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_BoxPlace, mv$(trait_params_data)), "make_place", {}),
{}
}));
break; }
- case ::HIR::ExprNode_Emplace::Type::Placer:
- TODO(node.span(), "_Emplace - Placer");
- break;
+ case ::HIR::ExprNode_Emplace::Type::Placer: {
+ // Visit the place
+ node.m_place->visit(*this);
+ auto val = m_builder.get_result_in_param(node.m_place->span(), node.m_place->m_res_type);
+ if(const auto* e = val.opt_LValue() ) {
+ m_builder.moved_lvalue( node.m_place->span(), *e );
+ }
+ // Extract the "Place" type
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ place__ok, place__panic,
+ place.clone(), ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_Placer, trait_params_data.clone()), "make_place", {}),
+ ::make_vec1( mv$(val) )
+ }));
+ break; }
}
// TODO: Proper panic handling, including scope destruction
@@ -1624,7 +1635,7 @@ namespace {
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");
+ finalize_path = ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_InPlace, trait_params_data.clone()), "finalize");
break;
}
diff --git a/src/parse/eTokenType.enum.h b/src/parse/eTokenType.enum.h
index 2de1000b..23b03c49 100644
--- a/src/parse/eTokenType.enum.h
+++ b/src/parse/eTokenType.enum.h
@@ -43,6 +43,7 @@ _(TOK_PIPE)
_(TOK_FATARROW) // =>
_(TOK_THINARROW) // ->
+_(TOK_THINARROW_LEFT) // <-
_(TOK_PLUS) _(TOK_DASH)
_(TOK_EXCLAM)
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index f074bc3a..b5263bec 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -698,14 +698,31 @@ bool Parse_IsTokValue(eTokenType tok_type)
default:
return false;
}
-
}
ExprNodeP Parse_Expr1_1(TokenStream& lex);
-// Very evil handling for '..'
ExprNodeP Parse_Expr1(TokenStream& lex)
{
Token tok;
ExprNodeP (*next)(TokenStream&) = Parse_Expr1_1;
+
+ auto dest = next(lex);
+ if( lex.lookahead(0) == TOK_THINARROW_LEFT )
+ {
+ GET_TOK(tok, lex);
+ auto val = Parse_Expr1(lex);
+ return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::PLACE_IN, mv$(dest), mv$(val));
+ }
+ else
+ {
+ return dest;
+ }
+}
+ExprNodeP Parse_Expr1_2(TokenStream& lex);
+// Very evil handling for '..'
+ExprNodeP Parse_Expr1_1(TokenStream& lex)
+{
+ Token tok;
+ ExprNodeP (*next)(TokenStream&) = Parse_Expr1_2;
ExprNodeP left, right;
// Inclusive range to a value
@@ -746,7 +763,7 @@ ExprNodeP Parse_Expr1(TokenStream& lex)
return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) );
}
// TODO: Is this left associative?
-LEFTASSOC(Parse_Expr1_1, Parse_Expr1_5,
+LEFTASSOC(Parse_Expr1_2, Parse_Expr1_5,
case TOK_TRIPLE_DOT:
rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) );
break;
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp
index 1fa0729f..fb57043d 100644
--- a/src/parse/lex.cpp
+++ b/src/parse/lex.cpp
@@ -97,6 +97,7 @@ static const struct {
TOKENT("::", TOK_DOUBLE_COLON),
TOKENT(";", TOK_SEMICOLON),
TOKENT("<", TOK_LT),
+ TOKENT("<-", TOK_THINARROW_LEFT),
TOKENT("<<", TOK_DOUBLE_LT),
TOKENT("<<=",TOK_DOUBLE_LT_EQUAL),
TOKENT("<=", TOK_LTE),
diff --git a/src/parse/token.cpp b/src/parse/token.cpp
index ffa566f4..09f50a09 100644
--- a/src/parse/token.cpp
+++ b/src/parse/token.cpp
@@ -330,8 +330,9 @@ struct EscapedString {
case TOK_AMP: return "&";
case TOK_PIPE: return "|";
- case TOK_FATARROW: return "=>"; // =>
- case TOK_THINARROW: return "->"; // ->
+ case TOK_FATARROW: return "=>";
+ case TOK_THINARROW: return "->";
+ case TOK_THINARROW_LEFT: return "<-";
case TOK_PLUS: return "+";
case TOK_DASH: return "-";