diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-29 16:24:46 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-29 16:24:46 +0800 |
commit | 2a0d3a03e3f32e383ed61beb2514ac3094fffb0f (patch) | |
tree | c422e8ca7c2c89f37bfb0917278e1933fd18833c | |
parent | aa324bf5be8e415a7e81460e6dca405a48fcbffb (diff) | |
download | mrust-2a0d3a03e3f32e383ed61beb2514ac3094fffb0f.tar.gz |
Twiddling root-level typecheck
-rw-r--r-- | src/ast/ast.cpp | 1 | ||||
-rw-r--r-- | src/common.hpp | 1 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 108 | ||||
-rw-r--r-- | src/include/compile_error.hpp | 51 | ||||
-rw-r--r-- | src/macros.cpp | 8 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/parse/parseerror.cpp | 16 | ||||
-rw-r--r-- | src/parse/parseerror.hpp | 46 |
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( ¶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<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)
}
|