diff options
author | John Hodge <tpg@mutabah.net> | 2016-06-04 12:33:35 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-06-04 12:33:35 +0800 |
commit | e33d210a4a85e91abe04f1874f460b6e60c6b5e0 (patch) | |
tree | 96668e07ac5972f3f25b1a5369831a0edea3ea35 /src | |
parent | ef9d2edb3752a19b827240e91ef3fea7bc354586 (diff) | |
download | mrust-e33d210a4a85e91abe04f1874f460b6e60c6b5e0.tar.gz |
Byte string literals in AST, infrastructure for coercions
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/expr.cpp | 8 | ||||
-rw-r--r-- | src/ast/expr.hpp | 15 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 4 | ||||
-rw-r--r-- | src/expand/mod.cpp | 1 | ||||
-rw-r--r-- | src/hir/expr_ptr.cpp | 6 | ||||
-rw-r--r-- | src/hir/expr_ptr.hpp | 9 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 4 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 3 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 63 | ||||
-rw-r--r-- | src/parse/expr.cpp | 11 |
10 files changed, 97 insertions, 27 deletions
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 42010868..24e6ab3b 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -363,6 +363,13 @@ NODE(ExprNode_String, { },{ return NEWNODE(ExprNode_String, m_value); }) +NODE(ExprNode_ByteString, { + s.item(m_value); +},{ + os << "b\"" << m_value << "\""; +},{ + return NEWNODE(ExprNode_ByteString, m_value); +}) NODE(ExprNode_Closure, { s.item(m_args); @@ -708,6 +715,7 @@ NV(ExprNode_Integer, {(void)node;}) NV(ExprNode_Float, {(void)node;}) NV(ExprNode_Bool, {(void)node;}) NV(ExprNode_String, {(void)node;}) +NV(ExprNode_ByteString, {(void)node;}) NV(ExprNode_Closure, { diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index eab6f260..bddada90 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -365,6 +365,19 @@ struct ExprNode_String: NODE_METHODS(); }; +// Literal byte string +struct ExprNode_ByteString: + public ExprNode +{ + ::std::string m_value; + + ExprNode_ByteString() {} + ExprNode_ByteString(::std::string value): + m_value( ::std::move(value) ) + {} + + NODE_METHODS(); +}; // Closure / Lambda struct ExprNode_Closure: @@ -613,6 +626,7 @@ public: NT(ExprNode_Float); NT(ExprNode_Bool); NT(ExprNode_String); + NT(ExprNode_ByteString); NT(ExprNode_Closure); NT(ExprNode_StructLiteral); NT(ExprNode_Array); @@ -655,6 +669,7 @@ public: NT(ExprNode_Float); NT(ExprNode_Bool); NT(ExprNode_String); + NT(ExprNode_ByteString); NT(ExprNode_Closure); NT(ExprNode_StructLiteral); NT(ExprNode_Array); diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 2d079223..536af263 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -378,6 +378,10 @@ public: m_expr_root = false; m_os << "\"" << n.m_value << "\""; } + virtual void visit(AST::ExprNode_ByteString& n) override { + m_expr_root = false; + m_os << "b\"" << n.m_value << "\""; + } virtual void visit(AST::ExprNode_StructLiteral& n) override { m_expr_root = false; diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 62425f86..617a2fc9 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -444,6 +444,7 @@ struct CExpandExpr: void visit(::AST::ExprNode_Float& node) override { } void visit(::AST::ExprNode_Bool& node) override { } void visit(::AST::ExprNode_String& node) override { } + void visit(::AST::ExprNode_ByteString& node) override { } void visit(::AST::ExprNode_Closure& node) override { for(auto& arg : node.m_args) { Expand_Pattern(is_early, crate, modstack, this->cur_mod(), arg.first); diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp index c8136097..dc20f84c 100644 --- a/src/hir/expr_ptr.cpp +++ b/src/hir/expr_ptr.cpp @@ -15,3 +15,9 @@ { delete node; } +::std::unique_ptr< ::HIR::ExprNode> HIR::ExprPtr::into_unique() +{ + ::std::unique_ptr< ::HIR::ExprNode> rv( this->node ); + this->node = nullptr; + return rv; +} diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index 0dcc300a..6378b052 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -19,8 +19,17 @@ public: { x.node = nullptr; } + ExprPtr& operator=(ExprPtr&& x) + { + this->~ExprPtr(); + node = x.node; + x.node = nullptr; + return *this; + } ~ExprPtr(); + ::std::unique_ptr< ::HIR::ExprNode> into_unique(); + ::HIR::ExprNode& operator*() { return *node; } const ::HIR::ExprNode& operator*() const { return *node; } ::HIR::ExprNode* operator->() { return node; } diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index b26b7874..c48a6ee9 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -471,6 +471,10 @@ struct LowerHIR_ExprNode_Visitor: virtual void visit(::AST::ExprNode_String& v) override { m_rv.reset( new ::HIR::ExprNode_Literal( ::HIR::ExprNode_Literal::Data::make_String( v.m_value ) ) ); } + virtual void visit(::AST::ExprNode_ByteString& v) override { + ::std::vector<char> dat { v.m_value.begin(), v.m_value.end() }; + m_rv.reset( new ::HIR::ExprNode_Literal( ::HIR::ExprNode_Literal::Data::make_ByteString( mv$(dat) ) ) ); + } virtual void visit(::AST::ExprNode_Closure& v) override { ::HIR::ExprNode_Closure::args_t args; for(const auto& arg : v.m_args) { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index e64dd289..06abe38a 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -406,8 +406,7 @@ namespace { m_rv = ::HIR::Literal(e); ), (ByteString, - TODO(node.span(), "Byte literal in constant"); - //m_rv = ::HIR::Literal::make_String(e); + m_rv = ::HIR::Literal::make_String({e.begin(), e.end()}); ) ) } diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index b043aaa2..0018fc9d 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -738,7 +738,11 @@ namespace { // Adds a rule that two types must be equal // - NOTE: The ordering does matter, as the righthand side will get unsizing/deref coercions applied if possible // TODO: Support coercions - void apply_equality(const Span& sp, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right) + /// \param sp Span for reporting errors + /// \param left Lefthand type (destination for coercions) + /// \param right Righthand type (source for coercions) + /// \param node_ptr Pointer to ExprNodeP, updated with new nodes for coercions + void apply_equality(const Span& sp, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right, ::HIR::ExprNodeP* node_ptr_ptr = nullptr) { TRACE_FUNCTION_F(left << ", " << right); assert( ! left.m_data.is_Infer() || left.m_data.as_Infer().index != ~0u ); @@ -834,7 +838,7 @@ namespace { TODO(sp, "Recurse in apply_equality Array - " << l_t << " and " << r_t); ), (Slice, - TODO(sp, "Recurse in apply_equality Slice - " << l_t << " and " << r_t); + this->apply_equality(sp, *l_e.inner, *r_e.inner); ), (Tuple, if( l_e.size() != r_e.size() ) { @@ -847,10 +851,30 @@ namespace { ), (Borrow, if( l_e.type != r_e.type ) { - // TODO: This could be allowed (using coercions) + // TODO: This could be allowed if left == Shared && right == Unique (reborrowing) ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t << " - Borrow classes differ"); } - // TODO: Support coercions (have to be done here)? + // ------------------ + // Coercions! + // ------------------ + if( node_ptr_ptr != nullptr ) + { + // - If left is a trait object, right can unsize + // - If left is a slice, right can unsize/deref + if( l_e.inner->m_data.is_Slice() && !r_e.inner->m_data.is_Slice() ) + { + const auto& left_slice = l_e.inner->m_data.as_Slice(); + TU_IFLET(::HIR::TypeRef::Data, r_e.inner->m_data, Array, right_array, + this->apply_equality(sp, *left_slice.inner, *right_array.inner); + TODO(sp, "Apply slice unsize coerce operation - " << l_t << " <- " << r_t); + ) + else + { + // Apply deref coercions + } + } + // - If right has a deref chain to left, build it + } this->apply_equality(sp, *l_e.inner, *r_e.inner); ), (Pointer, @@ -933,7 +957,7 @@ namespace { TRACE_FUNCTION_F("{ }"); if( node.m_nodes.size() ) { - this->context.apply_equality(node.span(), node.m_res_type, node.m_nodes.back()->m_res_type); + this->context.apply_equality(node.span(), node.m_res_type, node.m_nodes.back()->m_res_type, &node.m_nodes.back()); } else { this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef( ::HIR::TypeRef::TagUnit() )); @@ -948,7 +972,7 @@ namespace { this->context.add_binding(node.m_pattern, node.m_type); if( node.m_value ) { - this->context.apply_equality(node.span(), node.m_type, node.m_value->m_res_type); + this->context.apply_equality(node.span(), node.m_type, node.m_value->m_res_type, &node.m_value); } } @@ -1003,28 +1027,35 @@ namespace { }; }; -void Typecheck_Code(TypecheckContext context, const ::HIR::TypeRef& result_type, ::HIR::ExprNode& root_node) +void Typecheck_Code(TypecheckContext context, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr) { TRACE_FUNCTION; // 1. Enumerate inferrence variables and assign indexes to them { ExprVisitor_Enum visitor { context }; - root_node.visit( visitor ); + expr->visit( visitor ); } + // - Apply equality between the node result and the expected type DEBUG("- Apply RV"); - context.apply_equality(root_node.span(), result_type, root_node.m_res_type); + { + // Convert ExprPtr into unique_ptr for the execution of this function + auto root_ptr = expr.into_unique(); + context.apply_equality(root_ptr->span(), result_type, root_ptr->m_res_type, &root_ptr); + expr = ::HIR::ExprPtr( mv$(root_ptr) ); + } + context.dump(); // 2. Iterate through nodes applying rules until nothing changes { ExprVisitor_Run visitor { context }; do { - root_node.visit( visitor ); + expr->visit( visitor ); } while( context.take_changed() ); } // 3. Check that there's no unresolved types left - // TODO + // TODO: Check for completed type resolution context.dump(); } @@ -1124,7 +1155,7 @@ namespace { this->visit_type( *e.inner ); TypecheckContext typeck_context { }; DEBUG("Array size"); - Typecheck_Code( mv$(typeck_context), ::HIR::TypeRef(::HIR::CoreType::Usize), *e.size ); + Typecheck_Code( mv$(typeck_context), ::HIR::TypeRef(::HIR::CoreType::Usize), e.size ); ) else { ::HIR::Visitor::visit_type(ty); @@ -1142,7 +1173,7 @@ namespace { typeck_context.add_binding( arg.first, arg.second ); } DEBUG("Function code"); - Typecheck_Code( mv$(typeck_context), item.m_return, *item.m_code ); + Typecheck_Code( mv$(typeck_context), item.m_return, item.m_code ); } } void visit_static(::HIR::Static& item) override { @@ -1151,7 +1182,7 @@ namespace { { TypecheckContext typeck_context { }; DEBUG("Static value"); - Typecheck_Code( mv$(typeck_context), item.m_type, *item.m_value ); + Typecheck_Code( mv$(typeck_context), item.m_type, item.m_value ); } } void visit_constant(::HIR::Constant& item) override { @@ -1160,7 +1191,7 @@ namespace { { TypecheckContext typeck_context { }; DEBUG("Const value"); - Typecheck_Code( mv$(typeck_context), item.m_type, *item.m_value ); + Typecheck_Code( mv$(typeck_context), item.m_type, item.m_value ); } } void visit_enum(::HIR::Enum& item) override { @@ -1175,7 +1206,7 @@ namespace { TU_IFLET(::HIR::Enum::Variant, var.second, Value, e, TypecheckContext typeck_context { }; DEBUG("Enum value"); - Typecheck_Code( mv$(typeck_context), enum_type, *e ); + Typecheck_Code( mv$(typeck_context), enum_type, e ); ) } } diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 37bc03e7..3dbdd1d3 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -1064,15 +1064,8 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return NEWNODE( AST::ExprNode_Float, tok.floatval(), tok.datatype() );
case TOK_STRING:
return NEWNODE( AST::ExprNode_String, tok.str() );
- case TOK_BYTESTRING: {
- ::std::vector<ExprNodeP> items;
- for(char b: tok.str()) {
- items.push_back( NEWNODE( AST::ExprNode_Integer, b, CORETYPE_U8 ) );
- }
- return NEWNODE( AST::ExprNode_Array, ::std::move(items) );
- }
- // TODO: Correct type here
- return NEWNODE( AST::ExprNode_String, tok.str() );
+ case TOK_BYTESTRING:
+ return NEWNODE( AST::ExprNode_ByteString, tok.str() );
case TOK_RWORD_TRUE:
return NEWNODE( AST::ExprNode_Bool, true );
case TOK_RWORD_FALSE:
|