summaryrefslogtreecommitdiff
path: root/src/ast/path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast/path.cpp')
-rw-r--r--src/ast/path.cpp56
1 files changed, 47 insertions, 9 deletions
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 ++;
}