diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 6 | ||||
-rw-r--r-- | src/ast/path.cpp | 56 | ||||
-rw-r--r-- | src/ast/path.hpp | 7 | ||||
-rw-r--r-- | src/ast/provided_module.cpp | 4 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 7 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 7 |
6 files changed, 69 insertions, 18 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 4c400a47..c071e139 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -180,12 +180,14 @@ static void iterate_module(Module& mod, ::std::function<void(Module& mod)> fcn) void Crate::post_parse()
{
// Iterate all modules, grabbing pointers to all impl blocks
- iterate_module(m_root_module, [this](Module& mod){
+ auto cb = [this](Module& mod){
for( auto& impl : mod.impls() )
{
m_impl_index.push_back( &impl );
}
- });
+ };
+ iterate_module(m_root_module, cb);
+ iterate_module(g_compiler_module, cb);
}
void Crate::iterate_functions(fcn_visitor_t* visitor)
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 7fa630f9..85559e0e 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -68,7 +68,7 @@ typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector< } /// Resolve a path into a canonical form, and bind it to the target value -void Path::resolve(const Crate& root_crate) +void Path::resolve(const Crate& root_crate, bool expect_params) { TRACE_FUNCTION_F("*this = "<< *this); if(m_class != ABSOLUTE) @@ -156,6 +156,7 @@ void Path::resolve(const Crate& root_crate) // Make a copy of the path, replace params with it, then replace *this? // - Maybe leave that up to other code? if( is_last ) { + check_param_counts(ta.params(), expect_params, m_nodes[i]); m_binding = PathBinding(&ta); goto ret; } @@ -169,6 +170,7 @@ void Path::resolve(const Crate& root_crate) const auto& fn = item.unwrap_Function(); DEBUG("Found function"); if( is_last ) { + check_param_counts(fn.params(), expect_params, m_nodes[i]); m_binding = PathBinding(&fn); goto ret; } @@ -182,10 +184,13 @@ void Path::resolve(const Crate& root_crate) const auto& t = item.unwrap_Trait(); DEBUG("Found trait"); if( is_last ) { + check_param_counts(t.params(), expect_params, m_nodes[i]); m_binding = PathBinding(&t); goto ret; } else if( is_sec_last ) { + check_param_counts(t.params(), expect_params, m_nodes[i]); + // TODO: Also check params on item m_binding = PathBinding(PathBinding::TagItem(), &t); goto ret; } @@ -199,10 +204,12 @@ void Path::resolve(const Crate& root_crate) const auto& str = item.unwrap_Struct(); DEBUG("Found struct"); if( is_last ) { + check_param_counts(str.params(), expect_params, m_nodes[i]); bind_struct(str, node.args()); goto ret; } else if( is_sec_last ) { + check_param_counts(str.params(), expect_params, m_nodes[i]); bind_struct_member(str, node.args(), m_nodes[i+1]); goto ret; } @@ -216,10 +223,12 @@ void Path::resolve(const Crate& root_crate) const auto& enm = item.unwrap_Enum(); DEBUG("Found enum"); if( is_last ) { + check_param_counts(enm.params(), expect_params, m_nodes[i]); bind_enum(enm, node.args()); goto ret; } else if( is_sec_last ) { + check_param_counts(enm.params(), expect_params, m_nodes[i]); bind_enum_var(enm, m_nodes[i+1].name(), node.args()); goto ret; } @@ -256,7 +265,7 @@ void Path::resolve(const Crate& root_crate) DEBUG("- newpath = " << newpath); // TODO: This should check for recursion somehow - newpath.resolve(root_crate); + newpath.resolve(root_crate, expect_params); *this = newpath; DEBUG("Alias resolved, *this = " << *this); @@ -273,7 +282,7 @@ void Path::resolve(const Crate& root_crate) } DEBUG("- newpath = " << newpath); // TODO: This should check for recursion somehow - newpath.resolve(root_crate); + newpath.resolve(root_crate, expect_params); *this = newpath; DEBUG("Alias resolved, *this = " << *this); @@ -294,16 +303,41 @@ ret: } return ; } +void Path::check_param_counts(const TypeParams& params, bool expect_params, PathNode& node) +{ + if( !expect_params ) + { + if( node.args().size() ) + throw CompileError::BugCheck(FMT("Unexpected parameters in path " << *this)); + } + else if( node.args().size() != params.ty_params().size() ) + { + DEBUG("Count mismatch"); + if( node.args().size() > params.ty_params().size() ) + { + // Too many, definitely an error + throw CompileError::Generic(FMT("Too many type parameters passed in path " << *this)); + } + else + { + // Too few, allow defaulting + while( node.args().size() < params.ty_params().size() ) + { + unsigned int i = node.args().size(); + const auto& p = params.ty_params()[i]; + DEBUG("Extra #" << i << ", p = " << p); + if( true || p.get_default() != TypeRef() ) + node.args().push_back( p.get_default() ); + else + throw CompileError::Generic(FMT("Not enough type parameters passed in path " << *this)); + } + } + } +} void Path::bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args) { DEBUG("Bound to enum"); m_binding = PathBinding(&ent); - //if( args.size() > 0 ) - //{ - // if( args.size() != ent.params().size() ) - // throw ParseError::Generic("Parameter count mismatch"); - // throw ParseError::Todo("Bind enum with params passed"); - //} } void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector<TypeRef>& args) { @@ -378,7 +412,11 @@ int Path::equal_no_generic(const Path& x) const return -1; if( e.args().size() || xe.args().size() ) + { + // + DEBUG("e = " << e << ", xe = " << xe); throw CompileError::Todo("Handle Path::equal_no_generic with generic"); + } i ++; } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 21d2dd51..7f45d360 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -16,6 +16,7 @@ class TypeRef; namespace AST { +class TypeParams; class Crate; class Module; class TypeAlias; @@ -246,7 +247,10 @@ public: m_binding = PathBinding(); } - void resolve(const Crate& crate); + /// Resolve the path, and set up binding + /// + /// expect_params enables checking of param counts (clear for handling 'use') + void resolve(const Crate& crate, bool expect_params=true); bool is_trivial() const { return m_class == RELATIVE && m_nodes.size() == 1 && m_nodes[0].args().size() == 0; @@ -278,6 +282,7 @@ public: friend ::Serialiser& operator<<(Serialiser& s, Path::Class pc); friend void operator>>(Deserialiser& s, Path::Class& pc); private: + void check_param_counts(const TypeParams& params, bool expect_params, PathNode& node); void bind_module(const Module& mod); void bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args); void bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector<TypeRef>& args); diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp index ea323172..bb1da26b 100644 --- a/src/ast/provided_module.cpp +++ b/src/ast/provided_module.cpp @@ -10,5 +10,9 @@ void AST_InitProvidedModule() g_compiler_module.add_struct(true, "str", AST::TypeParams(), ::std::vector<AST::StructItem> { AST::StructItem("", TypeRef(TypeRef::TagUnsizedArray(), TypeRef(CORETYPE_U8)), false), }); + + AST::Path copy_marker_path({AST::PathNode("marker"),AST::PathNode("Copy")}); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_F32), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_F64), copy_marker_path)); } diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 411d1ae4..f9795c1d 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -566,7 +566,7 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod }
// Run resolution on import
- imp.data.resolve(crate);
+ imp.data.resolve(crate, false);
DEBUG("Resolved import : " << imp.data);
// If wildcard, make sure it's sane
@@ -590,7 +590,7 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod for( auto& new_imp : new_imports )
{
if( not new_imp.binding().is_bound() ) {
- new_imp.resolve(crate);
+ new_imp.resolve(crate, false);
}
mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name());
}
@@ -618,7 +618,8 @@ void SetCrateName_Mod(const AST::Crate& crate, ::std::string name, AST::Module& for(auto& imp : mod.imports())
{
imp.data.set_crate(name);
- imp.data.resolve(crate);
+ // - Disable expectation of type parameters
+ imp.data.resolve(crate, false);
}
// TODO: All other types
diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp index 0a7af631..279978e8 100644 --- a/src/convert/typecheck_params.cpp +++ b/src/convert/typecheck_params.cpp @@ -126,9 +126,8 @@ bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait) DEBUG("- Nope"); return false; } - - throw CompileError::Todo( FMT("Search for impls on " << type << " for trait " << trait) ); - + + return true; } return false; } @@ -216,6 +215,8 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s }); const auto& trait = bound.bound(); + // TODO: Also resolve args in the trait + // Check if 'type' impls 'trait' if( !has_impl(bound_type, trait) ) { |