summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-29 16:24:46 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-29 16:24:46 +0800
commit2a0d3a03e3f32e383ed61beb2514ac3094fffb0f (patch)
treec422e8ca7c2c89f37bfb0917278e1933fd18833c
parentaa324bf5be8e415a7e81460e6dca405a48fcbffb (diff)
downloadmrust-2a0d3a03e3f32e383ed61beb2514ac3094fffb0f.tar.gz
Twiddling root-level typecheck
-rw-r--r--src/ast/ast.cpp1
-rw-r--r--src/common.hpp1
-rw-r--r--src/convert/typecheck_params.cpp108
-rw-r--r--src/include/compile_error.hpp51
-rw-r--r--src/macros.cpp8
-rw-r--r--src/main.cpp2
-rw-r--r--src/parse/parseerror.cpp16
-rw-r--r--src/parse/parseerror.hpp46
8 files changed, 145 insertions, 88 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 40ce413b..f5d87d72 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -735,6 +735,7 @@ int TypeParams::find_name(const char* name) const
if( m_type_params[i].name() == name )
return i;
}
+ DEBUG("Type param '" << name << "' not in list");
return -1;
}
diff --git a/src/common.hpp b/src/common.hpp
index c386b729..c39f8c07 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -13,6 +13,7 @@
#include "include/debug.hpp"
#include "include/rustic.hpp" // slice and option
+#include "include/compile_error.hpp"
template <typename T>
struct LList
diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp
index c0c21898..7bb4886d 100644
--- a/src/convert/typecheck_params.cpp
+++ b/src/convert/typecheck_params.cpp
@@ -11,18 +11,39 @@ class CGenericParamChecker:
public CASTIterator
{
int m_within_expr = 0;
- ::std::vector<const AST::TypeParams*> m_params_stack;
+ struct LocalType {
+ const ::std::string name;
+ const AST::TypeParams* source_params; // if nullptr, use fixed_type
+ TypeRef fixed_type;
+
+ LocalType():
+ name("")
+ {}
+ LocalType(const ::std::string& n, const AST::TypeParams* tps):
+ name(n), source_params(tps)
+ {}
+ LocalType(const ::std::string& n, TypeRef ty):
+ name(n), source_params(nullptr), fixed_type( ::std::move(ty) )
+ {}
+
+ bool is_separator() const { return name == ""; }
+ };
+ // name == "" indicates edge of a scope
+ ::std::vector<LocalType> m_types_stack;
public:
virtual void handle_path(AST::Path& path, CASTIterator::PathMode pm) override;
virtual void handle_expr(AST::ExprNode& root) override;
- virtual void start_scope() override;
- virtual void end_scope() override;
+ void start_scope() override;
+ void local_type(::std::string name, TypeRef type) override;
+ void end_scope() override;
virtual void handle_params(AST::TypeParams& params) override;
private:
bool has_impl_for_param(const ::std::string name, const AST::Path& trait) const;
bool has_impl(const TypeRef& type, const AST::Path& trait) const;
void check_generic_params(const AST::TypeParams& info, ::std::vector<TypeRef>& types, bool allow_infer = false);
+
+ const LocalType* find_type_by_name(const ::std::string& name) const;
};
class CNodeVisitor:
@@ -40,17 +61,17 @@ bool CGenericParamChecker::has_impl_for_param(const ::std::string name, const AS
{
const AST::TypeParams* tps = nullptr;
// Locate params set that contains the passed name
- for( const auto ptr : m_params_stack )
+ for( const auto lt : m_types_stack )
{
- if( ptr )
+ if( lt.name == name )
{
- for( const auto& p : ptr->ty_params() )
- {
- if(p.name() == name) {
- tps = ptr;
- break ;
- }
+ if( lt.source_params != nullptr ) {
+ tps = lt.source_params;
+ }
+ else {
+ DEBUG("Type name '" << name << "' isn't a param");
}
+ break ;
}
}
@@ -78,7 +99,7 @@ bool CGenericParamChecker::has_impl_for_param(const ::std::string name, const AS
}
bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait) const
{
- DEBUG("(type = " << type << ", trait = " << trait << ")");
+ TRACE_FUNCTION_F("(type = " << type << ", trait = " << trait << ")");
if( type.is_type_param() )
{
// TODO: Search current scope (requires access to CGenericParamChecker) for this type,
@@ -162,17 +183,25 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s
// Not a wildcard!
// Check that the type fits the bounds applied to it
TypeRef param_type(TypeRef::TagArg(), param);
- for( const auto& bound : info.bounds() )
+ }
+ }
+
+ for( const auto& bound : info.bounds() )
+ {
+ if( bound.is_trait() )
+ {
+ auto bound_type = bound.test();
+ bound_type.resolve_args([&](const char *a){
+ if( strcmp(a, "Self") == 0 )
+ throw CompileError::Todo("Resolving 'Self' in check_generic_params");
+ return types.at(info.find_name(a));
+ });
+
+ const auto& trait = bound.bound();
+ // Check if 'type' impls 'trait'
+ if( !has_impl(bound_type, trait) )
{
- if( bound.is_trait() && bound.test() == param_type )
- {
- const auto& trait = bound.bound();
- // Check if 'type' impls 'trait'
- if( !has_impl(type, trait) )
- {
- throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<type));
- }
- }
+ throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<bound_type));
}
}
}
@@ -180,7 +209,7 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s
void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode pm)
{
- DEBUG("path = " << path);
+ TRACE_FUNCTION_F("path = " << path);
AST::PathNode& last_node = path[path.size()-1];
const AST::TypeParams* params = nullptr;
switch(path.binding().type())
@@ -205,13 +234,7 @@ void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode p
case AST::PathBinding::FUNCTION:
params = &path.binding().bound_func().params();
- try {
- check_generic_params(*params, last_node.args(), (m_within_expr > 0));
- }
- catch( const ::std::exception& e )
- {
- throw ::std::runtime_error( FMT("Checking '" << path << "', threw : " << e.what()) );
- }
+ check_generic_params(*params, last_node.args(), (m_within_expr > 0));
break;
default:
throw ::std::runtime_error("Unknown path type in CGenericParamChecker::handle_path");
@@ -229,17 +252,32 @@ void CGenericParamChecker::handle_expr(AST::ExprNode& root)
void CGenericParamChecker::start_scope()
{
- m_params_stack.push_back(nullptr);
+ m_types_stack.push_back( LocalType() );
+}
+void CGenericParamChecker::local_type(::std::string name, TypeRef type)
+{
+ throw CompileError::Todo("local_type");
}
void CGenericParamChecker::end_scope()
{
- assert( m_params_stack.size() > 0 );
- while( m_params_stack.back() != nullptr )
- m_params_stack.pop_back();
+ assert( m_types_stack.size() > 0 );
+ while( !m_types_stack.back().is_separator() )
+ m_types_stack.pop_back();
}
void CGenericParamChecker::handle_params(AST::TypeParams& params)
{
- m_params_stack.push_back( &params );
+ for( const auto& p : params.ty_params())
+ m_types_stack.push_back( LocalType(p.name(), &params) );
+}
+
+const CGenericParamChecker::LocalType* CGenericParamChecker::find_type_by_name(const ::std::string& name) const
+{
+ for( unsigned int i = m_types_stack.size(); i --; )
+ {
+ if( m_types_stack[i].name == name )
+ return &m_types_stack[i];
+ }
+ return nullptr;
}
/// Typecheck generic parameters (ensure that they match all generic bounds)
diff --git a/src/include/compile_error.hpp b/src/include/compile_error.hpp
new file mode 100644
index 00000000..f88cbe58
--- /dev/null
+++ b/src/include/compile_error.hpp
@@ -0,0 +1,51 @@
+/*
+ */
+#ifndef _COMPILE_ERROR_H_
+#define _COMPILE_ERROR_H_
+
+class TokenStream;
+
+namespace CompileError {
+
+class Base:
+ public ::std::exception
+{
+public:
+ virtual ~Base() throw();
+};
+
+class Generic:
+ public Base
+{
+ ::std::string m_message;
+public:
+ Generic(::std::string message);
+ Generic(const TokenStream& lex, ::std::string message);
+ virtual ~Generic() throw () {}
+};
+
+class BugCheck:
+ public Base
+{
+ ::std::string m_message;
+public:
+ BugCheck(::std::string message);
+ BugCheck(const TokenStream& lex, ::std::string message);
+ virtual ~BugCheck() throw () {}
+};
+
+class Todo:
+ public Base
+{
+ ::std::string m_message;
+public:
+ Todo(::std::string message);
+ Todo(const TokenStream& lex, ::std::string message);
+ virtual ~Todo() throw ();
+
+};
+
+}
+
+#endif
+
diff --git a/src/macros.cpp b/src/macros.cpp
index fa303574..d8d74d5a 100644
--- a/src/macros.cpp
+++ b/src/macros.cpp
@@ -303,7 +303,7 @@ bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat)
Parse_TT_Type(slex);
return true;
}
- catch( const ParseError::Base& e ) {
+ catch( const CompileError::Base& e ) {
return false;
}
case MacroPatEnt::PAT_EXPR:
@@ -314,7 +314,7 @@ bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat)
Parse_TT_Stmt(slex);
return true;
}
- catch( const ParseError::Base& e ) {
+ catch( const CompileError::Base& e ) {
return false;
}
case MacroPatEnt::PAT_PAT:
@@ -323,7 +323,7 @@ bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat)
Parse_TT_Pattern(slex);
return true;
}
- catch( const ParseError::Base& e ) {
+ catch( const CompileError::Base& e ) {
return false;
}
}
@@ -473,7 +473,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
return ::std::unique_ptr<TokenStream>( ret_ptr );
}
- catch(const ParseError::Base& e)
+ catch(const CompileError::Base& e)
{
DEBUG("Parse of rule " << i << " of " << name <<" failed - " << e.what());
}
diff --git a/src/main.cpp b/src/main.cpp
index bbe079fd..299301db 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -100,7 +100,7 @@ int main(int argc, char *argv[])
// Convert structures to C structures / tagged enums
//Convert_Render(flat_crate, stdout);
}
- catch(const ParseError::Base& e)
+ catch(const CompileError::Base& e)
{
::std::cerr << "Parser Error: " << e.what() << ::std::endl;
return 2;
diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp
index 01c8cced..eebad982 100644
--- a/src/parse/parseerror.cpp
+++ b/src/parse/parseerror.cpp
@@ -8,42 +8,42 @@
#include "parseerror.hpp"
#include <iostream>
-ParseError::Base::~Base() throw()
+CompileError::Base::~Base() throw()
{
}
-ParseError::Generic::Generic(::std::string message):
+CompileError::Generic::Generic(::std::string message):
m_message(message)
{
::std::cout << "Generic(" << message << ")" << ::std::endl;
}
-ParseError::Generic::Generic(const TokenStream& lex, ::std::string message)
+CompileError::Generic::Generic(const TokenStream& lex, ::std::string message)
{
::std::cout << lex.getPosition() << ": Generic(" << message << ")" << ::std::endl;
}
-ParseError::BugCheck::BugCheck(const TokenStream& lex, ::std::string message):
+CompileError::BugCheck::BugCheck(const TokenStream& lex, ::std::string message):
m_message(message)
{
::std::cout << lex.getPosition() << "BugCheck(" << message << ")" << ::std::endl;
}
-ParseError::BugCheck::BugCheck(::std::string message):
+CompileError::BugCheck::BugCheck(::std::string message):
m_message(message)
{
::std::cout << "BugCheck(" << message << ")" << ::std::endl;
}
-ParseError::Todo::Todo(::std::string message):
+CompileError::Todo::Todo(::std::string message):
m_message(message)
{
::std::cout << "Todo(" << message << ")" << ::std::endl;
}
-ParseError::Todo::Todo(const TokenStream& lex, ::std::string message):
+CompileError::Todo::Todo(const TokenStream& lex, ::std::string message):
m_message(message)
{
::std::cout << lex.getPosition() << ": Todo(" << message << ")" << ::std::endl;
}
-ParseError::Todo::~Todo() throw()
+CompileError::Todo::~Todo() throw()
{
}
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp
index 911312c5..50ec19ff 100644
--- a/src/parse/parseerror.hpp
+++ b/src/parse/parseerror.hpp
@@ -6,46 +6,12 @@
namespace ParseError {
-class Base:
- public ::std::exception
-{
-public:
- virtual ~Base() throw();
-};
-
-class Generic:
- public Base
-{
- ::std::string m_message;
-public:
- Generic(::std::string message);
- Generic(const TokenStream& lex, ::std::string message);
- virtual ~Generic() throw () {}
-};
-
-class BugCheck:
- public Base
-{
- ::std::string m_message;
-public:
- BugCheck(::std::string message);
- BugCheck(const TokenStream& lex, ::std::string message);
- virtual ~BugCheck() throw () {}
-};
-
-class Todo:
- public Base
-{
- ::std::string m_message;
-public:
- Todo(::std::string message);
- Todo(const TokenStream& lex, ::std::string message);
- virtual ~Todo() throw ();
-
-};
+using CompileError::Generic;
+using CompileError::BugCheck;
+using CompileError::Todo;
class BadChar:
- public Base
+ public CompileError::Base
{
char m_char;
public:
@@ -55,7 +21,7 @@ public:
};
class Unexpected:
- public Base
+ public CompileError::Base
{
Token m_tok;
public:
@@ -65,7 +31,7 @@ public:
};
-#define ASSERT(lex, cnd) do { if( !(cnd) ) throw ParseError::BugCheck(lex, "Assertion failed: "#cnd); } while(0)
+#define ASSERT(lex, cnd) do { if( !(cnd) ) throw CompileError::BugCheck(lex, "Assertion failed: "#cnd); } while(0)
}