diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-27 14:35:59 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-27 14:35:59 +0800 |
commit | aa324bf5be8e415a7e81460e6dca405a48fcbffb (patch) | |
tree | e3796b1af9683cf53e71c94cd1036e599c0cbaad | |
parent | 27362c07d86e3d24b75545916697f124d826bbc9 (diff) | |
download | mrust-aa324bf5be8e415a7e81460e6dca405a48fcbffb.tar.gz |
Split type and lifetime parameters apart
-rw-r--r-- | src/ast/ast.cpp | 61 | ||||
-rw-r--r-- | src/ast/ast.hpp | 29 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 8 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 17 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 22 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 20 | ||||
-rw-r--r-- | src/parse/root.cpp | 12 |
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();
}
|