From 15284f127f4c622bf4d67d8d8c44e1799f84e7cb Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Tue, 20 Jan 2015 22:24:46 +0800 Subject: Type resolution coming along, need to add 'self' to the local variable table --- src/convert/ast_iterate.cpp | 8 +++-- src/convert/ast_iterate.hpp | 2 +- src/convert/resolve.cpp | 2 +- src/convert/typecheck_expr.cpp | 72 ++++++++++++++++++++++++++++++++++-------- src/types.cpp | 15 ++++++--- 5 files changed, 77 insertions(+), 22 deletions(-) (limited to 'src') 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 > vars; + }; + + ::std::vector 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 : "<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; -- cgit v1.2.3