summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-05-29 18:11:02 +0800
committerJohn Hodge <tpg@mutabah.net>2016-05-29 18:11:02 +0800
commitf89032cc3bb82ae691cc353ac33345bbf8a8559a (patch)
treea90294c2439029f0575c52d7a9479600fb0e7fc6 /src
parentd97f3089b257754741326bda377103d2c99f263e (diff)
downloadmrust-f89032cc3bb82ae691cc353ac33345bbf8a8559a.tar.gz
HIR - Add binding pointers to TypeRef and Pattern
Diffstat (limited to 'src')
-rw-r--r--src/hir/from_ast.cpp4
-rw-r--r--src/hir/hir.cpp4
-rw-r--r--src/hir/pattern.hpp29
-rw-r--r--src/hir/type.cpp28
-rw-r--r--src/hir/type.hpp17
-rw-r--r--src/hir/visitor.cpp2
-rw-r--r--src/hir_conv/bind.cpp262
-rw-r--r--src/hir_conv/expand_type.cpp2
-rw-r--r--src/hir_conv/main_bindings.hpp1
-rw-r--r--src/hir_typeck/expr.cpp11
-rw-r--r--src/include/tagged_union.hpp3
-rw-r--r--src/main.cpp1
12 files changed, 345 insertions, 19 deletions
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 431a75f4..8f306957 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -157,6 +157,7 @@
mv$(binding),
::HIR::Pattern::Data::make_EnumTuple({
LowerHIR_GenericPath(pat.span(), e.path),
+ nullptr, 0,
mv$(sub_patterns)
})
};
@@ -166,6 +167,7 @@
mv$(binding),
::HIR::Pattern::Data::make_StructTuple({
LowerHIR_GenericPath(pat.span(), e.path),
+ nullptr,
mv$(sub_patterns)
})
};
@@ -187,6 +189,7 @@
mv$(binding),
::HIR::Pattern::Data::make_EnumStruct({
LowerHIR_GenericPath(pat.span(), e.path),
+ nullptr, 0,
mv$(sub_patterns)
})
};
@@ -196,6 +199,7 @@
mv$(binding),
::HIR::Pattern::Data::make_Struct({
LowerHIR_GenericPath(pat.span(), e.path),
+ nullptr,
mv$(sub_patterns)
})
};
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index dede6489..b722d0f6 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -51,9 +51,9 @@ namespace {
(Diverge, return true; ),
(Primitive, return le == re;),
(Path,
- if( le.m_data.tag() != re.m_data.tag() )
+ if( le.path.m_data.tag() != re.path.m_data.tag() )
return false;
- TU_MATCH_DEF(::HIR::Path::Data, (le.m_data, re.m_data), (ple, pre),
+ TU_MATCH_DEF(::HIR::Path::Data, (le.path.m_data, re.path.m_data), (ple, pre),
(
return false;
),
diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp
index 4d7668f6..0db35059 100644
--- a/src/hir/pattern.hpp
+++ b/src/hir/pattern.hpp
@@ -10,6 +10,9 @@
namespace HIR {
+class Struct;
+class Enum;
+
struct PatternBinding
{
enum class Type {
@@ -56,13 +59,31 @@ struct Pattern
(Box, struct { ::std::unique_ptr<Pattern> sub; }),
(Ref, struct { ::HIR::BorrowType type; ::std::unique_ptr<Pattern> sub; } ),
(Tuple, struct { ::std::vector<Pattern> sub_patterns; } ),
- (StructTuple, struct { GenericPath path; ::std::vector<Pattern> sub_patterns; } ),
- (Struct, struct { GenericPath path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; } ),
+ (StructTuple, struct {
+ GenericPath path;
+ const Struct* binding;
+ ::std::vector<Pattern> sub_patterns;
+ } ),
+ (Struct, struct {
+ GenericPath path;
+ const Struct* binding;
+ ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns;
+ } ),
// Refutable
(Value, struct { Value val; } ),
(Range, struct { Value start; Value end; } ),
- (EnumTuple, struct { GenericPath path; ::std::vector<Pattern> sub_patterns; } ),
- (EnumStruct, struct { GenericPath path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; } ),
+ (EnumTuple, struct {
+ GenericPath path;
+ const Enum* binding_ptr;
+ unsigned binding_idx;
+ ::std::vector<Pattern> sub_patterns;
+ } ),
+ (EnumStruct, struct {
+ GenericPath path;
+ const Enum* binding_ptr;
+ unsigned binding_idx;
+ ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns;
+ } ),
(Slice, struct {
::std::vector<Pattern> sub_patterns;
} ),
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 6863cd12..caf042e0 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -50,7 +50,7 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
os << e;
),
(Path,
- os << e;
+ os << e.path;
),
(Generic,
os << e.name << "/*#" << e.binding << "*/";
@@ -106,6 +106,19 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
)
)
}
+
+namespace {
+ ::HIR::TypeRef::TypePathBinding clone_binding(const ::HIR::TypeRef::TypePathBinding& x) {
+ TU_MATCH(::HIR::TypeRef::TypePathBinding, (x), (e),
+ (Unbound, return ::HIR::TypeRef::TypePathBinding::make_Unbound({}); ),
+ (Opaque , return ::HIR::TypeRef::TypePathBinding::make_Opaque({}); ),
+ (Struct , return ::HIR::TypeRef::TypePathBinding(e); ),
+ (Enum , return ::HIR::TypeRef::TypePathBinding(e); )
+ )
+ throw "";
+ }
+}
+
::HIR::TypeRef HIR::TypeRef::clone() const
{
TU_MATCH(::HIR::TypeRef::Data, (m_data), (e),
@@ -119,13 +132,22 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
return ::HIR::TypeRef( Data::make_Primitive(e) );
),
(Path,
- return ::HIR::TypeRef( Data::make_Path(e.clone()) );
+ return ::HIR::TypeRef( Data::make_Path({
+ e.path.clone(),
+ clone_binding(e.binding)
+ }) );
),
(Generic,
return ::HIR::TypeRef( Data::make_Generic(e) );
),
(TraitObject,
- TODO(Span(), "TypeRef::clone() - this = " << *this);
+ ::std::vector< ::HIR::GenericPath> traits;
+ for(const auto& trait : e.m_traits)
+ traits.push_back( trait.clone() );
+ return ::HIR::TypeRef( Data::make_TraitObject({
+ mv$(traits),
+ e.m_lifetime
+ }) );
),
(Array,
TODO(Span(), "TypeRef::clone() - this = " << *this);
diff --git a/src/hir/type.hpp b/src/hir/type.hpp
index 5cfbbf10..7c2d1d0e 100644
--- a/src/hir/type.hpp
+++ b/src/hir/type.hpp
@@ -9,6 +9,9 @@
namespace HIR {
+class Struct;
+class Enum;
+
struct TypeRef;
enum class CoreType
@@ -58,13 +61,23 @@ struct TypeRef
// - Borrow
// - Pointer
+ TAGGED_UNION(TypePathBinding, Unbound,
+ (Unbound, struct {}), // Not yet bound (state during first part of lowering) - TODO kill
+ (Opaque, struct {}),
+ (Struct, const ::HIR::Struct*),
+ (Enum, const ::HIR::Enum*)
+ );
+
TAGGED_UNION(Data, Infer,
(Infer, struct {
unsigned int index = 0;
}),
(Diverge, struct {}),
(Primitive, ::HIR::CoreType),
- (Path, ::HIR::Path),
+ (Path, struct {
+ ::HIR::Path path;
+ TypePathBinding binding;
+ }),
(Generic, struct {
::std::string name;
unsigned int binding;
@@ -111,7 +124,7 @@ struct TypeRef
m_data( Data::make_Primitive(mv$(ct)) )
{}
TypeRef(::HIR::Path p):
- m_data( Data::make_Path(mv$(p)) )
+ m_data( Data::make_Path( {mv$(p), TypePathBinding()} ) )
{}
TypeRef clone() const;
diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp
index 1bc94bc7..33ac6505 100644
--- a/src/hir/visitor.cpp
+++ b/src/hir/visitor.cpp
@@ -250,7 +250,7 @@ void ::HIR::Visitor::visit_type(::HIR::TypeRef& ty)
(Primitive,
),
(Path,
- this->visit_path(e, ::HIR::Visitor::PathContext::TYPE);
+ this->visit_path(e.path, ::HIR::Visitor::PathContext::TYPE);
),
(Generic,
),
diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp
new file mode 100644
index 00000000..a4fb4d05
--- /dev/null
+++ b/src/hir_conv/bind.cpp
@@ -0,0 +1,262 @@
+/*
+ * Set binding pointers in TypeRef and Pattern
+ */
+#include "main_bindings.hpp"
+#include <hir/visitor.hpp>
+#include <hir/expr.hpp>
+#include <algorithm> // std::find_if
+
+namespace {
+
+
+ enum class Target {
+ TypeItem,
+ Struct,
+ Enum,
+ EnumVariant,
+ };
+ const void* get_type_pointer(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path, Target t)
+ {
+ if( path.m_crate_name != "" ) {
+ TODO(sp, "Handle extern crates");
+ }
+
+ const ::HIR::Module* mod = &crate.m_root_module;
+ for( unsigned int i = 0; i < path.m_components.size()-1; i ++ )
+ {
+ const auto& pc = path.m_components[i];
+ auto it = mod->m_mod_items.find( pc );
+ if( it == mod->m_mod_items.end() ) {
+ BUG(sp, "Couldn't find component " << i << " of " << path);
+ }
+
+ // If second-last, and an enum variant is desired, return the pointer to the enum
+ if( i+1 == path.m_components.size()-1 && t == Target::EnumVariant )
+ {
+ TU_IFLET(::HIR::TypeItem, it->second->ent, Enum, e2,
+ return &e2;
+ )
+ else {
+ ERROR(sp, E0000, "Expected an enum at penultimate node of " << path << ", got a " << it->second->ent.tag_str());
+ }
+ }
+ else {
+ TU_MATCH_DEF( ::HIR::TypeItem, (it->second->ent), (e2),
+ (
+ BUG(sp, "Node " << i << " of path " << path << " wasn't a module");
+ ),
+ (Module,
+ mod = &e2;
+ )
+ )
+ }
+ }
+
+ const auto& pc = path.m_components.back();
+ auto it = mod->m_mod_items.find( pc );
+ if( it == mod->m_mod_items.end() ) {
+ BUG(sp, "Couldn't find final component of " << path);
+ }
+
+ switch(t)
+ {
+ case Target::TypeItem: return &it->second->ent;
+ case Target::EnumVariant: throw "";
+
+ case Target::Struct:
+ TU_IFLET(::HIR::TypeItem, it->second->ent, Struct, e2,
+ return &e2;
+ )
+ else {
+ ERROR(sp, E0000, "Expected a struct at " << path << ", got a " << it->second->ent.tag_str());
+ }
+ break;
+ case Target::Enum:
+ TU_IFLET(::HIR::TypeItem, it->second->ent, Enum, e2,
+ return &e2;
+ )
+ else {
+ ERROR(sp, E0000, "Expected a enum at " << path << ", got a " << it->second->ent.tag_str());
+ }
+ break;
+ }
+ throw "";
+ }
+
+ class Visitor:
+ public ::HIR::Visitor
+ {
+ const ::HIR::Crate& m_crate;
+
+ public:
+ Visitor(const ::HIR::Crate& crate):
+ m_crate(crate)
+ {}
+
+ void visit_pattern(::HIR::Pattern& pat) override
+ {
+ static Span _sp = Span();
+ const Span& sp = _sp;
+
+ ::HIR::Visitor::visit_pattern(pat);
+
+ TU_MATCH_DEF(::HIR::Pattern::Data, (pat.m_data), (e),
+ (
+ ),
+ (StructTuple,
+ const auto& str = *reinterpret_cast< const ::HIR::Struct*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::Struct) );
+ TU_IFLET(::HIR::Struct::Data, str.m_data, Tuple, _,
+ // All good
+ )
+ else {
+ ERROR(sp, E0000, "Struct tuple pattern on non-tuple struct " << e.path);
+ }
+ e.binding = &str;
+ ),
+ (Struct,
+ const auto& str = *reinterpret_cast< const ::HIR::Struct*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::Struct) );
+ TU_IFLET(::HIR::Struct::Data, str.m_data, Named, _,
+ // All good
+ )
+ else {
+ ERROR(sp, E0000, "Struct pattern on field-less struct " << e.path);
+ }
+ e.binding = &str;
+ ),
+ (EnumTuple,
+ const auto& enm = *reinterpret_cast< const ::HIR::Enum*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::EnumVariant) );
+ const auto& des_name = e.path.m_path.m_components.back();
+ unsigned int idx = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x) { return x.first == des_name; }) - enm.m_variants.begin();
+ if( idx == enm.m_variants.size() ) {
+ ERROR(sp, E0000, "Couldn't find enum variant " << e.path);
+ }
+ const auto& var = enm.m_variants[idx].second;
+ TU_IFLET(::HIR::Enum::Variant, var, Tuple, _,
+ // All good
+ )
+ else {
+ ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path);
+ }
+ e.binding_ptr = &enm;
+ e.binding_idx = idx;
+ ),
+ (EnumStruct,
+ const auto& enm = *reinterpret_cast< const ::HIR::Enum*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::EnumVariant) );
+ const auto& des_name = e.path.m_path.m_components.back();
+ unsigned int idx = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x) { return x.first == des_name; }) - enm.m_variants.begin();
+ if( idx == enm.m_variants.size() ) {
+ ERROR(sp, E0000, "Couldn't find enum variant " << e.path);
+ }
+ const auto& var = enm.m_variants[idx].second;
+ TU_IFLET(::HIR::Enum::Variant, var, Struct, e,
+ // All good
+ )
+ else {
+ ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path);
+ }
+ e.binding_ptr = &enm;
+ e.binding_idx = idx;
+ )
+ )
+ }
+ void visit_type(::HIR::TypeRef& ty) override
+ {
+ static Span _sp = Span();
+ const Span& sp = _sp;
+
+ ::HIR::Visitor::visit_type(ty);
+
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e,
+ TU_IFLET( ::HIR::Path::Data, e.path.m_data, Generic, e2,
+ const auto& item = *reinterpret_cast< const ::HIR::TypeItem*>( get_type_pointer(sp, m_crate, e2.m_path, Target::TypeItem) );
+ TU_MATCH_DEF( ::HIR::TypeItem, (item), (e3),
+ (
+ ERROR(sp, E0000, "Unexpected item type returned for " << e2.m_path << " - " << item.tag_str());
+ ),
+ (Struct,
+ e.binding = ::HIR::TypeRef::TypePathBinding::make_Struct(&e3);
+ ),
+ (Enum,
+ e.binding = ::HIR::TypeRef::TypePathBinding::make_Enum(&e3);
+ ),
+ (Trait,
+ ::std::vector< ::HIR::GenericPath> traits;
+ traits.push_back( mv$(e2) );
+ ty.m_data = ::HIR::TypeRef::Data::make_TraitObject({ mv$(traits), {} });
+ )
+ )
+ )
+ else {
+ e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
+ }
+ )
+ }
+
+ void visit_expr(::HIR::ExprPtr& expr) override
+ {
+ struct ExprVisitor:
+ public ::HIR::ExprVisitorDef
+ {
+ Visitor& upper_visitor;
+
+ ExprVisitor(Visitor& uv):
+ upper_visitor(uv)
+ {}
+
+ void visit(::HIR::ExprNode_Let& node) override
+ {
+ upper_visitor.visit_type(node.m_type);
+ upper_visitor.visit_pattern(node.m_pattern);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_Match& node) override
+ {
+ for(auto& arm : node.m_arms)
+ {
+ for(auto& pat : arm.m_patterns)
+ upper_visitor.visit_pattern(pat);
+ }
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_Cast& node) override
+ {
+ upper_visitor.visit_type(node.m_type);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+
+ void visit(::HIR::ExprNode_CallPath& node) override
+ {
+ upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_CallMethod& node) override
+ {
+ upper_visitor.visit_path_params(node.m_params);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+
+ void visit(::HIR::ExprNode_Closure& node) override
+ {
+ upper_visitor.visit_type(node.m_return);
+ for(auto& arg : node.m_args) {
+ upper_visitor.visit_pattern(arg.first);
+ upper_visitor.visit_type(arg.second);
+ }
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ };
+
+ if( &*expr != nullptr )
+ {
+ ExprVisitor v { *this };
+ (*expr).visit(v);
+ }
+ }
+ };
+}
+
+void ConvertHIR_Bind(::HIR::Crate& crate)
+{
+ Visitor exp { crate };
+ exp.visit_crate( crate );
+}
diff --git a/src/hir_conv/expand_type.cpp b/src/hir_conv/expand_type.cpp
index 0d8eb85e..2b2ba4c6 100644
--- a/src/hir_conv/expand_type.cpp
+++ b/src/hir_conv/expand_type.cpp
@@ -73,7 +73,7 @@ public:
::HIR::Visitor::visit_type(ty);
TU_IFLET(::HIR::TypeRef::Data, (ty.m_data), Path, (e),
- auto new_type = ConvertHIR_ExpandAliases_GetExpansion(m_crate, e);
+ auto new_type = ConvertHIR_ExpandAliases_GetExpansion(m_crate, e.path);
if( ! new_type.m_data.is_Infer() ) {
DEBUG("Replacing " << ty << " with " << new_type);
ty = mv$(new_type);
diff --git a/src/hir_conv/main_bindings.hpp b/src/hir_conv/main_bindings.hpp
index fc288975..732e1722 100644
--- a/src/hir_conv/main_bindings.hpp
+++ b/src/hir_conv/main_bindings.hpp
@@ -8,4 +8,5 @@ namespace HIR {
extern void ConvertHIR_ResolveUFCS(::HIR::Crate& crate);
extern void ConvertHIR_ExpandAliases(::HIR::Crate& crate);
+extern void ConvertHIR_Bind(::HIR::Crate& crate);
extern void ConvertHIR_ConstantEvaluate(::HIR::Crate& hir_crate);
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 5fc7bffe..cb95fb42 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -394,7 +394,7 @@ namespace {
(Struct,
if( ty.m_data.is_Infer() ) {
//TODO: Does this lead to issues with generic parameters?
- ty.m_data = ::HIR::TypeRef::Data::make_Path( e.path.clone() );
+ ty.m_data = ::HIR::TypeRef::Data::make_Path( {e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)} );
this->mark_change();
}
@@ -404,11 +404,12 @@ namespace {
),
(Infer, throw "";),
(Path,
- if( ! te.m_data.is_Generic() ) {
- ERROR(sp, E0000, "UFCS path being destructured - " << te);
+ if( ! te.path.m_data.is_Generic() ) {
+ ERROR(sp, E0000, "UFCS path being destructured - " << te.path);
}
- const auto& gp = te.m_data.as_Generic();
- TODO(sp, "Struct - destructure - " << te);
+ const auto& s = *te.binding.as_Struct();
+ assert(&s);
+ TODO(sp, "Struct - destructure - " << te.path);
)
)
),
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index 213ebceb..e0a30dd0 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -203,11 +203,12 @@ class _name TU_EXP _inherit { \
*/ ~_name() { switch(m_tag) { case TAGDEAD: break; TU_DEST_CASES _variants } m_tag = TAGDEAD; } \
\
Tag tag() const { return m_tag; }\
+ const char* tag_str() const { return tag_to_str(m_tag); }\
TU_CONSS(_name, TU_EXP _variants) \
/*
*/ static const char *tag_to_str(Tag tag) { \
switch(tag) {/*
-*/ case TAGDEAD: return "";/*
+*/ case TAGDEAD: return "ERR:DEAD";/*
*/ TU_TOSTR_CASES _variants/*
*/ } return ""; \
}/*
diff --git a/src/main.cpp b/src/main.cpp
index 09d16dfe..f5dd63a3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -157,6 +157,7 @@ int main(int argc, char *argv[])
});
CompilePhaseV("Resolve UFCS paths", [&]() {
ConvertHIR_ResolveUFCS(*hir_crate);
+ ConvertHIR_Bind(*hir_crate);
});
CompilePhaseV("Constant Evaluate", [&]() {
ConvertHIR_ConstantEvaluate(*hir_crate);