summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-04 12:33:35 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-04 12:33:35 +0800
commite33d210a4a85e91abe04f1874f460b6e60c6b5e0 (patch)
tree96668e07ac5972f3f25b1a5369831a0edea3ea35 /src
parentef9d2edb3752a19b827240e91ef3fea7bc354586 (diff)
downloadmrust-e33d210a4a85e91abe04f1874f460b6e60c6b5e0.tar.gz
Byte string literals in AST, infrastructure for coercions
Diffstat (limited to 'src')
-rw-r--r--src/ast/expr.cpp8
-rw-r--r--src/ast/expr.hpp15
-rw-r--r--src/dump_as_rust.cpp4
-rw-r--r--src/expand/mod.cpp1
-rw-r--r--src/hir/expr_ptr.cpp6
-rw-r--r--src/hir/expr_ptr.hpp9
-rw-r--r--src/hir/from_ast_expr.cpp4
-rw-r--r--src/hir_conv/constant_evaluation.cpp3
-rw-r--r--src/hir_typeck/expr.cpp63
-rw-r--r--src/parse/expr.cpp11
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: