diff options
author | John Hodge <tpg@mutabah.net> | 2016-05-29 18:11:02 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-05-29 18:11:02 +0800 |
commit | f89032cc3bb82ae691cc353ac33345bbf8a8559a (patch) | |
tree | a90294c2439029f0575c52d7a9479600fb0e7fc6 /src | |
parent | d97f3089b257754741326bda377103d2c99f263e (diff) | |
download | mrust-f89032cc3bb82ae691cc353ac33345bbf8a8559a.tar.gz |
HIR - Add binding pointers to TypeRef and Pattern
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/from_ast.cpp | 4 | ||||
-rw-r--r-- | src/hir/hir.cpp | 4 | ||||
-rw-r--r-- | src/hir/pattern.hpp | 29 | ||||
-rw-r--r-- | src/hir/type.cpp | 28 | ||||
-rw-r--r-- | src/hir/type.hpp | 17 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 2 | ||||
-rw-r--r-- | src/hir_conv/bind.cpp | 262 | ||||
-rw-r--r-- | src/hir_conv/expand_type.cpp | 2 | ||||
-rw-r--r-- | src/hir_conv/main_bindings.hpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 11 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 3 | ||||
-rw-r--r-- | src/main.cpp | 1 |
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);
|