diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-09-04 14:48:01 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-09-04 14:48:01 +0800 |
commit | 097f036747d0b99c6d9d2744190c614c02bbb388 (patch) | |
tree | 84f4f0be1e964ace4145eecb5113d207fe0b617b | |
parent | 3e511bbd5af436e1c757ee68f8af409c0e66ed43 (diff) | |
download | mrust-097f036747d0b99c6d9d2744190c614c02bbb388.tar.gz |
All - Placement new (<-) syntax
-rw-r--r-- | src/hir/from_ast_expr.cpp | 9 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 134 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 37 | ||||
-rw-r--r-- | src/parse/eTokenType.enum.h | 1 | ||||
-rw-r--r-- | src/parse/expr.cpp | 23 | ||||
-rw-r--r-- | src/parse/lex.cpp | 1 | ||||
-rw-r--r-- | src/parse/token.cpp | 5 |
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 "-"; |