diff options
author | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-22 14:51:07 +0800 |
---|---|---|
committer | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-22 14:51:07 +0800 |
commit | 76d70d4cbfbdf09082d35a224a4c7f2d2b501974 (patch) | |
tree | a0b3ce0ea0f624e56e57edc6850542e9f4081eae | |
parent | 8d1acfa3993e64b0266365379602799350855f3f (diff) | |
download | mrust-76d70d4cbfbdf09082d35a224a4c7f2d2b501974.tar.gz |
Added bounds to _ types, propagating type params further (and replacing when needed)
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | samples/std.rs | 1 | ||||
-rw-r--r-- | src/ast/ast.cpp | 5 | ||||
-rw-r--r-- | src/ast/ast.hpp | 1 | ||||
-rw-r--r-- | src/common.hpp | 17 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 8 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 85 | ||||
-rw-r--r-- | src/types.cpp | 5 | ||||
-rw-r--r-- | src/types.hpp | 12 |
9 files changed, 134 insertions, 8 deletions
@@ -3,9 +3,9 @@ EXESUF ?= CXX ?= g++ V ?= @ -LINKFLAGS := +LINKFLAGS := -g LIBS := -CXXFLAGS := -Wall -std=c++11 +CXXFLAGS := -g -Wall -std=c++11 CPPFLAGS := -I src/include/ @@ -29,8 +29,8 @@ clean: test: $(BIN) samples/1.rs mkdir -p output/ - time $(BIN) samples/std.rs --emit ast -o output/std.ast - time $(BIN) samples/1.rs --crate-path output/std.ast + time $(DBG) $(BIN) samples/std.rs --emit ast -o output/std.ast + time $(DBG) $(BIN) samples/1.rs --crate-path output/std.ast $(BIN): $(OBJ) @mkdir -p $(dir $@) diff --git a/samples/std.rs b/samples/std.rs index a0110c40..a44ae54e 100644 --- a/samples/std.rs +++ b/samples/std.rs @@ -27,6 +27,7 @@ pub mod io pub trait Reader { + fn read_byte(&mut self) -> IoResult<u8>; } } diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 7fb84100..a5af04f5 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -105,6 +105,11 @@ const Module& Crate::get_root_module(const ::std::string& name) const { throw ParseError::Generic("crate name unknown");
}
+Impl& Crate::find_impl(const TypeRef& trait, const TypeRef& type)
+{
+ throw ParseError::Generic( FMT("TODO: Lookup impl of " << trait << " for type " << type));
+}
+
Function& Crate::lookup_method(const TypeRef& type, const char *name)
{
throw ParseError::Generic( FMT("TODO: Lookup method "<<name<<" for type " <<type));
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index b56bd26a..94ffbb79 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -499,6 +499,7 @@ public: ::std::map< ::std::string, ExternCrate>& extern_crates() { return m_extern_crates; }
const ::std::map< ::std::string, ExternCrate>& extern_crates() const { return m_extern_crates; }
+ Impl& find_impl(const TypeRef& trait, const TypeRef& type);
Function& lookup_method(const TypeRef& type, const char *name);
void load_extern_crate(::std::string name);
diff --git a/src/common.hpp b/src/common.hpp index b9b90270..c73db0e8 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -5,6 +5,7 @@ #include <iostream> #include <vector> +#include <map> #include <cassert> #include <sstream> @@ -115,6 +116,22 @@ inline ::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v) return os; } +template <typename T, typename U> +inline ::std::ostream& operator<<(::std::ostream& os, const ::std::map<T,U>& v) { + if( v.size() > 0 ) + { + bool is_first = true; + for( const auto& i : v ) + { + if(!is_first) + os << ", "; + is_first = false; + os << i.first << ": " << i.second; + } + } + return os; +} + } #endif diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 787b50f3..4c79a401 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -274,6 +274,14 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) return ;
}
}
+ for( const auto& item : m_module->type_aliases() )
+ {
+ if( item.name == path[0].name() ) {
+ path = m_module_path + path;
+ path.resolve( m_crate );
+ return ;
+ }
+ }
// Values / Functions
for( const auto& item_fcn : m_module->functions() )
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 21ad40b8..b5ee6e0d 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -14,6 +14,7 @@ class CTypeChecker: struct Scope { ::std::vector< ::std::tuple<bool, ::std::string, TypeRef> > vars; ::std::vector< ::std::tuple< ::std::string, TypeRef> > types; + ::std::map< ::std::string, TypeRef > params; }; AST::Crate& m_crate; @@ -29,6 +30,8 @@ public: virtual void local_type(::std::string name, TypeRef type) override; virtual void end_scope() override; + virtual void handle_params(AST::TypeParams& params) override; + virtual void handle_function(AST::Path path, AST::Function& fcn) override; // - Ignore all non-function items on this pass virtual void handle_enum(AST::Path path, AST::Enum& ) override {} @@ -38,6 +41,7 @@ public: private: TypeRef& get_local_var(const char* name); const TypeRef& get_local_type(const char* name); + const TypeRef& get_type_param(const char* name); void lookup_method(const TypeRef& type, const char* name); }; class CTC_NodeVisitor: @@ -82,6 +86,26 @@ void CTypeChecker::end_scope() m_scopes.pop_back(); } +void CTypeChecker::handle_params(AST::TypeParams& params) +{ + ::std::map<std::string,TypeRef> trs; + + for( const auto& param : params.params() ) + { + trs.insert( make_pair(param.name(), TypeRef()) ); + } + + for( const auto& bound : params.bounds() ) + { + int i = params.find_name(bound.name().c_str()); + assert(i >= 0); + trs[bound.name()].add_trait( bound.type() ); + } + + assert(m_scopes.back().params.size() == 0); + m_scopes.back().params = trs; +} + TypeRef& CTypeChecker::get_local_var(const char* name) { for( auto it = m_scopes.end(); it-- != m_scopes.begin(); ) @@ -94,7 +118,7 @@ TypeRef& CTypeChecker::get_local_var(const char* name) } } } - throw ::std::runtime_error(FMT("get_local_type - name " << name << " not found")); + throw ::std::runtime_error(FMT("get_local_var - name " << name << " not found")); } const TypeRef& CTypeChecker::get_local_type(const char* name) { @@ -110,6 +134,21 @@ const TypeRef& CTypeChecker::get_local_type(const char* name) } throw ::std::runtime_error(FMT("get_local_type - name " << name << " not found")); } +const TypeRef& CTypeChecker::get_type_param(const char* name) +{ + DEBUG("name = " << name); + for( auto it = m_scopes.end(); it-- != m_scopes.begin(); ) + { + DEBUG("- params = " << it->params); + auto ent = it->params.find(name); + if( ent != it->params.end() ) + { + DEBUG("> match " << ent->second); + return ent->second; + } + } + throw ::std::runtime_error(FMT("get_type_param - name " << name << " not found")); +} void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn) { @@ -339,13 +378,53 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) // - TODO: Support case where a trait is known throw ::std::runtime_error("Unknown type in CallMethod"); } + else if( type.is_type_param() ) + { + const char *name = type.type_param().c_str(); + // Find this name in the current set of type params + const TypeRef& p_type = m_tc.get_type_param(name); + // Iterate bounds on type param + TypeRef ret_type; + for( const auto& t : p_type.traits() ) + { + DEBUG("- Trait " << t.path()); + const AST::Trait& trait = t.path().bound_trait(); + // - Find method on one of them + for( const auto& m : trait.functions() ) + { + DEBUG(" > method: " << m.name << " search: " << node.m_method.name()); + if( m.name == node.m_method.name() ) + { + DEBUG(" > Found method"); + if( m.data.params().n_params() ) + { + throw ::std::runtime_error("TODO: Call method with params"); + } + ret_type = m.data.rettype(); + } + } + } + if( ret_type.is_wildcard() ) + { + throw ::std::runtime_error("Couldn't find method"); + } + } else { + TypeRef ltype = type; + DEBUG("Resolving args in " << ltype); + ltype.resolve_args( [&](const char* name) { + DEBUG("- Looking up " << name); + return m_tc.get_type_param(name); + } ); + // TODO: Replace generic references in 'type' (copying the type) with + // '_: Bounds' (allowing method lookup to succeed) // - Search for a method on this type - AST::Function& fcn = m_tc.m_crate.lookup_method(type, node.m_method.name().c_str()); + // TODO: Requires passing knowledge of in-scope traits (or trying traits) + AST::Function& fcn = m_tc.m_crate.lookup_method(ltype, node.m_method.name().c_str()); if( fcn.params().n_params() != node.m_method.args().size() ) { - throw ::std::runtime_error("TODO: CallMethod with param count mismatch"); + throw ::std::runtime_error("CallMethod with param count mismatch"); } if( fcn.params().n_params() ) { diff --git a/src/types.cpp b/src/types.cpp index 7445dd03..e0287d01 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -85,6 +85,7 @@ void TypeRef::merge_with(const TypeRef& other) /// Resolve all Generic/Argument types to the value returned by the passed closure void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn) { + DEBUG("" << *this); switch(m_class) { case TypeRef::ANY: @@ -99,6 +100,7 @@ void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn) case TypeRef::ARRAY: for( auto& t : m_inner_types ) t.resolve_args(fcn); + break; case TypeRef::GENERIC: *this = fcn(m_path[0].name().c_str()); break; @@ -255,6 +257,9 @@ bool TypeRef::operator==(const TypeRef& x) const case TypeRef::ANY: //os << "TagAny"; os << "_"; + if( tr.m_inner_types.size() ) { + os << ": {" << tr.m_inner_types << "}"; + } break; case TypeRef::UNIT: //os << "TagUnit"; diff --git a/src/types.hpp b/src/types.hpp index 27d74662..b40c9424 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -53,6 +53,11 @@ public: TypeRef():
m_class(ANY)
{}
+ struct TagBoundedAny {};
+ TypeRef(TagBoundedAny, ::std::vector<TypeRef> traits):
+ m_class(ANY),
+ m_inner_types( ::std::move(traits) )
+ {}
struct TagUnit {}; // unit maps to a zero-length tuple, just easier to type
TypeRef(TagUnit):
@@ -138,8 +143,13 @@ public: bool is_reference() const { return m_class == REFERENCE; }
const ::std::string& type_param() const { assert(is_type_param()); return m_path[0].name(); }
AST::Path& path() { assert(is_path() || m_class == ASSOCIATED); return m_path; }
+ const AST::Path& path() const { assert(is_path() || m_class == ASSOCIATED); return m_path; }
::std::vector<TypeRef>& sub_types() { return m_inner_types; }
-
+ const ::std::vector<TypeRef>& sub_types() const { return m_inner_types; }
+
+ void add_trait(TypeRef trait) { assert(is_wildcard()); m_inner_types.push_back( ::std::move(trait) ); }
+ const ::std::vector<TypeRef>& traits() const { assert(is_wildcard()); return m_inner_types; }
+
bool operator==(const TypeRef& x) const;
bool operator!=(const TypeRef& x) const { return !(*this == x); }
|