summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge (sonata) <tpg@mutabah.net>2015-01-22 14:51:07 +0800
committerJohn Hodge (sonata) <tpg@mutabah.net>2015-01-22 14:51:07 +0800
commit76d70d4cbfbdf09082d35a224a4c7f2d2b501974 (patch)
treea0b3ce0ea0f624e56e57edc6850542e9f4081eae
parent8d1acfa3993e64b0266365379602799350855f3f (diff)
downloadmrust-76d70d4cbfbdf09082d35a224a4c7f2d2b501974.tar.gz
Added bounds to _ types, propagating type params further (and replacing when needed)
-rw-r--r--Makefile8
-rw-r--r--samples/std.rs1
-rw-r--r--src/ast/ast.cpp5
-rw-r--r--src/ast/ast.hpp1
-rw-r--r--src/common.hpp17
-rw-r--r--src/convert/resolve.cpp8
-rw-r--r--src/convert/typecheck_expr.cpp85
-rw-r--r--src/types.cpp5
-rw-r--r--src/types.hpp12
9 files changed, 134 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 12469c9b..6cff5d01 100644
--- a/Makefile
+++ b/Makefile
@@ -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); }