summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-31 19:42:05 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-31 19:42:05 +0800
commit752202c3857b00d0aa53117573d4a931f79ed65d (patch)
treec1884c7206604f778c2b8607febd53489e29a7fd /src
parentf725889aedd5b64141e8f8e9924e4e59f716c225 (diff)
downloadmrust-752202c3857b00d0aa53117573d4a931f79ed65d.tar.gz
Add Copy impls (hacky), and parameter count checking/extending
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp6
-rw-r--r--src/ast/path.cpp56
-rw-r--r--src/ast/path.hpp7
-rw-r--r--src/ast/provided_module.cpp4
-rw-r--r--src/convert/resolve.cpp7
-rw-r--r--src/convert/typecheck_params.cpp7
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) )
{