summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-27 14:35:59 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-27 14:35:59 +0800
commitaa324bf5be8e415a7e81460e6dca405a48fcbffb (patch)
treee3796b1af9683cf53e71c94cd1036e599c0cbaad
parent27362c07d86e3d24b75545916697f124d826bbc9 (diff)
downloadmrust-aa324bf5be8e415a7e81460e6dca405a48fcbffb.tar.gz
Split type and lifetime parameters apart
-rw-r--r--src/ast/ast.cpp61
-rw-r--r--src/ast/ast.hpp29
-rw-r--r--src/convert/ast_iterate.cpp8
-rw-r--r--src/convert/typecheck_expr.cpp17
-rw-r--r--src/convert/typecheck_params.cpp22
-rw-r--r--src/dump_as_rust.cpp20
-rw-r--r--src/parse/root.cpp12
7 files changed, 73 insertions, 96 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index efd1e830..40ce413b 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -81,15 +81,15 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
::rust::option<Impl&> Impl::matches(const TypeRef& trait, const TypeRef& type)
{
DEBUG("this = " << *this);
- if( m_params.n_params() )
+ if( m_params.ty_params().size() > 0 )
{
- ::std::vector<TypeRef> param_types(m_params.n_params());
+ ::std::vector<TypeRef> param_types(m_params.ty_params().size());
try
{
auto c = [&](const char* name,const TypeRef& ty){
int idx = m_params.find_name(name);
assert( idx >= 0 );
- assert( (unsigned)idx < m_params.n_params() );
+ assert( (unsigned)idx < param_types.size() );
param_types[idx].merge_with( ty );
};
m_trait.match_args(trait, c);
@@ -654,7 +654,7 @@ SERIALISE_TYPE(Enum::, "AST_Enum", {
TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& args)
{
- if( args.size() != m_params.n_params() )
+ if( args.size() != m_params.ty_params().size() )
{
throw ::std::runtime_error("Incorrect parameter count for struct");
}
@@ -668,9 +668,9 @@ TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& a
{
TypeRef res = f.data;
res.resolve_args( [&](const char *argname){
- for(unsigned int i = 0; i < m_params.n_params(); i ++)
+ for(unsigned int i = 0; i < m_params.ty_params().size(); i ++)
{
- if( m_params.params()[i].name() == argname ) {
+ if( m_params.ty_params()[i].name() == argname ) {
return args.at(i);
}
}
@@ -699,11 +699,6 @@ SERIALISE_TYPE(Struct::, "AST_Struct", {
::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp)
{
//os << "TypeParam(";
- switch(tp.m_class)
- {
- case TypeParam::LIFETIME: os << "'"; break;
- case TypeParam::TYPE: os << ""; break;
- }
os << tp.m_name;
os << " = ";
os << tp.m_default;
@@ -711,23 +706,9 @@ SERIALISE_TYPE(Struct::, "AST_Struct", {
return os;
}
SERIALISE_TYPE(TypeParam::, "AST_TypeParam", {
- const char *classstr = "-";
- switch(m_class)
- {
- case TypeParam::LIFETIME: classstr = "Lifetime"; break;
- case TypeParam::TYPE: classstr = "Type"; break;
- }
- s << classstr;
s << m_name;
s << m_default;
},{
- {
- ::std::string n;
- s.item(n);
- if(n == "Lifetime") m_class = TypeParam::LIFETIME;
- else if(n == "Type") m_class = TypeParam::TYPE;
- else throw ::std::runtime_error("");
- }
s.item(m_name);
s.item(m_default);
})
@@ -749,9 +730,9 @@ SERIALISE_TYPE_S(GenericBound, {
int TypeParams::find_name(const char* name) const
{
- for( unsigned int i = 0; i < m_params.size(); i ++ )
+ for( unsigned int i = 0; i < m_type_params.size(); i ++ )
{
- if( m_params[i].name() == name )
+ if( m_type_params[i].name() == name )
return i;
}
return -1;
@@ -763,29 +744,23 @@ bool TypeParams::check_params(Crate& crate, const ::std::vector<TypeRef>& types)
}
bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool allow_infer) const
{
- // XXX: Make sure all params are types
- {
- for(const auto& p : m_params)
- assert(p.is_type());
- }
-
// Check parameter counts
- if( types.size() > m_params.size() )
+ if( types.size() > m_type_params.size() )
{
- throw ::std::runtime_error(FMT("Too many generic params ("<<types.size()<<" passed, expecting "<< m_params.size()<<")"));
+ throw ::std::runtime_error(FMT("Too many generic params ("<<types.size()<<" passed, expecting "<< m_type_params.size()<<")"));
}
- else if( types.size() < m_params.size() )
+ else if( types.size() < m_type_params.size() )
{
if( allow_infer )
{
- while( types.size() < m_params.size() )
+ while( types.size() < m_type_params.size() )
{
- types.push_back( m_params[types.size()].get_default() );
+ types.push_back( m_type_params[types.size()].get_default() );
}
}
else
{
- throw ::std::runtime_error(FMT("Too few generic params, (" << types.size() << " passed, expecting " << m_params.size() << ")"));
+ throw ::std::runtime_error(FMT("Too few generic params, (" << types.size() << " passed, expecting " << m_type_params.size() << ")"));
}
}
else
@@ -796,7 +771,7 @@ bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool
for( unsigned int i = 0; i < types.size(); i ++ )
{
auto& type = types[i];
- auto& param = m_params[i].name();
+ auto& param = m_type_params[i].name();
TypeRef test(TypeRef::TagArg(), param);
if( type.is_wildcard() )
{
@@ -838,11 +813,11 @@ bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool
::std::ostream& operator<<(::std::ostream& os, const TypeParams& tps)
{
- //return os << "TypeParams({" << tps.m_params << "}, {" << tps.m_bounds << "})";
- return os << "<" << tps.m_params << "> where {" << tps.m_bounds << "}";
+ return os << "<" << tps.m_lifetime_params << "," << tps.m_type_params << "> where {" << tps.m_bounds << "}";
}
SERIALISE_TYPE_S(TypeParams, {
- s.item(m_params);
+ s.item(m_type_params);
+ s.item(m_lifetime_params);
s.item(m_bounds);
})
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 341b860e..af73dca2 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -26,20 +26,11 @@ using ::std::move;
class TypeParam:
public Serialisable
{
- enum Class {
- LIFETIME,
- TYPE,
- //INTEGER,
- };
- Class m_class;
::std::string m_name;
TypeRef m_default;
public:
- TypeParam():
- m_class(LIFETIME)
- {}
- TypeParam(bool is_lifetime, ::std::string name):
- m_class( is_lifetime ? LIFETIME : TYPE ),
+ TypeParam(): m_name("") {}
+ TypeParam(::std::string name):
m_name( ::std::move(name) )
{}
void setDefault(TypeRef type) {
@@ -52,8 +43,6 @@ public:
TypeRef& get_default() { return m_default; }
- bool is_type() const { return m_class == TYPE; }
-
friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp);
SERIALISABLE_PROTOTYPES();
};
@@ -99,20 +88,20 @@ public:
class TypeParams:
public Serialisable
{
- ::std::vector<TypeParam> m_params;
+ ::std::vector<TypeParam> m_type_params;
+ ::std::vector< ::std::string > m_lifetime_params;
::std::vector<GenericBound> m_bounds;
public:
TypeParams() {}
- size_t n_params() const { return m_params.size(); }
- const ::std::vector<TypeParam>& params() const { return m_params; }
+ const ::std::vector<TypeParam>& ty_params() const { return m_type_params; }
+ const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; }
const ::std::vector<GenericBound>& bounds() const { return m_bounds; }
- ::std::vector<TypeParam>& params() { return m_params; }
+ ::std::vector<TypeParam>& ty_params() { return m_type_params; }
::std::vector<GenericBound>& bounds() { return m_bounds; }
- void add_param(TypeParam param) {
- m_params.push_back( ::std::move(param) );
- }
+ void add_ty_param(TypeParam param) { m_type_params.push_back( ::std::move(param) ); }
+ void add_lft_param(::std::string name) { m_lifetime_params.push_back( ::std::move(name) ); }
void add_bound(GenericBound bound) {
m_bounds.push_back( ::std::move(bound) );
}
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp
index 405d55df..061af2b6 100644
--- a/src/convert/ast_iterate.cpp
+++ b/src/convert/ast_iterate.cpp
@@ -25,12 +25,10 @@ void CASTIterator::handle_expr(AST::ExprNode& node)
void CASTIterator::handle_params(AST::TypeParams& params)
{
DEBUG("params");
- for( auto& param : params.params() )
+ for( auto& param : params.ty_params() )
{
- if( param.is_type() ) {
- handle_type(param.get_default());
- local_type( param.name(), TypeRef(TypeRef::TagArg(), param.name()) );
- }
+ handle_type(param.get_default());
+ local_type( param.name(), TypeRef(TypeRef::TagArg(), param.name()) );
}
DEBUG("Bounds");
for( auto& bound : params.bounds() )
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp
index 8cb290c3..57678e94 100644
--- a/src/convert/typecheck_expr.cpp
+++ b/src/convert/typecheck_expr.cpp
@@ -107,7 +107,7 @@ void CTypeChecker::handle_params(AST::TypeParams& params)
{
::std::map<std::string,TypeRef> trs;
- for( const auto& param : params.params() )
+ for( const auto& param : params.ty_params() )
{
trs.insert( make_pair(param.name(), TypeRef()) );
}
@@ -256,15 +256,16 @@ void CTypeChecker::iterate_traits(::std::function<bool(const TypeRef& trait)> fc
void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, const AST::TypeParams& params, const AST::EnumVariant& var)
{
// We know the enum, but it might have type params, need to handle that case
- if( params.n_params() > 0 )
+ // TODO: Check for more parameters than required
+ if( params.ty_params().size() > 0 )
{
// 1. Obtain the pattern set from the path (should it be pre-marked with _ types?)
- while( path_args.size() < params.n_params() )
+ while( path_args.size() < params.ty_params().size() )
path_args.push_back( TypeRef() );
DEBUG("path_args = [" << path_args << "]");
// 2. Create a pattern from the argument types and the format of the variant
DEBUG("argtypes = [" << argtypes << "]");
- ::std::vector<TypeRef> item_args(params.n_params());
+ ::std::vector<TypeRef> item_args(params.ty_params().size());
DEBUG("variant type = " << var.m_sub_types << "");
for( unsigned int i = 0; i < var.m_sub_types.size(); i ++ )
{
@@ -314,7 +315,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node)
AST::Path tp = p;
tp.nodes().pop_back();
AST::PathNode& pn = tp.nodes().back();
- unsigned int num_params = enm.params().n_params();
+ unsigned int num_params = enm.params().ty_params().size();
if(pn.args().size() > num_params)
throw ::std::runtime_error( FMT("Too many arguments to enum variant - " << p) );
while(pn.args().size() < num_params)
@@ -551,11 +552,11 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node)
}
AST::Function& fcn = *fcnp;
- if( fcn.params().n_params() != node.m_method.args().size() )
+ if( fcn.params().ty_params().size() != node.m_method.args().size() )
{
throw ::std::runtime_error("CallMethod with param count mismatch");
}
- if( fcn.params().n_params() )
+ if( fcn.params().ty_params().size() )
{
throw ::std::runtime_error("TODO: CallMethod with params");
}
@@ -576,7 +577,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node)
{
const AST::Function& fcn = node.m_path.binding().bound_func();
- if( fcn.params().n_params() > 0 )
+ if( fcn.params().ty_params().size() > 0 )
{
throw ::std::runtime_error("CallPath - TODO: Params on functions");
}
diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp
index 3b0a5a93..c0c21898 100644
--- a/src/convert/typecheck_params.cpp
+++ b/src/convert/typecheck_params.cpp
@@ -44,7 +44,7 @@ bool CGenericParamChecker::has_impl_for_param(const ::std::string name, const AS
{
if( ptr )
{
- for( const auto& p : ptr->params() )
+ for( const auto& p : ptr->ty_params() )
{
if(p.name() == name) {
tps = ptr;
@@ -104,14 +104,9 @@ bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait)
/// \param allow_infer Allow inferrence (mutates \a types with conditions from \a info)
void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::std::vector<TypeRef>& types, bool allow_infer)
{
- DEBUG("(info = " << info << ", types = {" << types << "}");
+ TRACE_FUNCTION_F("info = " << info << ", types = {" << types << "}");
// TODO: Need to correctly handle lifetime params here, they should be in a different list
- const auto& params = info.params();
-
- {
- for(const auto& p : params)
- assert(p.is_type());
- }
+ const auto& params = info.ty_params();
if( types.size() > params.size() )
{
@@ -119,6 +114,11 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s
}
else if( types.size() < params.size() )
{
+ // Fill with defaults
+ while( types.size() < params.size() && params[types.size()].get_default() != TypeRef() )
+ types.push_back( params[types.size()].get_default() );
+
+ // And (optionally) infer
if( allow_infer )
{
while( types.size() < params.size() )
@@ -126,7 +126,7 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s
types.push_back( TypeRef() );
}
}
- else
+ else if( types.size() < params.size() )
{
throw ::std::runtime_error(FMT("Too few generic params, ("<<types.size()<<" passed, expecting "<<params.size()<<")"));
}
@@ -135,11 +135,12 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s
{
// Counts are good, time to validate types
}
-
+
for( unsigned int i = 0; i < types.size(); i ++ )
{
auto& type = types[i];
auto& param = params[i].name();
+ DEBUG("#" << i << " - checking type " << type << " against " << param);
if( type.is_wildcard() )
{
// Type is a wildcard - this can match any condition
@@ -148,6 +149,7 @@ void CGenericParamChecker::check_generic_params(const AST::TypeParams& info, ::s
// Apply conditions for this param to the type
// TODO: Requires supporting type "ranges" on the TypeRef
// Should also check for conflicting requirements (negative bounds?)
+ DEBUG("TODO: Type inferrence");
}
else
{
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index 6155caec..bac9d104 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -660,18 +660,26 @@ void RustPrinter::handle_module(const AST::Module& mod)
void RustPrinter::print_params(const AST::TypeParams& params)
{
- if( params.n_params() > 0 )
+ if( params.ty_params().size() > 0 || params.lft_params().size() > 0 )
{
bool is_first = true;
m_os << "<";
- for( const auto& p : params.params() )
+ // Lifetimes
+ for( const auto& p : params.lft_params() )
{
if( !is_first )
m_os << ", ";
- if( p.is_type() )
- m_os << p.name() << " = " << p.get_default();
- else
- m_os << "'" << p.name();
+ m_os << "'" << p;
+ is_first = false;
+ }
+ // Types
+ for( const auto& p : params.ty_params() )
+ {
+ if( !is_first )
+ m_os << ", ";
+ m_os << p.name();
+ if( !p.get_default().is_wildcard() )
+ m_os << " = " << p.get_default();
is_first = false;
}
m_os << ">";
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 3bf43e1f..cbc0ef3b 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -61,7 +61,11 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex)
throw ParseError::Unexpected(lex, tok);
}
::std::string param_name = tok.str();
- ret.add_param( AST::TypeParam( is_lifetime, param_name ) );
+ if( is_lifetime )
+ ret.add_lft_param( param_name );
+ else
+ ret.add_ty_param( AST::TypeParam( param_name ) );
+
if( GET_TOK(tok, lex) == TOK_COLON )
{
if( is_lifetime )
@@ -80,7 +84,7 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex)
if( !is_lifetime && tok.type() == TOK_EQUAL )
{
- ret.params().back().setDefault( Parse_Type(lex) );
+ ret.ty_params().back().setDefault( Parse_Type(lex) );
GET_TOK(tok, lex);
}
} while( tok.type() == TOK_COMMA );
@@ -433,8 +437,8 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
// TODO: Support "for Sized?"
if(tok.type() == TOK_RWORD_WHERE)
{
- if( params.n_params() == 0 )
- throw ParseError::Generic("Where clause with no generic params");
+ //if( params.ty_params().size() == 0 )
+ // throw ParseError::Generic("Where clause with no generic params");
Parse_WhereClause(lex, params);
tok = lex.getToken();
}