From 2a0d3a03e3f32e383ed61beb2514ac3094fffb0f Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 29 Mar 2015 16:24:46 +0800 Subject: Twiddling root-level typecheck --- src/ast/ast.cpp | 1 + src/common.hpp | 1 + src/convert/typecheck_params.cpp | 108 ++++++++++++++++++++++++++------------- src/include/compile_error.hpp | 51 ++++++++++++++++++ src/macros.cpp | 8 +-- src/main.cpp | 2 +- src/parse/parseerror.cpp | 16 +++--- src/parse/parseerror.hpp | 46 +++-------------- 8 files changed, 145 insertions(+), 88 deletions(-) create mode 100644 src/include/compile_error.hpp (limited to 'src') 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 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 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 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& 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 "< 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( ¶ms ); + for( const auto& p : params.ty_params()) + m_types_stack.push_back( LocalType(p.name(), ¶ms) ); +} + +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( 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 -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) } -- cgit v1.2.3