diff options
author | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-20 22:24:46 +0800 |
---|---|---|
committer | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-20 22:24:46 +0800 |
commit | 15284f127f4c622bf4d67d8d8c44e1799f84e7cb (patch) | |
tree | 4b85f478b9f840eeba2bfada5d53d8c7d70b6aef /src | |
parent | 2306ea6076531132e990d038bdf759b71d9654db (diff) | |
download | mrust-15284f127f4c622bf4d67d8d8c44e1799f84e7cb.tar.gz |
Type resolution coming along, need to add 'self' to the local variable table
Diffstat (limited to 'src')
-rw-r--r-- | src/convert/ast_iterate.cpp | 8 | ||||
-rw-r--r-- | src/convert/ast_iterate.hpp | 2 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 2 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 72 | ||||
-rw-r--r-- | src/types.cpp | 15 |
5 files changed, 77 insertions, 22 deletions
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 5d8961f9..4ed63b56 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -27,7 +27,7 @@ void CASTIterator::handle_params(AST::TypeParams& params) for( auto& param : params.params() ) { if( param.is_type() ) - local_type(param.name()); + local_type( param.name(), TypeRef(TypeRef::TagArg(), param.name()) ); } for( auto& bound : params.bounds() ) { @@ -40,9 +40,9 @@ void CASTIterator::start_scope() { INDENT(); } -void CASTIterator::local_type(::std::string name) +void CASTIterator::local_type(::std::string name, TypeRef type) { - DEBUG("type " << name); + DEBUG("type " << name << " = " << type); } void CASTIterator::local_variable(bool is_mut, ::std::string name, const TypeRef& type) { @@ -171,6 +171,8 @@ void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl) // Type handle_type( impl.type() ); + local_type("Self", impl.type()); + // TODO: Associated types // Functions diff --git a/src/convert/ast_iterate.hpp b/src/convert/ast_iterate.hpp index 5a51a78d..756d8ca2 100644 --- a/src/convert/ast_iterate.hpp +++ b/src/convert/ast_iterate.hpp @@ -30,7 +30,7 @@ public: virtual void handle_params(AST::TypeParams& params); virtual void start_scope(); - virtual void local_type(::std::string name); + virtual void local_type(::std::string name, TypeRef type); virtual void local_variable(bool is_mut, ::std::string name, const TypeRef& type); virtual void local_use(::std::string name, AST::Path path); virtual void end_scope(); diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 0450a348..787b50f3 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -51,7 +51,7 @@ public: virtual void handle_module(AST::Path path, AST::Module& mod) override;
virtual void start_scope() override;
- virtual void local_type(::std::string name) override {
+ virtual void local_type(::std::string name, TypeRef type) override {
m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name)) );
}
virtual void local_variable(bool _is_mut, ::std::string name, const TypeRef& _type) override {
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 7f14ad2a..44d3056b 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -10,9 +10,21 @@ class CTypeChecker: public CASTIterator { friend class CTC_NodeVisitor; + + struct Scope { + ::std::vector< ::std::tuple<bool, ::std::string, TypeRef> > vars; + }; + + ::std::vector<Scope> m_scopes; + protected: + TypeRef& get_local(const char* name); void lookup_method(const TypeRef& type, const char* name); public: + virtual void start_scope() override; + virtual void local_variable(bool is_mut, ::std::string name, const TypeRef& type) override; + virtual void end_scope() 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 {} @@ -39,15 +51,58 @@ public: virtual void visit(AST::ExprNode_CallPath& node) override; }; +void CTypeChecker::start_scope() +{ + m_scopes.push_back( Scope() ); +} +void CTypeChecker::local_variable(bool is_mut, ::std::string name, const TypeRef& type) +{ + m_scopes.back().vars.push_back( make_tuple(is_mut, name, TypeRef(type)) ); +} +void CTypeChecker::end_scope() +{ + m_scopes.pop_back(); +} + +TypeRef& CTypeChecker::get_local(const char* name) +{ + for( auto it = m_scopes.end(); it-- != m_scopes.begin(); ) + { + for( auto it2 = it->vars.end(); it2-- != it->vars.begin(); ) + { + if( name == ::std::get<1>(*it2) ) + { + return ::std::get<2>(*it2); + } + } + } + throw ::std::runtime_error(FMT("get_local - name " << name << " not found")); +} void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn) { DEBUG("(path = " << path << ")"); + start_scope(); + + handle_params(fcn.params()); + + handle_type(fcn.rettype()); + + for( auto& arg : fcn.args() ) + { + handle_type(arg.second); + AST::Pattern pat(AST::Pattern::TagBind(), arg.first); + handle_pattern( pat, arg.second ); + } + CTC_NodeVisitor nv(*this); if( fcn.code().is_valid() ) { + fcn.code().node().get_res_type() = fcn.rettype(); fcn.code().visit_nodes(nv); } + + end_scope(); } void CTypeChecker::lookup_method(const TypeRef& type, const char* name) @@ -102,7 +157,9 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node) } else { - throw ::std::runtime_error( FMT("TODO: Get type from local : "<<p) ); + TypeRef& local_type = m_tc.get_local( p[0].name().c_str() ); + node.get_res_type().merge_with( local_type ); + local_type = node.get_res_type(); } } @@ -121,23 +178,12 @@ void CTC_NodeVisitor::visit(AST::ExprNode_LetBinding& node) // Obtain resultant type from value // Compare to binding type // - If both concrete, but different : error - if( !bind_type.is_wildcard() && !val_type.is_wildcard() ) + if( bind_type.is_concrete() && val_type.is_concrete() ) { if( bind_type != val_type ) { throw ::std::runtime_error( FMT("Type mismatch on let, expected " << bind_type << ", got " << val_type) ); } } - // - If value type concrete, but binding not : set binding to value - else if( !val_type.is_wildcard() ) - { - node.m_type = val_type; - } - // - If binding concrete, but value not : reverse propagate type (set result type of value node to binding type) - else if( !bind_type.is_wildcard() ) - { - // TODO: Check that value's current bind type's requirements fit this type - node.m_value->get_res_type() = bind_type; - } // - If neither concrete, merge requirements of both else { diff --git a/src/types.cpp b/src/types.cpp index d0bd0cc3..384c0e6e 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -34,20 +34,26 @@ void TypeRef::merge_with(const TypeRef& other) if( m_class == TypeRef::ANY ) { *this = other; + return; } if( m_class != other.m_class ) throw ::std::runtime_error("TypeRef::merge_with - Types not compatible"); + if( is_concrete() && other.is_concrete() ) + { + if( *this != other ) + throw ::std::runtime_error("TypeRef::merge_with - Types not compatible"); + return; + } + + switch(m_class) { case TypeRef::ANY: - break; case TypeRef::UNIT: case TypeRef::PRIMITIVE: - if( other != *this && other.is_concrete() ) - throw ::std::runtime_error("TypeRef::merge_with - Types not compatible"); - break; + throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); case TypeRef::TUPLE: // Other is known not to be wildcard, and is also a tuple, so it must be the same size if( m_inner_types.size() != other.m_inner_types.size() ) @@ -144,6 +150,7 @@ bool TypeRef::operator==(const TypeRef& x) const } return true; case TypeRef::GENERIC: + DEBUG(*this << " == " << x); throw ::std::runtime_error("BUGCHECK - Can't compare generic type"); case TypeRef::PATH: return m_path == x.m_path; |