From 553112fcbf7175e9ea751a2aedc4c0d336d95593 Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Sat, 17 Jan 2015 16:19:27 +0800 Subject: Clean up hanlding of generic params --- src/ast/ast.cpp | 120 ++++++++++-------------------------------------- src/ast/ast.hpp | 67 +++++++++++++++++++++------ src/ast/path.cpp | 3 +- src/convert/resolve.cpp | 8 ++-- src/parse/root.cpp | 23 +++++----- 5 files changed, 94 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 4bafb357..be4c9400 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -9,8 +9,6 @@ namespace AST { -ExternCrate ExternCrate_std(); - SERIALISE_TYPE(MetaItem::, "AST_MetaItem", { s << m_name; s << m_str_val; @@ -116,16 +114,6 @@ void Crate::load_extern_crate(::std::string name) d.item( ret.crate() ); m_extern_crates.insert( make_pair(::std::move(name), ::std::move(ret)) ); - - //if( name == "std" ) - //{ - // // HACK! Load std using a hackjob (included within the compiler) - // m_extern_crates.insert( make_pair( ::std::move(name), ExternCrate_std() ) ); - //} - //else - //{ - // throw ParseError::Todo("'extern crate' (not hackjob std)"); - //} } SERIALISE_TYPE(Crate::, "AST_Crate", { s << m_load_std; @@ -149,77 +137,6 @@ SERIALISE_TYPE(ExternCrate::, "AST_ExternCrate", { },{ }) -ExternCrate ExternCrate_std() -{ - ExternCrate crate; - - Module& std_mod = crate.root_module(); - - // === Add modules === - // - option - Module option("option"); - option.add_enum(true, "Option", Enum( - { - TypeParam(false, "T"), - }, - { - StructItem("None", TypeRef()), - StructItem("Some", TypeRef(TypeRef::TagArg(), "T")), - } - )); - std_mod.add_submod(true, ::std::move(option)); - // - result - Module result("result"); - result.add_enum(true, "Result", Enum( - { - TypeParam(false, "R"), - TypeParam(false, "E"), - }, - { - StructItem("Ok", TypeRef(TypeRef::TagArg(), "R")), - StructItem("Err", TypeRef(TypeRef::TagArg(), "E")), - } - )); - std_mod.add_submod(true, ::std::move(result)); - // - io - Module io("io"); - io.add_typealias(true, "IoResult", TypeAlias( - { TypeParam(false, "T") }, - TypeRef( Path("std", { - PathNode("result",{}), - PathNode("Result", {TypeRef("T"),TypeRef(Path("std", {PathNode("io"), PathNode("IoError")}))}) - }) ) - )); - std_mod.add_submod(true, ::std::move(io)); - // - iter - { - Module iter("iter"); - #if 0 - { - Trait iterator; - iterator.add_type("Item", TypeRef()); - //iterator.add_function("next", Function({}, Function::CLASS_REFMETHOD, "Option<::Item>", {}, Expr()); - iter.add_trait(true, "Iterator", ::std::move(iterator)); - } - #endif - std_mod.add_submod(true, ::std::move(iter)); - } - - // - prelude - Module prelude("prelude"); - // Re-exports - #define USE(mod, name, ...) do{ Path p("std", {__VA_ARGS__}); mod.add_alias(true, ::std::move(p), name); } while(0) - USE(prelude, "Option", PathNode("option", {}), PathNode("Option",{}) ); - USE(prelude, "Some", PathNode("option", {}), PathNode("Option",{}), PathNode("Some",{}) ); - USE(prelude, "None", PathNode("option", {}), PathNode("Option",{}), PathNode("None",{}) ); - USE(prelude, "Result", PathNode("result", {}), PathNode("Result",{}) ); - USE(prelude, "Ok", PathNode("result", {}), PathNode("Result",{}), PathNode("Ok",{}) ); - USE(prelude, "Err", PathNode("result", {}), PathNode("Result",{}), PathNode("Err",{}) ); - std_mod.add_submod(true, prelude); - - return crate; -} - SERIALISE_TYPE(Module::, "AST_Module", { s << m_name; s << m_attrs; @@ -368,14 +285,6 @@ SERIALISE_TYPE(Struct::, "AST_Struct", { s.item(m_fields); }) -void TypeParam::addLifetimeBound(::std::string name) -{ - -} -void TypeParam::addTypeBound(TypeRef type) -{ - -} ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp) { os << "TypeParam("; @@ -385,10 +294,8 @@ void TypeParam::addTypeBound(TypeRef type) case TypeParam::TYPE: os << ""; break; } os << tp.m_name; - if( tp.m_trait_bounds.size() ) - { - os << ": [" << tp.m_trait_bounds << "]"; - } + os << " = "; + os << tp.m_default; os << ")"; return os; } @@ -401,7 +308,7 @@ SERIALISE_TYPE(TypeParam::, "AST_TypeParam", { } s << classstr; s << m_name; - s << m_trait_bounds; + s << m_default; },{ { ::std::string n; @@ -411,7 +318,26 @@ SERIALISE_TYPE(TypeParam::, "AST_TypeParam", { else throw ::std::runtime_error(""); } s.item(m_name); - s.item(m_trait_bounds); + s.item(m_default); +}) + +::std::ostream& operator<<(::std::ostream& os, const GenericBound& x) +{ + return os << "GenericBound(" << x.m_argname << "," << x.m_lifetime << "," << x.m_trait << ")"; +} +SERIALISE_TYPE_S(GenericBound, { + s.item(m_argname); + s.item(m_lifetime); + s.item(m_trait); +}) + +::std::ostream& operator<<(::std::ostream& os, const TypeParams& tps) +{ + return os << "TypeParams({" << tps.m_params << "}, {" << tps.m_bounds << "})"; +} +SERIALISE_TYPE_S(TypeParams, { + s.item(m_params); + s.item(m_bounds); }) } diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 4cc8f807..af797e7b 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -31,7 +31,7 @@ class TypeParam: }; Class m_class; ::std::string m_name; - ::std::vector m_trait_bounds; + TypeRef m_default; public: TypeParam(): m_class(LIFETIME) @@ -40,20 +40,62 @@ public: m_class( is_lifetime ? LIFETIME : TYPE ), m_name( ::std::move(name) ) {} - void addLifetimeBound(::std::string name); - void addTypeBound(TypeRef type); void setDefault(TypeRef type); const ::std::string& name() const { return m_name; } bool is_type() const { return m_class == TYPE; } - //TypeRef& get_default() const { return m_ - ::std::vector& get_bounds() { assert(is_type()); return m_trait_bounds; } friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp); SERIALISABLE_PROTOTYPES(); }; +class GenericBound: + public Serialisable +{ + ::std::string m_argname; + ::std::string m_lifetime; + TypeRef m_trait; +public: + GenericBound() {} + GenericBound(::std::string argname, ::std::string lifetime): + m_argname(argname), + m_lifetime(lifetime) + { } + GenericBound(::std::string argname, TypeRef trait): + m_argname(argname), + m_trait( ::std::move(trait) ) + { } + + TypeRef& get_type() { return m_trait; } + + friend ::std::ostream& operator<<(::std::ostream& os, const GenericBound& x); + SERIALISABLE_PROTOTYPES(); +}; + +class TypeParams: + public Serialisable +{ + ::std::vector m_params; + ::std::vector m_bounds; +public: + TypeParams() {} + + size_t n_params() const { return m_params.size(); } + ::std::vector& params() { return m_params; } + ::std::vector& bounds() { return m_bounds; } + + void add_param(TypeParam param) { + m_params.push_back( ::std::move(param) ); + } + void add_bound(GenericBound bound) { + m_bounds.push_back( ::std::move(bound) ); + } + + friend ::std::ostream& operator<<(::std::ostream& os, const TypeParams& tp); + SERIALISABLE_PROTOTYPES(); +}; + template struct Item: public Serialisable @@ -83,7 +125,6 @@ struct Item: template using ItemList = ::std::vector >; -typedef ::std::vector TypeParams; typedef ::std::pair< ::std::string, TypeRef> StructItem; class Crate; @@ -204,7 +245,7 @@ public: class Trait: public Serialisable { - ::std::vector m_params; + TypeParams m_params; ItemList m_types; ItemList m_functions; public: @@ -227,16 +268,16 @@ public: class Enum: public Serialisable { - ::std::vector m_params; + TypeParams m_params; ::std::vector m_variants; public: Enum() {} - Enum( ::std::vector params, ::std::vector variants ): + Enum( TypeParams params, ::std::vector variants ): m_params( move(params) ), m_variants( move(variants) ) {} - const ::std::vector params() const { return m_params; } + const TypeParams params() const { return m_params; } const ::std::vector variants() const { return m_variants; } SERIALISABLE_PROTOTYPES(); @@ -245,16 +286,16 @@ public: class Struct: public Serialisable { - ::std::vector m_params; + TypeParams m_params; ::std::vector m_fields; public: Struct() {} - Struct( ::std::vector params, ::std::vector fields ): + Struct( TypeParams params, ::std::vector fields ): m_params( move(params) ), m_fields( move(fields) ) {} - const ::std::vector params() const { return m_params; } + const TypeParams params() const { return m_params; } const ::std::vector fields() const { return m_fields; } SERIALISABLE_PROTOTYPES(); diff --git a/src/ast/path.cpp b/src/ast/path.cpp index acd92dd8..8f77f008 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -53,7 +53,6 @@ void Path::resolve(const Crate& root_crate) const bool is_last = (i+1 == m_nodes.size()); const bool is_sec_last = (i+2 == m_nodes.size()); const PathNode& node = m_nodes[i]; - DEBUG("mod = " << mod << ", node = " << node); // Sub-modules { @@ -261,7 +260,7 @@ void Path::bind_struct(const Struct& ent, const ::std::vector& args) { if( args.size() > 0 ) { - if( args.size() != ent.params().size() ) + if( args.size() != ent.params().n_params() ) throw ParseError::Generic("Parameter count mismatch"); // TODO: Is it the role of this section of code to ensure that the passed args are valid? // - Probably not, it should instead be the type checker that does it diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 02b3ea78..f5e88b4f 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -449,12 +449,14 @@ void ResolvePaths_HandleModule(const AST::Crate& crate, const AST::Path& modpath // Params pr.push_scope(); - for( auto& param : impl.params() ) + for( auto& param : impl.params().params() ) { DEBUG("Param " << param); pr.add_local_type(param.name()); - for(auto& trait : param.get_bounds()) - pr.resolve_type(trait); + } + for( auto& bound : impl.params().bounds() ) + { + pr.resolve_type(bound.get_type()); } // Trait pr.resolve_type( impl.trait() ); diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 024860bf..2c0acd4e 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -228,9 +228,9 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex) // Oopsie! throw ParseError::Unexpected(tok); } - AST::TypeParam param( is_lifetime, tok.str() ); - tok = lex.getToken(); - if( tok.type() == TOK_COLON ) + ::std::string param_name = tok.str(); + ret.add_param( AST::TypeParam( is_lifetime, param_name ) ); + if( GET_TOK(tok, lex) == TOK_COLON ) { // TODO: Conditions if( is_lifetime ) @@ -238,18 +238,17 @@ AST::TypeParams Parse_TypeParams(TokenStream& lex) throw ParseError::Todo("lifetime param conditions"); } - do { - tok = lex.getToken(); - if(tok.type() == TOK_LIFETIME) - param.addLifetimeBound(tok.str()); + do + { + if(GET_TOK(tok, lex) == TOK_LIFETIME) { + ret.add_bound( AST::GenericBound(param_name, tok.str()) ); + } else { lex.putback(tok); - param.addTypeBound(Parse_Type(lex)); + ret.add_bound( AST::GenericBound(param_name, Parse_Type(lex)) ); } - tok = lex.getToken(); - } while(tok.type() == TOK_PLUS); + } while( GET_TOK(tok, lex) == TOK_PLUS ); } - ret.push_back(param); } while( tok.type() == TOK_COMMA ); lex.putback(tok); return ret; @@ -473,7 +472,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const ::std::vector m // TODO: Support "for Sized?" if(tok.type() == TOK_RWORD_WHERE) { - if( params.size() == 0 ) + if( params.n_params() == 0 ) throw ParseError::Generic("Where clause with no generic params"); Parse_TypeConds(lex, params); tok = lex.getToken(); -- cgit v1.2.3