summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge (sonata) <tpg@mutabah.net>2015-01-20 22:24:46 +0800
committerJohn Hodge (sonata) <tpg@mutabah.net>2015-01-20 22:24:46 +0800
commit15284f127f4c622bf4d67d8d8c44e1799f84e7cb (patch)
tree4b85f478b9f840eeba2bfada5d53d8c7d70b6aef /src
parent2306ea6076531132e990d038bdf759b71d9654db (diff)
downloadmrust-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.cpp8
-rw-r--r--src/convert/ast_iterate.hpp2
-rw-r--r--src/convert/resolve.cpp2
-rw-r--r--src/convert/typecheck_expr.cpp72
-rw-r--r--src/types.cpp15
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;