From 859d43ae7012da10a58de5926d096dc817596fce Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 6 Mar 2016 17:41:46 +0800 Subject: HUGE REFACTOR - Move named module items into a tagged union - Item attributes now "owned" by the parent --- src/ast/ast.cpp | 503 +++++++------------------------------- src/ast/ast.hpp | 514 +++++++++------------------------------ src/ast/crate.cpp | 345 ++++++++++++++++++++++++++ src/ast/crate.hpp | 102 ++++++++ src/ast/generics.hpp | 138 +++++++++++ src/ast/item.hpp | 57 +++++ src/ast/path.cpp | 4 +- src/ast/provided_module.cpp | 4 +- src/convert/ast_iterate.cpp | 80 +++--- src/convert/ast_iterate.hpp | 2 +- src/convert/decorators.cpp | 1 + src/convert/resolve.cpp | 49 ++-- src/convert/typecheck_bounds.cpp | 1 + src/convert/typecheck_expr.cpp | 2 + src/convert/typecheck_params.cpp | 1 + src/dump_as_rust.cpp | 101 +++++--- src/expand/expand.hpp | 1 + src/expand/mod.cpp | 115 +++++++++ src/include/main_bindings.hpp | 16 +- src/include/synext.hpp | 52 ++-- src/main.cpp | 17 +- src/parse/common.hpp | 4 +- src/parse/expr.cpp | 8 +- src/parse/root.cpp | 160 ++++++------ src/synexts/derive.cpp | 17 +- src/synexts/lang_item.cpp | 19 +- src/types.cpp | 1 + 27 files changed, 1291 insertions(+), 1023 deletions(-) create mode 100644 src/ast/crate.cpp create mode 100644 src/ast/crate.hpp create mode 100644 src/ast/generics.hpp create mode 100644 src/ast/item.hpp create mode 100644 src/expand/expand.hpp create mode 100644 src/expand/mod.cpp (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index e552692d..787a6a40 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1,6 +1,7 @@ /* */ #include "ast.hpp" +#include "crate.hpp" #include "../types.hpp" #include "../common.hpp" #include @@ -182,12 +183,6 @@ SERIALISE_TYPE(Impl::, "AST_Impl", { s.item(m_functions); }) -Crate::Crate(): - m_root_module(MetaItems(), ""), - m_load_std(true) -{ -} - ::rust::option ImplRef::find_named_item(const ::std::string& name) const { if( this->impl.has_named_item(name) ) { @@ -199,307 +194,6 @@ Crate::Crate(): } -static void iterate_module(Module& mod, ::std::function fcn) -{ - fcn(mod); - for( auto& sm : mod.submods() ) - iterate_module(sm.first, fcn); -} - -void Crate::post_parse() -{ - // Iterate all modules, grabbing pointers to all impl blocks - auto cb = [this](Module& mod){ - for( auto& impl : mod.impls() ) - m_impl_index.push_back( &impl ); - for( auto& impl : mod.neg_impls() ) - m_neg_impl_index.push_back( &impl ); - }; - iterate_module(m_root_module, cb); - iterate_module(g_compiler_module, cb); - - // Create a map of inherent impls - for( const auto& impl : m_impl_index ) - { - if( impl->def().trait().is_valid() == false ) - { - auto& ent = m_impl_map[impl->def().type()]; - ent.push_back( impl ); - } - } -} - -void Crate::iterate_functions(fcn_visitor_t* visitor) -{ - m_root_module.iterate_functions(visitor, *this); -} -Module& Crate::get_root_module(const ::std::string& name) { - return const_cast( const_cast(this)->get_root_module(name) ); -} -const Module& Crate::get_root_module(const ::std::string& name) const { - if( name == "" ) - return m_root_module; - auto it = m_extern_crates.find(name); - if( it != m_extern_crates.end() ) - return it->second.root_module(); - throw ParseError::Generic("crate name unknown"); -} - -bool Crate::is_trait_implicit(const Path& trait) const -{ - // 1. Handle lang_item traits (e.g. FhantomFn) - if( m_lang_item_PhantomFn.is_valid() && trait.equal_no_generic( m_lang_item_PhantomFn ) >= 0 ) - { - return true; - } - return false; -} - -/** - * \brief Checks if a type implements the provided wildcard trait - * \param trait Trait path - * \param type Type in question - * \note Wildcard trait = A trait for which there exists a 'impl Trait for ..' definition - * - * \return True if the trait is implemented (either exlicitly, or implicitly) - */ -bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) const -{ - ::std::vector _params; - TRACE_FUNCTION_F("trait="< )> callback) const -{ - assert( !type.is_type_param() ); - - for( auto implptr : m_impl_index ) - { - Impl& impl = *implptr; - if( impl.def().trait().is_valid() ) - { - // Trait - } - else - { - DEBUG("- " << impl.def()); - ::std::vector out_params; - if( impl.def().matches(out_params, AST::Path(), type) ) - { - if( callback(impl, out_params) ) { - return true; - } - } - } - } - - return false; -} - -::rust::option Crate::find_impl(const Path& trait, const TypeRef& type) const -{ - ::std::vector params; - Impl *out_impl; - if( find_impl(trait, type, &out_impl, ¶ms) ) - { - return ::rust::Some( ImplRef(*out_impl, params) ); - } - else { - return ::rust::None(); - } -} - -bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector* out_params) const -{ - TRACE_FUNCTION_F("trait = " << trait << ", type = " << type); - - // If no params output provided, use a dud locaton - ::std::vector dud_params; - if(out_params) - *out_params = ::std::vector(); - else - out_params = &dud_params; - - // Zero output - if(out_impl) - *out_impl = nullptr; - - if( is_trait_implicit(trait) ) - { - if(out_impl) throw CompileError::BugCheck("find_impl - Asking for concrete impl of a marker trait"); - return true; - } - - // 0. Handle generic bounds - // TODO: Handle more complex bounds like "[T]: Trait" - if( type.is_type_param() ) - { - if( trait.is_valid() ) - { - assert(type.type_params_ptr()); - // Search bounds for type: trait - for( const auto& bound : type.type_params_ptr()->bounds() ) - { - DEBUG("bound = " << bound); - TU_MATCH_DEF(GenericBound, (bound), (ent), - (), - (IsTrait, - if(ent.type == type && ent.trait == trait) { - // If found, success! - DEBUG("- Success!"); - // TODO: What should be returned, kinda need to return a boolean - if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed"); - return true; - } - ) - ) - } - // Else, failure - DEBUG("- No impl :("); - //if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed"); - return false; - } - else - { - DEBUG("- No inherent impl for generic params"); - return false; - } - } - - // TODO: Do a sort to allow a binary search - // 1. Search for wildcard traits (i.e. ones like "impl Send for ..") - // - These require special handling, as negatives apply - for( auto implptr : m_impl_index ) - { - Impl& impl = *implptr; - ::std::vector _p; - if( impl.def().matches(_p, trait, TypeRef()) ) - { - assert(_p.size() == 0); - // This is a wildcard trait, need to locate either a negative, or check contents - if( check_impls_wildcard(trait, type) ) - { - if(out_impl) *out_impl = &impl; - return true; - } - else { - return false; - } - } - - } - - // 2. Check real impls - DEBUG("Not wildcard"); - for( auto implptr : m_impl_index ) - { - Impl& impl = *implptr; - // TODO: What if there's two impls that match this combination? - if( impl.def().matches(*out_params, trait, type) ) - { - if(out_impl) *out_impl = &impl; - return true; - } - } - DEBUG("No impl of " << trait << " for " << type); - return false; -} - -Function& Crate::lookup_method(const TypeRef& type, const char *name) -{ - throw ParseError::Generic( FMT("TODO: Lookup method "<( mv$(name), mv$(it), is_pub ) ); + m_items.back().data.attrs = mv$(attrs); +} +void Module::add_ext_crate(::std::string ext_name, ::std::string imp_name, MetaItems attrs) { + // TODO: Extern crates can be public + this->add_item( false, imp_name, Item::make_Crate({mv$(ext_name)}), mv$(attrs) ); +} +void Module::add_alias(bool is_public, Path path, ::std::string name, MetaItems attrs) { + // TODO: Attributes on aliases / imports + m_imports.push_back( Named( move(name), move(path), is_public) ); +} +void Module::add_typealias(bool is_public, ::std::string name, TypeAlias alias, MetaItems attrs) { + this->add_item( is_public, name, Item::make_Type({mv$(alias)}), mv$(attrs) ); +} +void Module::add_static(bool is_public, ::std::string name, Static item, MetaItems attrs) { + this->add_item( is_public, name, Item::make_Static({mv$(item)}), mv$(attrs) ); +} +void Module::add_trait(bool is_public, ::std::string name, Trait item, MetaItems attrs) { + this->add_item( is_public, name, Item::make_Trait({mv$(item)}), mv$(attrs) ); +} +void Module::add_struct(bool is_public, ::std::string name, Struct item, MetaItems attrs) { + this->add_item( is_public, name, Item::make_Struct({mv$(item)}), mv$(attrs) ); +} +void Module::add_enum(bool is_public, ::std::string name, Enum item, MetaItems attrs) { + this->add_item( is_public, name, Item::make_Enum({mv$(item)}), mv$(attrs) ); +} +void Module::add_function(bool is_public, ::std::string name, Function item, MetaItems attrs) { + this->add_item( is_public, name, Item::make_Function({mv$(item)}), mv$(attrs) ); +} +void Module::add_submod(bool is_public, Module mod, MetaItems attrs) { + this->add_item( is_public, mod.m_name, Item::make_Module({mv$(mod)}), mv$(attrs) ); +} + void Module::prescan() { - TRACE_FUNCTION; - DEBUG("- '"<m_functions ) + for( auto& item : this->m_items ) { - visitor(crate, *this, fcn_item.data); + TU_MATCH_DEF(::AST::Item, (item.data), (e), + ( ), + (Function, + visitor(crate, *this, e.e); + ) + ) } } template -typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) +typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) { - return ::std::find_if(vec.begin(), vec.end(), [&name](const Item& x) { + return ::std::find_if(vec.begin(), vec.end(), [&name](const Named& x) { //DEBUG("find_named - x.name = " << x.name); return x.name == name; }); @@ -624,87 +352,36 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves { TRACE_FUNCTION_F("needle = " << needle); - // Sub-modules - { - auto& sms = submods(); - auto it = ::std::find_if(sms.begin(), sms.end(), [&needle](const ::std::pair& x) { - return x.first.name() == needle; - }); - if( it != sms.end() ) { - return ItemRef(it->first); - } - } - - // External crates - { - auto& crates = this->extern_crates(); - auto it = find_named(crates, needle); - if( it != crates.end() ) { - return ItemRef(it->data); - } - } - - // Type Aliases - { - auto& items = this->type_aliases(); - auto it = find_named(items, needle); - if( it != items.end() ) { - return ItemRef(it->data); - } - } - - // Functions - { - auto& items = this->functions(); - auto it = find_named(items, needle); - if( it != items.end() ) { - if( allow_leaves ) - return ItemRef(it->data); - else - DEBUG("Skipping function, leaves not allowed"); - } - } - - // Traits { - auto& items = this->traits(); - auto it = find_named(items, needle); - if( it != items.end() ) { - return ItemRef(it->data); - } - } - - // Structs - { - auto& items = this->structs(); - auto it = find_named(items, needle); - if( it != items.end() ) { - return ItemRef(it->data); - } - } - - // Enums - { - auto& items = this->enums(); - auto it = find_named(items, needle); - if( it != items.end() ) { - return ItemRef(it->data); + auto it = find_named(this->items(), needle); + if( it != this->items().end() ) { + TU_MATCH(::AST::Item, (it->data), (e), + (None, + break; + ), + (Module, return ItemRef(e.e); ), + (Crate, return ItemRef(e.name); ), + (Type, return ItemRef(e.e); ), + (Struct, return ItemRef(e.e); ), + (Enum, return ItemRef(e.e); ), + (Trait, return ItemRef(e.e); ), + (Function, + if( allow_leaves ) + return ItemRef(e.e); + else + DEBUG("Skipping function, leaves not allowed"); + ), + (Static, + if( allow_leaves ) + return ItemRef(e.e); + else + DEBUG("Skipping function, leaves not allowed"); + ) + ) + DEBUG("Item not checked at this level, try re-export list"); } } - // Statics - { - auto& items = this->statics(); - auto it = find_named(items, needle); - if( it != items.end() ) { - if( allow_leaves ) { - return ItemRef(it->data); - } - else - DEBUG("Skipping static, leaves not allowed"); - } - } - // - Re-exports // > Comes last, as it's a potentially expensive operation { @@ -779,6 +456,12 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves return Module::ItemRef(); } +SERIALISE_TYPE(Item::, "AST_Item", { + s.item(attrs); +},{ + s.item(attrs); +}) + SERIALISE_TYPE(TypeAlias::, "AST_TypeAlias", { s << m_params; s << m_type; diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 3e8ee259..9eba0307 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -25,139 +25,17 @@ #include "attrs.hpp" #include "expr.hpp" #include "macro.hpp" +#include "item.hpp" + +#include "generics.hpp" namespace AST { +class Crate; + using ::std::unique_ptr; using ::std::move; -class TypeParam: - public Serialisable -{ - ::std::string m_name; - TypeRef m_default; -public: - TypeParam(): m_name("") {} - TypeParam(::std::string name): - m_name( ::std::move(name) ) - {} - void setDefault(TypeRef type) { - assert(m_default.is_wildcard()); - m_default = ::std::move(type); - } - - const ::std::string& name() const { return m_name; } - const TypeRef& get_default() const { return m_default; } - - TypeRef& get_default() { return m_default; } - - friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp); - SERIALISABLE_PROTOTYPES(); -}; - -TAGGED_UNION_EX( GenericBound, (: public Serialisable), Lifetime, - ( - // Lifetime bound: 'test must be valid for 'bound - (Lifetime, ( - ::std::string test; - ::std::string bound; - )), - // Type lifetime bound - (TypeLifetime, ( - TypeRef type; - ::std::string bound; - )), - // Standard trait bound: "Type: [for<'a>] Trait" - (IsTrait, ( - TypeRef type; - ::std::vector< ::std::string> hrls; // Higher-ranked lifetimes - AST::Path trait; - )), - // Removed trait bound: "Type: ?Trait" - (MaybeTrait, ( - TypeRef type; - AST::Path trait; - )), - // Negative trait bound: "Type: !Trait" - (NotTrait, ( - TypeRef type; - AST::Path trait; - )), - // Type equality: "Type = Replacement" - (Equality, ( - TypeRef type; - TypeRef replacement; - )) - ), - ( - public: - SERIALISABLE_PROTOTYPES(); - - GenericBound clone() const { - TU_MATCH(GenericBound, ( (*this) ), (ent), - (Lifetime, return make_Lifetime({ent.test, ent.bound}); ), - (TypeLifetime, return make_TypeLifetime({ent.type, ent.bound}); ), - (IsTrait, return make_IsTrait({ent.type, ent.hrls, ent.trait}); ), - (MaybeTrait, return make_MaybeTrait({ent.type, ent.trait}); ), - (NotTrait, return make_NotTrait({ent.type, ent.trait}); ), - (Equality, return make_Equality({ent.type, ent.replacement}); ) - ) - return GenericBound(); - } - ) - ); - -::std::ostream& operator<<(::std::ostream& os, const GenericBound& x); - -class GenericParams: - public Serialisable -{ - ::std::vector m_type_params; - ::std::vector< ::std::string > m_lifetime_params; - ::std::vector m_bounds; -public: - GenericParams() {} - GenericParams(GenericParams&& x) noexcept: - m_type_params( mv$(x.m_type_params) ), - m_lifetime_params( mv$(x.m_lifetime_params) ), - m_bounds( mv$(x.m_bounds) ) - {} - GenericParams& operator=(GenericParams&& x) { - m_type_params = mv$(x.m_type_params); - m_lifetime_params = mv$(x.m_lifetime_params); - m_bounds = mv$(x.m_bounds); - return *this; - } - GenericParams(const GenericParams& x): - m_type_params(x.m_type_params), - m_lifetime_params(x.m_lifetime_params), - m_bounds() - { - m_bounds.reserve( x.m_bounds.size() ); - for(auto& e: x.m_bounds) - m_bounds.push_back( e.clone() ); - } - - const ::std::vector& ty_params() const { return m_type_params; } - const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; } - const ::std::vector& bounds() const { return m_bounds; } - ::std::vector& ty_params() { return m_type_params; } - ::std::vector& bounds() { return m_bounds; } - - 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) ); - } - - int find_name(const char* name) const; - bool check_params(Crate& crate, const ::std::vector& types) const; - bool check_params(Crate& crate, ::std::vector& types, bool allow_infer) const; - - friend ::std::ostream& operator<<(::std::ostream& os, const GenericParams& tp); - SERIALISABLE_PROTOTYPES(); -}; - enum eItemType { ITEM_TRAIT, @@ -165,71 +43,21 @@ enum eItemType ITEM_FN, }; -template -struct ItemNS -{ - ::std::string name; - T data; - bool is_pub; - - ItemNS(): - is_pub(false) - {} - ItemNS(ItemNS&&) noexcept = default; - ItemNS(const ItemNS&) = default; - ItemNS(::std::string name, T data, bool is_pub): - name( ::std::move(name) ), - data( ::std::move(data) ), - is_pub( is_pub ) - { - } - - //friend ::std::ostream& operator<<(::std::ostream& os, const Item& i) { - // return os << (i.is_pub ? "pub " : " ") << i.name << ": " << i.data; - //} -}; - -template -struct Item: - public ItemNS, - public Serialisable -{ - Item(): - ItemNS() - {} - Item(Item&&) noexcept = default; - Item(const Item&) = default; - Item(::std::string name, T data, bool is_pub): - ItemNS( ::std::move(name), ::std::move(data), is_pub ) - {} - SERIALISE_TYPE_A(, "Item", { - s.item(this->name); - s.item(this->data); - s.item(this->is_pub); - }) -}; - -template -using ItemList = ::std::vector >; - -typedef Item StructItem; +typedef Named StructItem; class Crate; class TypeAlias: public Serialisable { - MetaItems m_attrs; GenericParams m_params; TypeRef m_type; public: TypeAlias() {} - TypeAlias(MetaItems attrs, GenericParams params, TypeRef type): - m_attrs( move(attrs) ), + TypeAlias(GenericParams params, TypeRef type): m_params( move(params) ), m_type( move(type) ) {} - const MetaItems& attrs() const { return m_attrs; } const GenericParams& params() const { return m_params; } const TypeRef& type() const { return m_type; } @@ -250,7 +78,6 @@ public: MUT, }; private: - MetaItems m_attrs; Class m_class; TypeRef m_type; Expr m_value; @@ -258,14 +85,12 @@ public: Static(): m_class(CONST) {} - Static(MetaItems attrs, Class s_class, TypeRef type, Expr value): - m_attrs( move(attrs) ), + Static(Class s_class, TypeRef type, Expr value): m_class(s_class), m_type( move(type) ), m_value( move(value) ) {} - const MetaItems& attrs() const { return m_attrs; } const Class& s_class() const { return m_class; } const TypeRef& type() const { return m_type; } const Expr& value() const { return m_value; } @@ -283,7 +108,6 @@ public: typedef ::std::vector< ::std::pair > Arglist; private: - MetaItems m_attrs; ::std::string m_lifetime; GenericParams m_params; Expr m_code; @@ -294,8 +118,7 @@ public: {} Function(const Function&) = delete; Function(Function&&) noexcept = default; - Function(MetaItems attrs, GenericParams params, TypeRef ret_type, Arglist args): - m_attrs( move(attrs) ), + Function(GenericParams params, TypeRef ret_type, Arglist args): m_params( move(params) ), m_rettype( move(ret_type) ), m_args( move(args) ) @@ -305,7 +128,6 @@ public: void set_code(Expr code) { m_code = ::std::move(code); } void set_self_lifetime(::std::string s) { m_lifetime = s; } - const MetaItems& attrs() const { return m_attrs; } const GenericParams& params() const { return m_params; } const Expr& code() const { return m_code; } const TypeRef& rettype() const { return m_rettype; } @@ -322,41 +144,38 @@ public: class Trait: public Serialisable { - MetaItems m_attrs; GenericParams m_params; ::std::vector m_supertraits; - ItemList m_types; - ItemList m_functions; - ItemList m_statics; + NamedList m_types; + NamedList m_functions; + NamedList m_statics; public: Trait() {} - Trait(MetaItems attrs, GenericParams params, ::std::vector supertraits): - m_attrs( mv$(attrs) ), + Trait(GenericParams params, ::std::vector supertraits): m_params( mv$(params) ), m_supertraits( mv$(supertraits) ) { } - const MetaItems& attrs() const { return m_attrs; } const GenericParams& params() const { return m_params; } const ::std::vector& supertraits() const { return m_supertraits; } - const ItemList& functions() const { return m_functions; } - const ItemList& types() const { return m_types; } - const ItemList& statics() const { return m_statics; } + const NamedList& functions() const { return m_functions; } + const NamedList& types() const { return m_types; } + const NamedList& statics() const { return m_statics; } GenericParams& params() { return m_params; } ::std::vector& supertraits() { return m_supertraits; } - ItemList& functions() { return m_functions; } - ItemList& types() { return m_types; } + NamedList& functions() { return m_functions; } + NamedList& types() { return m_types; } void add_type(::std::string name, TypeRef type) { - m_types.push_back( Item(move(name), TypeAlias(MetaItems(), GenericParams(), move(type)), true) ); + m_types.push_back( Named(move(name), TypeAlias(GenericParams(), move(type)), true) ); } void add_function(::std::string name, Function fcn) { - m_functions.push_back( Item(::std::move(name), ::std::move(fcn), true) ); + m_functions.push_back( Named(::std::move(name), ::std::move(fcn), true) ); } void add_static(::std::string name, Static v) { - m_statics.push_back( Item(mv$(name), mv$(v), true) ); + m_statics.push_back( Named(mv$(name), mv$(v), true) ); } bool has_named_item(const ::std::string& name, bool& out_is_fcn) const { @@ -399,14 +218,14 @@ struct EnumVariant: } EnumVariant(MetaItems attrs, ::std::string name, ::std::vector sub_types): - m_attrs( move(attrs) ), + m_attrs( mv$(attrs) ), m_name( ::std::move(name) ), m_sub_types( ::std::move(sub_types) ) { } EnumVariant(MetaItems attrs, ::std::string name, ::std::vector fields): - m_attrs( move(attrs) ), + m_attrs( mv$(attrs) ), m_name( ::std::move(name) ), m_fields( ::std::move(fields) ) { @@ -422,18 +241,15 @@ struct EnumVariant: class Enum: public Serialisable { - MetaItems m_attrs; GenericParams m_params; ::std::vector m_variants; public: Enum() {} - Enum( MetaItems attrs, GenericParams params, ::std::vector variants ): - m_attrs( move(attrs) ), + Enum( GenericParams params, ::std::vector variants ): m_params( move(params) ), m_variants( move(variants) ) {} - const MetaItems& attrs() const { return m_attrs; } const GenericParams& params() const { return m_params; } const ::std::vector& variants() const { return m_variants; } @@ -446,22 +262,18 @@ public: class Struct: public Serialisable { - MetaItems m_attrs; GenericParams m_params; ::std::vector m_fields; public: Struct() {} - Struct( MetaItems attrs, GenericParams params, ::std::vector fields ): - m_attrs( move(attrs) ), + Struct( GenericParams params, ::std::vector fields ): m_params( move(params) ), m_fields( move(fields) ) {} - const MetaItems& attrs() const { return m_attrs; } const GenericParams& params() const { return m_params; } const ::std::vector& fields() const { return m_fields; } - MetaItems& attrs() { return m_attrs; } GenericParams& params() { return m_params; } ::std::vector& fields() { return m_fields; } @@ -509,9 +321,9 @@ class Impl: { ImplDef m_def; - ItemList m_types; - ItemList m_functions; - ItemList m_statics; + NamedList m_types; + NamedList m_functions; + NamedList m_statics; ::std::vector m_macro_invocations; ::std::vector< ::std::pair< ::std::vector, Impl > > m_concrete_impls; @@ -523,25 +335,25 @@ public: {} void add_function(bool is_public, ::std::string name, Function fcn) { - m_functions.push_back( Item( ::std::move(name), ::std::move(fcn), is_public ) ); + m_functions.push_back( Named( ::std::move(name), ::std::move(fcn), is_public ) ); } void add_type(bool is_public, ::std::string name, TypeRef type) { - m_types.push_back( Item( ::std::move(name), ::std::move(type), is_public ) ); + m_types.push_back( Named( ::std::move(name), ::std::move(type), is_public ) ); } void add_static(bool is_public, ::std::string name, Static v) { - m_statics.push_back( Item( mv$(name), mv$(v), is_public ) ); + m_statics.push_back( Named( mv$(name), mv$(v), is_public ) ); } void add_macro_invocation( MacroInvocation inv ) { m_macro_invocations.push_back( mv$(inv) ); } const ImplDef& def() const { return m_def; } - const ItemList& functions() const { return m_functions; } - const ItemList& types() const { return m_types; } + const NamedList& functions() const { return m_functions; } + const NamedList& types() const { return m_types; } ImplDef& def() { return m_def; } - ItemList& functions() { return m_functions; } - ItemList& types() { return m_types; } + NamedList& functions() { return m_functions; } + NamedList& types() { return m_types; } bool has_named_item(const ::std::string& name) const; @@ -557,9 +369,8 @@ private: }; -class Crate; -class ExternCrate; class Module; +class Item; typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Function& fcn); @@ -567,42 +378,32 @@ typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Func class Module: public Serialisable { - typedef ::std::vector< Item > itemlist_fcn_t; - typedef ::std::vector< ::std::pair > itemlist_mod_t; - typedef ::std::vector< Item > itemlist_use_t; - typedef ::std::vector< Item< ::std::string> > itemlist_ext_t; - typedef ::std::vector< Item > itemlist_static_t; - typedef ::std::vector< Item > itemlist_enum_t; - typedef ::std::vector< Item > itemlist_struct_t; - typedef ::std::vector< Item > itemlist_macros_t; - typedef ::std::multimap< ::std::string, ::std::string > macro_imports_t; + typedef ::std::vector< Named > itemlist_use_t; - MetaItems m_attrs; ::std::string m_name; - itemlist_fcn_t m_functions; - itemlist_mod_t m_submods; + + // Module-level items + /// General items + ::std::vector> m_items; + /// `use` imports (public and private) itemlist_use_t m_imports; - ::std::vector > m_type_aliases; - itemlist_ext_t m_extern_crates; - ::std::vector m_anon_modules; // TODO: Should this be serialisable? - - itemlist_macros_t m_macros; - macro_imports_t m_macro_imports; // module => macro - ::std::vector< ItemNS > m_macro_import_res; // Vec of imported macros (not serialised) + /// Macro invocations ::std::vector m_macro_invocations; - - - itemlist_static_t m_statics; - ItemList m_traits; - itemlist_enum_t m_enums; - itemlist_struct_t m_structs; + /// Impl blocks ::std::vector m_impls; + /// Negative impl blocks ::std::vector m_neg_impls; + + + // --- Runtime caches and state --- + ::std::vector m_anon_modules; // TODO: Should this be serialisable? + + ::std::vector< NamedNS > m_macro_import_res; // Vec of imported macros (not serialised) + ::std::vector< Named > m_macros; public: Module() {} - Module(MetaItems attrs, ::std::string name): - m_attrs( move(attrs) ), + Module(::std::string name): m_name(name) { } @@ -610,39 +411,17 @@ public: // Called when module is loaded from a serialised format void prescan(); - void add_ext_crate(::std::string ext_name, ::std::string imp_name) { - m_extern_crates.push_back( Item< ::std::string>( move(imp_name), move(ext_name), false ) ); - } - void add_alias(bool is_public, Path path, ::std::string name) { - m_imports.push_back( Item( move(name), move(path), is_public) ); - } - void add_typealias(bool is_public, ::std::string name, TypeAlias alias) { - m_type_aliases.push_back( Item( move(name), move(alias), is_public ) ); - } - //void add_constant(bool is_public, ::std::string name, TypeRef type, Expr val) { - // m_statics.push_back( Item( move(name), Static(Static::CONST, move(type), move(val)), is_public) ); - //} - //void add_global(bool is_public, bool is_mut, ::std::string name, TypeRef type, Expr val) { - // m_statics.push_back( Item( move(name), Static(is_mut ? Static::MUT : Static::STATIC, move(type), move(val)), is_public) ); - //} - void add_static(bool is_public, ::std::string name, Static item) { - m_statics.push_back( Item( move(name), ::std::move(item), is_public) ); - } - void add_trait(bool is_public, ::std::string name, Trait trait) { - m_traits.push_back( Item( move(name), move(trait), is_public) ); - } - void add_struct(bool is_public, ::std::string name, Struct item) { - m_structs.push_back( Item( move(name), move(item), is_public) ); - } - void add_enum(bool is_public, ::std::string name, Enum inst) { - m_enums.push_back( Item( move(name), move(inst), is_public ) ); - } - void add_function(bool is_public, ::std::string name, Function func) { - m_functions.push_back( Item( move(name), move(func), is_public ) ); - } - void add_submod(bool is_public, Module mod) { - m_submods.push_back( ::std::make_pair( move(mod), is_public ) ); - } + void add_item(bool is_pub, ::std::string name, Item it, MetaItems attrs); + void add_ext_crate(::std::string ext_name, ::std::string imp_name, MetaItems attrs); + void add_alias(bool is_public, Path path, ::std::string name, MetaItems attrs); + void add_typealias(bool is_public, ::std::string name, TypeAlias alias, MetaItems attrs); + void add_static(bool is_public, ::std::string name, Static item, MetaItems attrs); + void add_trait(bool is_public, ::std::string name, Trait item, MetaItems attrs); + void add_struct(bool is_public, ::std::string name, Struct item, MetaItems attrs); + void add_enum(bool is_public, ::std::string name, Enum inst, MetaItems attrs); + void add_function(bool is_public, ::std::string name, Function item, MetaItems attrs); + void add_submod(bool is_public, Module mod, MetaItems attrs); + void add_impl(Impl impl) { m_impls.emplace_back( ::std::move(impl) ); } @@ -650,16 +429,13 @@ public: m_neg_impls.emplace_back( ::std::move(impl) ); } void add_macro(bool is_exported, ::std::string name, MacroRules macro) { - m_macros.push_back( Item( move(name), move(macro), is_exported ) ); + m_macros.push_back( Named( move(name), move(macro), is_exported ) ); } void add_macro_import(const Crate& crate, ::std::string mod, ::std::string name); void add_macro_invocation(MacroInvocation item) { m_macro_invocations.push_back( mv$(item) ); } - void add_attr(MetaItem item) { - m_attrs.push_back(item); - } unsigned int add_anon_module(Module* mod_ptr) { auto it = ::std::find(m_anon_modules.begin(), m_anon_modules.end(), mod_ptr); if( it != m_anon_modules.end() ) @@ -708,51 +484,75 @@ public: _(AST::Struct, Struct) _(AST::Enum, Enum) _(AST::Static, Static) - _(AST::Item, Use) + _(AST::Named, Use) #undef _ }; ItemRef find_item(const ::std::string& needle, bool allow_leaves = true, bool ignore_private_wildcard = true) const; + + ::std::vector>& items() { return m_items; } + const ::std::vector>& items() const { return m_items; } - MetaItems& attrs() { return m_attrs; } - itemlist_fcn_t& functions() { return m_functions; } - itemlist_mod_t& submods() { return m_submods; } itemlist_use_t& imports() { return m_imports; } - ::std::vector >& type_aliases() { return m_type_aliases; } - itemlist_ext_t& extern_crates() { return m_extern_crates; } - ::std::vector& impls() { return m_impls; } - itemlist_static_t& statics() { return m_statics; } - ItemList& traits() { return m_traits; } - itemlist_enum_t& enums () { return m_enums; } - itemlist_struct_t& structs() { return m_structs; } - ::std::vector& anon_mods() { return m_anon_modules; } - - const MetaItems& attrs() const { return m_attrs; } - const itemlist_fcn_t& functions() const { return m_functions; } - const itemlist_mod_t& submods() const { return m_submods; } const itemlist_use_t& imports() const { return m_imports; } - const ::std::vector >& type_aliases() const { return m_type_aliases; } - const itemlist_ext_t& extern_crates() const { return m_extern_crates; } + + ::std::vector& impls() { return m_impls; } const ::std::vector& impls() const { return m_impls; } - const itemlist_static_t& statics() const { return m_statics; } - const ItemList& traits() const { return m_traits; } - const itemlist_enum_t& enums () const { return m_enums; } - const itemlist_struct_t& structs() const { return m_structs; } - const ::std::vector& anon_mods() const { return m_anon_modules; } + // No need to mutate this list const ::std::vector& neg_impls() const { return m_neg_impls; } + + ::std::vector& anon_mods() { return m_anon_modules; } + const ::std::vector& anon_mods() const { return m_anon_modules; } - const itemlist_macros_t& macros() const { return m_macros; } - const macro_imports_t& macro_imports() const { return m_macro_imports; } - const ::std::vector > macro_imports_res() const { return m_macro_import_res; } + + const NamedList& macros() const { return m_macros; } + const ::std::vector > macro_imports_res() const { return m_macro_import_res; } SERIALISABLE_PROTOTYPES(); private: void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name); }; -} -extern void handle_lang_item(AST::Crate& , const AST::Path& h, const ::std::string& , AST::eItemType ); -namespace AST { + + +TAGGED_UNION_EX(Item, (: public Serialisable), None, + ( + (None, ( + )), + (Module, ( + Module e; + )), + (Crate, ( + ::std::string name; + )), + + (Type, ( + TypeAlias e; + )), + (Struct, ( + Struct e; + )), + (Enum, ( + Enum e; + )), + (Trait, ( + Trait e; + )), + + (Function, ( + Function e; + )), + (Static, ( + Static e; + )) + ), + ( + public: + MetaItems attrs; + + SERIALISABLE_PROTOTYPES(); + ) + ); struct ImplRef @@ -768,84 +568,6 @@ struct ImplRef ::rust::option find_named_item(const ::std::string& name) const; }; -class Crate: - public Serialisable -{ -public: - ::std::map< TypeRef, ::std::vector > m_impl_map; - ::std::vector m_impl_index; - ::std::vector m_neg_impl_index; - - // XXX: EVIL - Make the method that handles #[lang] a friend, so it can twiddle these paths - friend void ::handle_lang_item(AST::Crate& , const AST::Path& h, const ::std::string& , AST::eItemType ); - AST::Path m_lang_item_PhantomFn; -public: - Module m_root_module; - ::std::map< ::std::string, ExternCrate> m_extern_crates; - // Mapping filled by searching for (?visible) macros with is_pub=true - ::std::map< ::std::string, const MacroRules*> m_exported_macros; - - bool m_load_std; - - Crate(); - - Module& root_module() { return m_root_module; } - Module& get_root_module(const ::std::string& name); - ::std::map< ::std::string, ExternCrate>& extern_crates() { return m_extern_crates; } - - const Module& root_module() const { return m_root_module; } - const Module& get_root_module(const ::std::string& name) const; - const ::std::map< ::std::string, ExternCrate>& extern_crates() const { return m_extern_crates; } - - void post_parse(); - - bool is_trait_implicit(const Path& trait) const; - - - //::std::vector find_inherent_impls(const TypeRef& type) const; - bool find_inherent_impls(const TypeRef& type, ::std::function )>) const; - ::rust::option find_impl(const Path& trait, const TypeRef& type) const; - bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector* out_prams=nullptr) const; - const ::rust::option get_impl(const Path& trait, const TypeRef& type) { - Impl* impl_ptr; - ::std::vector params; - if( find_impl(trait, type, &impl_ptr, ¶ms) ) { - return ::rust::option( impl_ptr->get_concrete(params) ); - } - else { - return ::rust::option(); - } - } - Function& lookup_method(const TypeRef& type, const char *name); - - void load_extern_crate(::std::string name); - - void iterate_functions( fcn_visitor_t* visitor ); - - SERIALISABLE_PROTOTYPES(); -private: - bool check_impls_wildcard(const Path& trait, const TypeRef& type) const; -}; - -/// Representation of an imported crate -/// - Functions are stored as resolved+typechecked ASTs -class ExternCrate: - public Serialisable -{ - Crate m_crate; -public: - ExternCrate(); - ExternCrate(const char *path); - Crate& crate() { return m_crate; } - const Crate& crate() const { return m_crate; } - Module& root_module() { return m_crate.root_module(); } - const Module& root_module() const { return m_crate.root_module(); } - - void prescan(); - - SERIALISABLE_PROTOTYPES(); -}; - class CStruct { // ::std::vector m_fields; diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp new file mode 100644 index 00000000..e8ebb1eb --- /dev/null +++ b/src/ast/crate.cpp @@ -0,0 +1,345 @@ +/* + */ +#include "crate.hpp" +#include "ast.hpp" +#include "../parse/parseerror.hpp" + +#include + +namespace { + void iterate_module(::AST::Module& mod, ::std::function fcn) + { + fcn(mod); + for( auto& sm : mod.items() ) + { + TU_MATCH_DEF(::AST::Item, (sm.data), (e), + ( ), + (Module, + iterate_module(e.e, fcn); + ) + ) + } + } +} + + +namespace AST { + +Crate::Crate(): + m_root_module(""), + m_load_std(true) +{ +} + +void Crate::load_externs() +{ + auto cb = [this](Module& mod) { + for( const auto& it : mod.items() ) + { + if( it.data.is_Crate() ) { + const auto& name = it.data.as_Crate().name; + throw ::std::runtime_error( FMT("TODO: Load crate '" << name << "' as '" << it.name << "'") ); + } + } + }; + iterate_module(m_root_module, cb); +} + +void Crate::index_impls() +{ + // Iterate all modules, grabbing pointers to all impl blocks + auto cb = [this](Module& mod){ + for( auto& impl : mod.impls() ) + m_impl_index.push_back( &impl ); + for( auto& impl : mod.neg_impls() ) + m_neg_impl_index.push_back( &impl ); + }; + iterate_module(m_root_module, cb); + iterate_module(g_compiler_module, cb); + + // Create a map of inherent impls + for( const auto& impl : m_impl_index ) + { + if( impl->def().trait().is_valid() == false ) + { + auto& ent = m_impl_map[impl->def().type()]; + ent.push_back( impl ); + } + } +} + +void Crate::iterate_functions(fcn_visitor_t* visitor) +{ + m_root_module.iterate_functions(visitor, *this); +} +Module& Crate::get_root_module(const ::std::string& name) { + return const_cast( const_cast(this)->get_root_module(name) ); +} +const Module& Crate::get_root_module(const ::std::string& name) const { + if( name == "" ) + return m_root_module; + auto it = m_extern_crates.find(name); + if( it != m_extern_crates.end() ) + throw ::std::runtime_error("TODO: Get root module for extern crate"); +// return it->second.root_module(); + throw ParseError::Generic("crate name unknown"); +} + +bool Crate::is_trait_implicit(const Path& trait) const +{ + // 1. Handle lang_item traits (e.g. FhantomFn) + if( m_lang_item_PhantomFn.is_valid() && trait.equal_no_generic( m_lang_item_PhantomFn ) >= 0 ) + { + return true; + } + return false; +} + +/** + * \brief Checks if a type implements the provided wildcard trait + * \param trait Trait path + * \param type Type in question + * \note Wildcard trait = A trait for which there exists a 'impl Trait for ..' definition + * + * \return True if the trait is implemented (either exlicitly, or implicitly) + */ +bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) const +{ + ::std::vector _params; + TRACE_FUNCTION_F("trait="< )> callback) const +{ + assert( !type.is_type_param() ); + + for( auto implptr : m_impl_index ) + { + Impl& impl = *implptr; + if( impl.def().trait().is_valid() ) + { + // Trait + } + else + { + DEBUG("- " << impl.def()); + ::std::vector out_params; + if( impl.def().matches(out_params, AST::Path(), type) ) + { + if( callback(impl, out_params) ) { + return true; + } + } + } + } + + return false; +} + +::rust::option Crate::find_impl(const Path& trait, const TypeRef& type) const +{ + ::std::vector params; + Impl *out_impl; + if( find_impl(trait, type, &out_impl, ¶ms) ) + { + return ::rust::Some( ImplRef(*out_impl, params) ); + } + else { + return ::rust::None(); + } +} + +bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector* out_params) const +{ + TRACE_FUNCTION_F("trait = " << trait << ", type = " << type); + + // If no params output provided, use a dud locaton + ::std::vector dud_params; + if(out_params) + *out_params = ::std::vector(); + else + out_params = &dud_params; + + // Zero output + if(out_impl) + *out_impl = nullptr; + + if( is_trait_implicit(trait) ) + { + if(out_impl) throw CompileError::BugCheck("find_impl - Asking for concrete impl of a marker trait"); + return true; + } + + // 0. Handle generic bounds + // TODO: Handle more complex bounds like "[T]: Trait" + if( type.is_type_param() ) + { + if( trait.is_valid() ) + { + assert(type.type_params_ptr()); + // Search bounds for type: trait + for( const auto& bound : type.type_params_ptr()->bounds() ) + { + DEBUG("bound = " << bound); + TU_MATCH_DEF(GenericBound, (bound), (ent), + (), + (IsTrait, + if(ent.type == type && ent.trait == trait) { + // If found, success! + DEBUG("- Success!"); + // TODO: What should be returned, kinda need to return a boolean + if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed"); + return true; + } + ) + ) + } + // Else, failure + DEBUG("- No impl :("); + //if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed"); + return false; + } + else + { + DEBUG("- No inherent impl for generic params"); + return false; + } + } + + // TODO: Do a sort to allow a binary search + // 1. Search for wildcard traits (i.e. ones like "impl Send for ..") + // - These require special handling, as negatives apply + for( auto implptr : m_impl_index ) + { + Impl& impl = *implptr; + ::std::vector _p; + if( impl.def().matches(_p, trait, TypeRef()) ) + { + assert(_p.size() == 0); + // This is a wildcard trait, need to locate either a negative, or check contents + if( check_impls_wildcard(trait, type) ) + { + if(out_impl) *out_impl = &impl; + return true; + } + else { + return false; + } + } + + } + + // 2. Check real impls + DEBUG("Not wildcard"); + for( auto implptr : m_impl_index ) + { + Impl& impl = *implptr; + // TODO: What if there's two impls that match this combination? + if( impl.def().matches(*out_params, trait, type) ) + { + if(out_impl) *out_impl = &impl; + return true; + } + } + DEBUG("No impl of " << trait << " for " << type); + return false; +} + +Function& Crate::lookup_method(const TypeRef& type, const char *name) +{ + throw ParseError::Generic( FMT("TODO: Lookup method "< > m_impl_map; + ::std::vector m_impl_index; + ::std::vector m_neg_impl_index; + + ::AST::MetaItems m_attrs; + + AST::Path m_lang_item_PhantomFn; +public: + Module m_root_module; + ::std::map< ::std::string, ExternCrate> m_extern_crates; + // Mapping filled by searching for (?visible) macros with is_pub=true + ::std::map< ::std::string, const MacroRules*> m_exported_macros; + + bool m_load_std; + + Crate(); + + Module& root_module() { return m_root_module; } + Module& get_root_module(const ::std::string& name); + ::std::map< ::std::string, ExternCrate>& extern_crates() { return m_extern_crates; } + + const Module& root_module() const { return m_root_module; } + const Module& get_root_module(const ::std::string& name) const; + const ::std::map< ::std::string, ExternCrate>& extern_crates() const { return m_extern_crates; } + + /// Load referenced crates + void load_externs(); + void index_impls(); + + bool is_trait_implicit(const Path& trait) const; + + + //::std::vector find_inherent_impls(const TypeRef& type) const; + bool find_inherent_impls(const TypeRef& type, ::std::function )>) const; + ::rust::option find_impl(const Path& trait, const TypeRef& type) const; + bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector* out_prams=nullptr) const; + const ::rust::option get_impl(const Path& trait, const TypeRef& type) { + Impl* impl_ptr; + ::std::vector params; + if( find_impl(trait, type, &impl_ptr, ¶ms) ) { + return ::rust::option( impl_ptr->get_concrete(params) ); + } + else { + return ::rust::option(); + } + } + Function& lookup_method(const TypeRef& type, const char *name); + + void load_extern_crate(::std::string name); + + void iterate_functions( fcn_visitor_t* visitor ); + + SERIALISABLE_PROTOTYPES(); +private: + bool check_impls_wildcard(const Path& trait, const TypeRef& type) const; +}; + +/// Representation of an imported crate +/// - Functions are stored as resolved+typechecked ASTs +class ExternCrate: + public Serialisable +{ + ::std::map< ::std::string, MacroRules > m_mr_macros; + + //::MIR::Module m_root_module; + + //Crate m_crate; +public: + ExternCrate(); + ExternCrate(const char *path); + + MacroRules& find_macro(const ::std::string& name) { + auto i = m_mr_macros.find(name); + if(i != m_mr_macros.end()) + return i->second; + throw ::std::runtime_error( FMT("TODO: Unable to find macro '" << name << "'") ); + } + + //Crate& crate() { return m_crate; } + //const Crate& crate() const { return m_crate; } + //Module& root_module() { return m_crate.root_module(); } + //const Module& root_module() const { return m_crate.root_module(); } + + SERIALISABLE_PROTOTYPES(); +}; + +} // namespace AST diff --git a/src/ast/generics.hpp b/src/ast/generics.hpp new file mode 100644 index 00000000..c766fea6 --- /dev/null +++ b/src/ast/generics.hpp @@ -0,0 +1,138 @@ +#pragma once + +#include +#include "../types.hpp" + +namespace AST { + + +class TypeParam: + public Serialisable +{ + ::std::string m_name; + TypeRef m_default; +public: + TypeParam(): m_name("") {} + TypeParam(::std::string name): + m_name( ::std::move(name) ) + {} + void setDefault(TypeRef type) { + assert(m_default.is_wildcard()); + m_default = ::std::move(type); + } + + const ::std::string& name() const { return m_name; } + const TypeRef& get_default() const { return m_default; } + + TypeRef& get_default() { return m_default; } + + friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp); + SERIALISABLE_PROTOTYPES(); +}; + +TAGGED_UNION_EX( GenericBound, (: public Serialisable), Lifetime, + ( + // Lifetime bound: 'test must be valid for 'bound + (Lifetime, ( + ::std::string test; + ::std::string bound; + )), + // Type lifetime bound + (TypeLifetime, ( + TypeRef type; + ::std::string bound; + )), + // Standard trait bound: "Type: [for<'a>] Trait" + (IsTrait, ( + TypeRef type; + ::std::vector< ::std::string> hrls; // Higher-ranked lifetimes + AST::Path trait; + )), + // Removed trait bound: "Type: ?Trait" + (MaybeTrait, ( + TypeRef type; + AST::Path trait; + )), + // Negative trait bound: "Type: !Trait" + (NotTrait, ( + TypeRef type; + AST::Path trait; + )), + // Type equality: "Type = Replacement" + (Equality, ( + TypeRef type; + TypeRef replacement; + )) + ), + ( + public: + SERIALISABLE_PROTOTYPES(); + + GenericBound clone() const { + TU_MATCH(GenericBound, ( (*this) ), (ent), + (Lifetime, return make_Lifetime({ent.test, ent.bound}); ), + (TypeLifetime, return make_TypeLifetime({ent.type, ent.bound}); ), + (IsTrait, return make_IsTrait({ent.type, ent.hrls, ent.trait}); ), + (MaybeTrait, return make_MaybeTrait({ent.type, ent.trait}); ), + (NotTrait, return make_NotTrait({ent.type, ent.trait}); ), + (Equality, return make_Equality({ent.type, ent.replacement}); ) + ) + return GenericBound(); + } + ) + ); + +::std::ostream& operator<<(::std::ostream& os, const GenericBound& x); + +class GenericParams: + public Serialisable +{ + ::std::vector m_type_params; + ::std::vector< ::std::string > m_lifetime_params; + ::std::vector m_bounds; +public: + GenericParams() {} + GenericParams(GenericParams&& x) noexcept: + m_type_params( mv$(x.m_type_params) ), + m_lifetime_params( mv$(x.m_lifetime_params) ), + m_bounds( mv$(x.m_bounds) ) + {} + GenericParams& operator=(GenericParams&& x) { + m_type_params = mv$(x.m_type_params); + m_lifetime_params = mv$(x.m_lifetime_params); + m_bounds = mv$(x.m_bounds); + return *this; + } + GenericParams(const GenericParams& x): + m_type_params(x.m_type_params), + m_lifetime_params(x.m_lifetime_params), + m_bounds() + { + m_bounds.reserve( x.m_bounds.size() ); + for(auto& e: x.m_bounds) + m_bounds.push_back( e.clone() ); + } + + const ::std::vector& ty_params() const { return m_type_params; } + const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; } + const ::std::vector& bounds() const { return m_bounds; } + ::std::vector& ty_params() { return m_type_params; } + ::std::vector& bounds() { return m_bounds; } + + 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) ); + } + + int find_name(const char* name) const; + bool check_params(Crate& crate, const ::std::vector& types) const; + bool check_params(Crate& crate, ::std::vector& types, bool allow_infer) const; + + friend ::std::ostream& operator<<(::std::ostream& os, const GenericParams& tp); + SERIALISABLE_PROTOTYPES(); +}; + + +} + diff --git a/src/ast/item.hpp b/src/ast/item.hpp new file mode 100644 index 00000000..7b5437c4 --- /dev/null +++ b/src/ast/item.hpp @@ -0,0 +1,57 @@ + +#pragma once + +#include +#include + +namespace AST { + +template +struct NamedNS +{ + ::std::string name; + T data; + bool is_pub; + + NamedNS(): + is_pub(false) + {} + NamedNS(NamedNS&&) noexcept = default; + NamedNS(const NamedNS&) = default; + NamedNS(::std::string name, T data, bool is_pub): + name( ::std::move(name) ), + data( ::std::move(data) ), + is_pub( is_pub ) + { + } + + //friend ::std::ostream& operator<<(::std::ostream& os, const Named& i) { + // return os << (i.is_pub ? "pub " : " ") << i.name << ": " << i.data; + //} +}; + +template +struct Named: + public NamedNS, + public Serialisable +{ + Named(): + NamedNS() + {} + Named(Named&&) noexcept = default; + Named(const Named&) = default; + Named(::std::string name, T data, bool is_pub): + NamedNS( ::std::move(name), ::std::move(data), is_pub ) + {} + SERIALISE_TYPE_A(, "Named", { + s.item(this->name); + s.item(this->data); + s.item(this->is_pub); + }) +}; + +template +using NamedList = ::std::vector >; + +} // namespace AST + diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 5c0510fe..24318312 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -81,9 +81,9 @@ SERIALISE_TYPE(PathNode::, "PathNode", { /// Return an iterator to the named item template -typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) +typename ::std::vector >::const_iterator find_named(const ::std::vector >& vec, const ::std::string& name) { - return ::std::find_if(vec.begin(), vec.end(), [&name](const Item& x) { + return ::std::find_if(vec.begin(), vec.end(), [&name](const Named& x) { return x.name == name; }); } diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp index 8d32fb96..0cbd2955 100644 --- a/src/ast/provided_module.cpp +++ b/src/ast/provided_module.cpp @@ -12,9 +12,9 @@ void AST_InitProvidedModule() { // "struct str([u8])" g_compiler_module.add_struct(true, "str", - AST::Struct( AST::MetaItems(), AST::GenericParams(), ::std::vector { + AST::Struct( AST::GenericParams(), ::std::vector { AST::StructItem("", TypeRef(TypeRef::TagUnsizedArray(), TypeRef(CORETYPE_U8)), false), - })); + }), AST::MetaItems()); // TODO: Defer this until AFTER AST_InitProvidedModule_Impls(); diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 2e1dfe23..2a910692 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -303,41 +303,49 @@ void CASTIterator::handle_module(AST::Path path, AST::Module& mod) INDENT(); start_scope(); - for( auto& item : mod.structs() ) + for( auto& item : mod.items() ) { - DEBUG("Handling struct " << item.name); - handle_struct(path + item.name, item.data); - } - for( auto& item : mod.enums() ) - { - DEBUG("Handling enum " << item.name); - handle_enum(path + item.name, item.data); - } - for( auto& item : mod.traits() ) - { - DEBUG("Handling trait " << item.name); - handle_trait(path + item.name, item.data); - } - for( auto& item : mod.type_aliases() ) - { - DEBUG("Handling alias " << item.name); - handle_alias(path + item.name, item.data); - } - for( auto& stat : mod.statics() ) - { - DEBUG("handling static " << stat.name); - handle_type(stat.data.type()); - if( stat.data.value().is_valid() ) - { - handle_expr(stat.data.value().node()); - } + TU_MATCH(::AST::Item, (item.data), (e), + (None, + // Explicitly ignored (represents a deleted item) + ), + (Crate, + // Nothing to be done + ), + (Struct, + DEBUG("Handling struct " << item.name); + handle_struct(path + item.name, e.e); + ), + (Enum, + DEBUG("Handling enum " << item.name); + handle_enum(path + item.name, e.e); + ), + (Trait, + DEBUG("Handling trait " << item.name); + handle_trait(path + item.name, e.e); + ), + (Type, + DEBUG("Handling alias " << item.name); + handle_alias(path + item.name, e.e); + ), + (Static, + DEBUG("handling static " << item.name); + handle_type(e.e.type()); + if( e.e.value().is_valid() ) + { + handle_expr(e.e.value().node()); + } + ), + (Function, + DEBUG("Handling function '" << item.name << "'"); + handle_function(path + item.name, e.e); + ), + (Module, + // Skip, done after all items + ) + ) } - for( auto& fcn : mod.functions() ) - { - DEBUG("Handling function '" << fcn.name << "'"); - handle_function(path + fcn.name, fcn.data); - } for( auto& impl : mod.impls() ) { DEBUG("Handling 'impl' " << impl); @@ -347,10 +355,12 @@ void CASTIterator::handle_module(AST::Path path, AST::Module& mod) // End scope before handling sub-modules end_scope(); - for( auto& submod : mod.submods() ) + for( auto& item : mod.items() ) { - DEBUG("Handling submod '" << submod.first.name() << "'"); - handle_module(path + submod.first.name(), submod.first); + if(!item.data.is_Module()) continue; + auto& submod = item.data.as_Module().e; + DEBUG("Handling submod '" << item.name << "'"); + handle_module(path + item.name, submod); } unsigned int anon_mod_idx = 0; for( auto& anonmod : mod.anon_mods() ) diff --git a/src/convert/ast_iterate.hpp b/src/convert/ast_iterate.hpp index 3872db58..fc57cf57 100644 --- a/src/convert/ast_iterate.hpp +++ b/src/convert/ast_iterate.hpp @@ -13,7 +13,7 @@ class GenericParams; class Impl; class ImplDef; class EnumVariant; -template struct Item; +template struct Named; }; diff --git a/src/convert/decorators.cpp b/src/convert/decorators.cpp index 267f9dc7..06716e5f 100644 --- a/src/convert/decorators.cpp +++ b/src/convert/decorators.cpp @@ -7,6 +7,7 @@ */ #include "ast_iterate.hpp" #include "../ast/ast.hpp" +#include "../ast/crate.hpp" #include #include // C++11, hashmap #include diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 20785af5..cd72d27b 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -9,6 +9,7 @@ */ #include "../common.hpp" #include "../ast/ast.hpp" +#include "../ast/crate.hpp" #include "../parse/parseerror.hpp" #include "ast_iterate.hpp" @@ -161,20 +162,22 @@ private: ret.push_back(t); } if( it->module ) { - for( const auto& t : it->module->traits() ) { - auto trait_path = it->module_path + t.name; + for( const auto& i : it->module->items() ) { + if( !i.data.is_Trait() ) continue ; + const auto& t = i.data.as_Trait().e; + auto trait_path = it->module_path + i.name; DEBUG("t = " << trait_path); - ::std::pair tr(trait_path, t.data); - ret.push_back( tr ); + ret.push_back( ::std::pair(trait_path, t) ); } } } - for( const auto& t : m_module->traits() ) { - auto trait_path = m_module_path + t.name; + for( const auto& i : m_module->items() ) { + if( !i.data.is_Trait() ) continue ; + const auto& t = i.data.as_Trait().e; + auto trait_path = m_module_path + i.name; DEBUG("(mod) t = " << trait_path); - ::std::pair tr(trait_path, t.data); - ret.push_back( tr ); + ret.push_back( ::std::pair(trait_path, t) ); } for( const auto& i : m_module->imports() ) { if( i.data.binding().is_Trait() ) @@ -1369,7 +1372,7 @@ bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST { const auto& fcns = trait.functions(); //DEBUG("fcns = " << fcns); - auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Item& a) { DEBUG("fcn " << a.name); return a.name == item_name; } ); + auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Named& a) { DEBUG("fcn " << a.name); return a.name == item_name; } ); if( it != fcns.end() ) { // Found it. out_is_method = true; @@ -1381,7 +1384,7 @@ bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST } { const auto& types = trait.types(); - auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Item& a) { DEBUG("type " << a.name); return a.name == item_name; } ); + auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Named& a) { DEBUG("type " << a.name); return a.name == item_name; } ); if( it != types.end() ) { // Found it. out_is_method = false; @@ -1756,12 +1759,14 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod //if( new_imp.binding().is_Unbound() ) { // new_imp.resolve(crate, false); //} - mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name()); + // TODO: Get attributes from the source import + mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name(), ::AST::MetaItems()); } - for( auto& submod : mod.submods() ) - { - ResolvePaths_HandleModule_Use(crate, modpath + submod.first.name(), submod.first); + for(auto& item : mod.items()) { + if( item.data.is_Module() ) { + ResolvePaths_HandleModule_Use(crate, modpath + item.name, item.data.as_Module().e); + } } } @@ -1776,8 +1781,11 @@ void SetCrateName_Type(const AST::Crate& crate, ::std::string name, TypeRef& typ void SetCrateName_Mod(const AST::Crate& crate, ::std::string name, AST::Module& mod) { - for(auto& submod : mod.submods()) - SetCrateName_Mod(crate, name, submod.first); + for(auto& item : mod.items()) { + if( item.data.is_Module() ) { + SetCrateName_Mod(crate, name, item.data.as_Module().e); + } + } // Imports 'use' statements for(auto& imp : mod.imports()) { @@ -1787,9 +1795,10 @@ void SetCrateName_Mod(const AST::Crate& crate, ::std::string name, AST::Module& } // TODO: All other types - for(auto& fcn : mod.functions()) - { - SetCrateName_Type(crate, name, fcn.data.rettype()); + for(auto& item : mod.items()) { + if( item.data.is_Function() ) { + SetCrateName_Type(crate, name, item.data.as_Function().e.rettype()); + } } } @@ -1801,6 +1810,7 @@ void ResolvePaths(AST::Crate& crate) { DEBUG(" >>>"); // Pre-process external crates to tag all paths + #if 0 DEBUG(" --- Extern crates"); INDENT(); for(auto& ec : crate.extern_crates()) @@ -1808,6 +1818,7 @@ void ResolvePaths(AST::Crate& crate) SetCrateName_Mod(crate, ec.first, ec.second.root_module()); } UNINDENT(); + #endif // Handle 'use' statements in an initial parss DEBUG(" --- Use Statements"); diff --git a/src/convert/typecheck_bounds.cpp b/src/convert/typecheck_bounds.cpp index 6af5e778..f2cda828 100644 --- a/src/convert/typecheck_bounds.cpp +++ b/src/convert/typecheck_bounds.cpp @@ -2,6 +2,7 @@ */ #include #include "ast_iterate.hpp" +#include "../ast/crate.hpp" #include "../common.hpp" #include diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 69651d7f..1c7099e4 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -7,6 +7,8 @@ */ #include #include "ast_iterate.hpp" +#include "../ast/expr.hpp" +#include "../ast/crate.hpp" #include "../common.hpp" #include diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp index ea6f74c7..2abcc099 100644 --- a/src/convert/typecheck_params.cpp +++ b/src/convert/typecheck_params.cpp @@ -3,6 +3,7 @@ */ #include #include "ast_iterate.hpp" +#include "../ast/crate.hpp" #include "../common.hpp" #include diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index fc338267..30f27d7c 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -5,6 +5,8 @@ * dump_as_rust.cpp * - Dumps the AST of a crate as rust code (annotated) */ +#include "ast/crate.hpp" +#include "ast/ast.hpp" #include "ast/expr.hpp" #include @@ -32,7 +34,7 @@ public: void handle_enum(const AST::Enum& s); void handle_trait(const AST::Trait& s); - void handle_function(const AST::Item& f); + void handle_function(bool is_pub, const ::std::string& name, const AST::Function& f); virtual bool is_const() const override { return true; } virtual void visit(AST::ExprNode_Block& n) override { @@ -557,76 +559,97 @@ void RustPrinter::handle_module(const AST::Module& mod) } need_nl = true; - for( const auto& sm : mod.submods() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Module() ) continue ; + const auto& e = item.data.as_Module().e; + m_os << "\n"; - m_os << indent() << (sm.second ? "pub " : "") << "mod " << sm.first.name() << "\n"; + m_os << indent() << (item.is_pub ? "pub " : "") << "mod " << item.name << "\n"; m_os << indent() << "{\n"; inc_indent(); - handle_module(sm.first); + handle_module(e); dec_indent(); m_os << indent() << "}\n"; m_os << "\n"; } - for( const auto& i : mod.type_aliases() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Type() ) continue ; + const auto& e = item.data.as_Type().e; + if(need_nl) { m_os << "\n"; need_nl = false; } - m_os << indent() << (i.is_pub ? "pub " : "") << "type " << i.name; - print_params(i.data.params()); - m_os << " = " << i.data.type(); - print_bounds(i.data.params()); + m_os << indent() << (item.is_pub ? "pub " : "") << "type " << item.name; + print_params(e.params()); + m_os << " = " << e.type(); + print_bounds(e.params()); m_os << ";\n"; m_os << "\n"; } need_nl = true; - for( const auto& i : mod.structs() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Struct() ) continue ; + const auto& e = item.data.as_Struct().e; + m_os << "\n"; - m_os << indent() << (i.is_pub ? "pub " : "") << "struct " << i.name; - handle_struct(i.data); + m_os << indent() << (item.is_pub ? "pub " : "") << "struct " << item.name; + handle_struct(e); } - for( const auto& i : mod.enums() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Enum() ) continue ; + const auto& e = item.data.as_Enum().e; + m_os << "\n"; - m_os << indent() << (i.is_pub ? "pub " : "") << "enum " << i.name; - handle_enum(i.data); + m_os << indent() << (item.is_pub ? "pub " : "") << "enum " << item.name; + handle_enum(e); } - for( const auto& i : mod.traits() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Trait() ) continue ; + const auto& e = item.data.as_Trait().e; + m_os << "\n"; - m_os << indent() << (i.is_pub ? "pub " : "") << "trait " << i.name; - handle_trait(i.data); + m_os << indent() << (item.is_pub ? "pub " : "") << "trait " << item.name; + handle_trait(e); } - for( const auto& i : mod.statics() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Static() ) continue ; + const auto& e = item.data.as_Static().e; + if(need_nl) { m_os << "\n"; need_nl = false; } - m_os << indent() << (i.is_pub ? "pub " : ""); - switch( i.data.s_class() ) + m_os << indent() << (item.is_pub ? "pub " : ""); + switch( e.s_class() ) { case AST::Static::CONST: m_os << "const "; break; case AST::Static::STATIC: m_os << "static "; break; case AST::Static::MUT: m_os << "static mut "; break; } - m_os << i.name << ": " << i.data.type() << " = "; - i.data.value().visit_nodes(*this); + m_os << item.name << ": " << e.type() << " = "; + e.value().visit_nodes(*this); m_os << ";\n"; } - for( const auto& i : mod.functions() ) + for( const auto& item : mod.items() ) { + if( !item.data.is_Function() ) continue ; + const auto& e = item.data.as_Function().e; + m_os << "\n"; - handle_function(i); + handle_function(item.is_pub, item.name, e); } for( const auto& i : mod.impls() ) @@ -649,7 +672,7 @@ void RustPrinter::handle_module(const AST::Module& mod) } for( const auto& t : i.functions() ) { - handle_function(t); + handle_function(t.is_pub, t.name, t.data); } dec_indent(); m_os << indent() << "}\n"; @@ -912,7 +935,7 @@ void RustPrinter::handle_trait(const AST::Trait& s) } for( const auto& i : s.functions() ) { - handle_function(i); + handle_function(false, i.name, i.data); } dec_indent(); @@ -920,14 +943,18 @@ void RustPrinter::handle_trait(const AST::Trait& s) m_os << "\n"; } -void RustPrinter::handle_function(const AST::Item& f) +void RustPrinter::handle_function(bool is_pub, const ::std::string& name, const AST::Function& f) { m_os << "\n"; - m_os << indent() << (f.is_pub ? "pub " : "") << "fn " << f.name; - print_params(f.data.params()); + m_os << indent(); + m_os << (is_pub ? "pub " : ""); + // TODO: Unsafe + // TODO: Const + m_os << "fn " << name; + print_params(f.params()); m_os << "("; bool is_first = true; - for( const auto& a : f.data.args() ) + for( const auto& a : f.args() ) { if( !is_first ) m_os << ", "; @@ -936,24 +963,24 @@ void RustPrinter::handle_function(const AST::Item& f) is_first = false; } m_os << ")"; - if( !f.data.rettype().is_unit() ) + if( !f.rettype().is_unit() ) { - m_os << " -> " << f.data.rettype().print_pretty(); + m_os << " -> " << f.rettype().print_pretty(); } - if( f.data.code().is_valid() ) + if( f.code().is_valid() ) { m_os << "\n"; - print_bounds(f.data.params()); + print_bounds(f.params()); m_os << indent(); - f.data.code().visit_nodes(*this); + f.code().visit_nodes(*this); m_os << "\n"; //m_os << indent() << f.data.code() << "\n"; } else { - print_bounds(f.data.params()); + print_bounds(f.params()); m_os << ";\n"; } } diff --git a/src/expand/expand.hpp b/src/expand/expand.hpp new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/expand/expand.hpp @@ -0,0 +1 @@ + diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp new file mode 100644 index 00000000..6598af4e --- /dev/null +++ b/src/expand/mod.cpp @@ -0,0 +1,115 @@ +/* + */ +#include +#include +#include +#include +#include + +::std::map< ::std::string, ::std::unique_ptr > g_decorators; +::std::map< ::std::string, ::std::unique_ptr > g_macros; + +void init() __attribute__((constructor(101))); +void init() +{ +} + +void Register_Synext_Decorator(::std::string name, ::std::unique_ptr handler) { + g_decorators[name] = mv$(handler); +} + +void Expand_Decorators_Mod(::AST::Crate& crate, bool is_before_macros, ::AST::Path modpath, ::AST::Module& mod) +{ + for( auto& i : mod.items() ) + { + ::AST::Path path = modpath + i.name; + for( auto& a : i.data.attrs.m_items ) + { + for( auto& d : g_decorators ) { + if( d.first == a.name() && d.second->expand_before_macros() == is_before_macros ) { + d.second->handle(a, crate, path, mod, i.data); + } + } + } + + TU_MATCH(::AST::Item, (i.data), (e), + (None, + // Skip, nothing + ), + (Module, + Expand_Decorators_Mod(crate, is_before_macros, path, e.e); + ), + (Crate, + // Skip, no recursion + ), + + (Struct, + // TODO: Struct items + ), + (Enum, + ), + (Trait, + ), + (Type, + // TODO: Do type aliases require recursion? + ), + + (Function, + // TODO: + ), + (Static, + // TODO: + ) + ) + } +} +void Expand_Decorators(::AST::Crate& crate, bool is_before_macros) +{ + // 1. Crate attributes + for( auto& a : crate.m_attrs.m_items ) + { + for( auto& d : g_decorators ) { + if( d.first == a.name() && d.second->expand_before_macros() == is_before_macros ) { + d.second->handle(a, crate); + } + } + } + + // 2. Module attributes + for( auto& a : crate.m_attrs.m_items ) + { + for( auto& d : g_decorators ) { + if( d.first == a.name() && d.second->expand_before_macros() == is_before_macros ) { + //d.second->handle(a, crate, ::AST::Path(), crate.m_root_module, crate.m_root_module); + } + } + } + + // 3. Module tree + Expand_Decorators_Mod(crate, is_before_macros, ::AST::Path(), crate.m_root_module); +} + +/// Expand decorators that apply before macros are expanded +/// - E.g. #[cfg] #![no_std] ... +void Expand_Decorators_Pre(::AST::Crate& crate) +{ + Expand_Decorators(crate, true); +} + +/// Expand macros +void Expand_Macros(::AST::Crate& crate) +{ +} + +/// Expand decorators that apply _after_ macros +/// - E.g. #[derive] +void Expand_Decorators_Post(::AST::Crate& crate) +{ + Expand_Decorators(crate, false); +} + +/// Expand syntax sugar (e.g. for loops) +void Expand_Sugar(::AST::Crate& crate) +{ +} + diff --git a/src/include/main_bindings.hpp b/src/include/main_bindings.hpp index 91bac742..dc9ef9eb 100644 --- a/src/include/main_bindings.hpp +++ b/src/include/main_bindings.hpp @@ -3,12 +3,26 @@ #ifndef _MAIN_BINDINGS_HPP_ #define _MAIN_BINDINGS_HPP_ -#include "../ast/ast.hpp" +#include + +namespace AST { + class Crate; + class Flat; +} /// Parse a crate from the given file extern AST::Crate Parse_Crate(::std::string mainfile); + + +extern void Expand_Decorators_Pre(::AST::Crate& crate); +extern void Expand_Macros(::AST::Crate& crate); +extern void Expand_Decorators_Post(::AST::Crate& crate); +extern void Expand_Sugar(::AST::Crate& crate); + /// Process #[] decorators extern void Process_Decorators(AST::Crate& crate); + + /// Resolve all in-text paths to absolute variants extern void ResolvePaths(AST::Crate& crate); /// Check that generic bounds are valid diff --git a/src/include/synext.hpp b/src/include/synext.hpp index d4026930..6d229aef 100644 --- a/src/include/synext.hpp +++ b/src/include/synext.hpp @@ -1,11 +1,10 @@ /* */ +#pragma once #ifndef _SYNEXT_HPP_ #define _SYNEXT_HPP_ -#include "../common.hpp" // for mv$ and other things -#include -#include +#include "../ast/item.hpp" namespace AST { class Crate; @@ -13,30 +12,47 @@ namespace AST { class Path; class Module; + class Item; + + class ExprNode; + class Expr; - class Struct; - class Trait; + class MacroInvocation; } +class TokenTree; + + +#include "../common.hpp" // for mv$ and other things +#include +#include + + +class ExpandDecorator +{ +public: + virtual bool expand_before_macros() const = 0; + + virtual void handle(const AST::MetaItem& mi, AST::Crate& crate) const {} + virtual void handle(const AST::MetaItem& mi, AST::Crate& crate, AST::MacroInvocation& mac) const {} + virtual void handle(const AST::MetaItem& mi, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const {} + virtual void handle(const AST::MetaItem& mi, AST::ExprNode& expr) const {}; +}; + -class CDecoratorHandler +class ExpandProcMacro { public: - virtual void handle_item(AST::Crate&, AST::Module&, const AST::MetaItem&, const AST::Path&, AST::Struct& ) const - { - } - virtual void handle_item(AST::Crate&, AST::Module&, const AST::MetaItem&, const AST::Path&, AST::Trait& ) const - { - } + virtual AST::Expr expand(const ::std::string& ident, const TokenTree& tt, AST::Module& mod) = 0; }; -#define STATIC_SYNEXT(_type, ident, _typename) \ - struct register_##_typename##_c {\ - register_##_typename##_c() {\ - Register_Synext_##_type( ident, ::std::unique_ptr(new _typename()) ); \ +#define STATIC_DECORATOR(ident, _handler_class) \ + struct register_##_handler_class##_c {\ + register_##_handler_class##_c() {\ + Register_Synext_Decorator( ident, ::std::unique_ptr(new _handler_class()) ); \ } \ - } s_register_##_typename; + } s_register_##_handler_class; -extern void Register_Synext_Decorator(::std::string name, ::std::unique_ptr handler); +extern void Register_Synext_Decorator(::std::string name, ::std::unique_ptr handler); #endif diff --git a/src/main.cpp b/src/main.cpp index 831e86c7..aed42260 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include "parse/lex.hpp" #include "parse/parseerror.hpp" #include "ast/ast.hpp" +#include "ast/crate.hpp" #include #include #include @@ -80,17 +81,23 @@ int main(int argc, char *argv[]) if( params.last_stage == ProgramParams::STAGE_PARSE ) { return 0; } + + // Load external crates. + CompilePhaseV("LoadCrates", [&]() { + crate.load_externs(); + }); // Iterate all items in the AST, applying syntax extensions - CompilePhaseV("Decorators", [&]() { - Process_Decorators(crate); - //Process_Synexts(crate); + CompilePhaseV("Expand", [&]() { + Expand_Decorators_Pre(crate); + Expand_Macros(crate); + Expand_Decorators_Post(crate); + Expand_Sugar(crate); }); // Run a quick post-parse pass - // TODO: What does this do? CompilePhaseV("PostParse", [&]() { - crate.post_parse(); + crate.index_impls(); }); // XXX: Dump crate before resolve diff --git a/src/parse/common.hpp b/src/parse/common.hpp index e6b552f1..e9b55eb2 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -44,8 +44,8 @@ extern TypeRef Parse_Type(TokenStream& lex); extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable); extern void Parse_Use(TokenStream& lex, ::std::function fcn); -extern AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items); -extern AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items); +extern AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items); +extern AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items); extern AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items); extern void Parse_Impl(TokenStream& lex, AST::Module& mod, AST::MetaItems attrs, bool is_unsafe=false); extern void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index a57cf487..e082dfa3 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -43,7 +43,7 @@ AST::Expr Parse_ExprBlock(TokenStream& lex) ExprNodeP Parse_ExprBlockNode(TokenStream& lex); ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end); -void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Item >& imports); +void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Named >& imports); ExprNodeP Parse_ExprBlockNode(TokenStream& lex) { @@ -52,7 +52,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) ::std::vector nodes; - ::std::unique_ptr local_mod( new AST::Module(AST::MetaItems(),"") ); + ::std::unique_ptr local_mod( new AST::Module("") ); bool keep_mod = false; const LList* prev_modstack = Macro_GetModule(); @@ -240,7 +240,7 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) } } /// Extern block within a block -void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Item >& imports) +void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Named >& imports) { Token tok; @@ -281,7 +281,7 @@ void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AS case TOK_RWORD_FN: GET_CHECK_TOK(tok, lex, TOK_IDENT); name = tok.str(); - imports.push_back( AST::Item( + imports.push_back( AST::Named( ::std::move(name), Parse_FunctionDef(lex, abi, AST::MetaItems(), false, true), false diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 00ba005f..dfbe8372 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -10,6 +10,7 @@ * - Parse_ModRoot */ #include "../ast/ast.hpp" +#include "../ast/crate.hpp" #include "parseerror.hpp" #include "common.hpp" #include "../macros.hpp" @@ -23,7 +24,7 @@ } AST::MetaItem Parse_MetaItem(TokenStream& lex); -void Parse_ModRoot(TokenStream& lex, AST::Module& mod, LList *prev_modstack, bool file_controls_dir, const ::std::string& path); +void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs, LList *prev_modstack, bool file_controls_dir, const ::std::string& path); ::std::vector< ::std::string> Parse_HRB(TokenStream& lex) { @@ -375,7 +376,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt lex.putback(tok); } - return AST::Function(::std::move(attrs), ::std::move(params), ::std::move(ret_type), ::std::move(args)); + return AST::Function(::std::move(params), ::std::move(ret_type), ::std::move(args)); } AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self) @@ -388,7 +389,7 @@ AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST return ret; } -AST::TypeAlias Parse_TypeAlias(TokenStream& lex, AST::MetaItems meta_items) +AST::TypeAlias Parse_TypeAlias(TokenStream& lex, AST::MetaItems& meta_items) { TRACE_FUNCTION; @@ -415,10 +416,10 @@ AST::TypeAlias Parse_TypeAlias(TokenStream& lex, AST::MetaItems meta_items) TypeRef type = Parse_Type(lex); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - return AST::TypeAlias( ::std::move(meta_items), ::std::move(params), ::std::move(type) ); + return AST::TypeAlias( ::std::move(params), ::std::move(type) ); } -AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items) +AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items) { TRACE_FUNCTION; @@ -473,12 +474,12 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items) GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); //if( refs.size() == 0 ) // WARNING( , W000, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong"); - return AST::Struct(::std::move(meta_items), ::std::move(params), ::std::move(refs)); + return AST::Struct(::std::move(params), ::std::move(refs)); } else if(tok.type() == TOK_SEMICOLON) { // Unit-like struct - return AST::Struct(::std::move(meta_items), ::std::move(params), ::std::vector()); + return AST::Struct(::std::move(params), ::std::vector()); } else if(tok.type() == TOK_BRACE_OPEN) { @@ -512,7 +513,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems meta_items) } //if( items.size() == 0 ) // WARNING( , W000, "Use 'struct Name;' instead of 'struct Nam { };' ... ning-nong"); - return AST::Struct(::std::move(meta_items), ::std::move(params), ::std::move(items)); + return AST::Struct(::std::move(params), ::std::move(items)); } else { @@ -560,7 +561,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) } - AST::Trait trait( mv$(meta_items), mv$(params), mv$(supertraits) ); + AST::Trait trait( mv$(params), mv$(supertraits) ); CHECK_TOK(tok, TOK_BRACE_OPEN); while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) @@ -590,7 +591,8 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) } CHECK_TOK(tok, TOK_SEMICOLON); - trait.add_static( mv$(name), ::AST::Static(mv$(item_attrs), AST::Static::STATIC, mv$(ty), val) ); + // TODO: Attrobutes on associated statics + trait.add_static( mv$(name), ::AST::Static(AST::Static::STATIC, mv$(ty), val)/*, mv$(item_attrs)*/ ); break; } case TOK_RWORD_CONST: { GET_CHECK_TOK(tok, lex, TOK_IDENT); @@ -605,7 +607,8 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) } CHECK_TOK(tok, TOK_SEMICOLON); - trait.add_static( mv$(name), ::AST::Static(mv$(item_attrs), AST::Static::CONST, mv$(ty), val) ); + // TODO: Attrobutes on associated constants + trait.add_static( mv$(name), ::AST::Static(AST::Static::CONST, mv$(ty), val)/*, mv$(item_attrs)*/ ); break; } // Associated type case TOK_RWORD_TYPE: { @@ -676,7 +679,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items) return trait; } -AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items) +AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) { TRACE_FUNCTION; @@ -763,7 +766,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items) GET_CHECK_TOK(tok, lex, TOK_COLON); auto ty = Parse_Type(lex); // TODO: Field attributes - fields.push_back( ::AST::Item(mv$(name), mv$(ty), true) ); + fields.push_back( ::AST::Named(mv$(name), mv$(ty), true) ); } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_BRACE_CLOSE); GET_TOK(tok, lex); @@ -787,7 +790,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items) CHECK_TOK(tok, TOK_BRACE_CLOSE); - return AST::Enum( mv$(meta_items), mv$(params), mv$(variants) ); + return AST::Enum( mv$(params), mv$(variants) ); } /// Parse a meta-item declaration (either #![ or #[) @@ -978,7 +981,9 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl) auto val = Parse_Expr(lex, true); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - impl.add_static( is_public, mv$(name), ::AST::Static(mv$(item_attrs), AST::Static::CONST, mv$(ty), mv$(val)) ); + auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val)); + // TODO: Attributes on associated constants + impl.add_static( is_public, mv$(name), mv$(i) /*, mv$(item_attrs)*/ ); break ; } else if( tok.type() == TOK_RWORD_UNSAFE ) @@ -1042,13 +1047,14 @@ void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi) } switch(tok.type()) { - case TOK_RWORD_FN: + case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); // parse function as prototype // - no self - mod.add_function(is_public, tok.str(), Parse_FunctionDef(lex, abi, ::std::move(meta_items), false, true)); + auto i = Parse_FunctionDef(lex, abi, meta_items, false, true); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - break; + break; } case TOK_RWORD_STATIC: { bool is_mut = false; if( GET_TOK(tok, lex) == TOK_RWORD_MUT ) @@ -1062,7 +1068,8 @@ void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi) GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); auto static_class = is_mut ? ::AST::Static::MUT : ::AST::Static::STATIC; - mod.add_static(is_public, mv$(name), ::AST::Static(mv$(meta_items), static_class, type, ::AST::Expr())); + auto i = ::AST::Static(static_class, type, ::AST::Expr()); + mod.add_static(is_public, mv$(name), mv$(i), mv$(meta_items)); break; } default: throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_STATIC}); @@ -1499,7 +1506,7 @@ void Parse_ExternCrate(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_i } GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - mod.add_ext_crate(path, name); + mod.add_ext_crate(path, name, mv$(meta_items)); // Handle #[macro_use]/#[macro_use(...)] //auto at = meta_items.get("macro_use"); @@ -1526,9 +1533,9 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c { // `use ...` case TOK_RWORD_USE: - Parse_Use(lex, [&mod,is_public,&file_path](AST::Path p, std::string s) { + Parse_Use(lex, [&mod,is_public,&file_path,meta_items](AST::Path p, std::string s) { DEBUG(file_path << " - use " << p << " as '" << s << "'"); - mod.add_alias(is_public, mv$(p), s); + mod.add_alias(is_public, mv$(p), s, meta_items); }); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); break; @@ -1543,23 +1550,26 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c switch(GET_TOK(tok, lex)) { // `extern "" fn ...` - case TOK_RWORD_FN: + case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, abi, ::std::move(meta_items), false)); - break; + auto i = Parse_FunctionDefWithCode(lex, abi, meta_items, false); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); + break; } // `extern "" { ...` case TOK_BRACE_OPEN: - Parse_ExternBlock(lex, mod, ::std::move(abi)); + // TODO: Use meta items on extern block + Parse_ExternBlock(lex, mod, mv$(abi)); break; default: throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_BRACE_OPEN}); } break; } // `extern fn ...` - case TOK_RWORD_FN: + case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "C", ::std::move(meta_items), false)); - break; + auto i = Parse_FunctionDefWithCode(lex, "C", meta_items, false); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); + break; } // `extern { ...` case TOK_BRACE_OPEN: Parse_ExternBlock(lex, mod, "C"); @@ -1587,18 +1597,21 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c GET_CHECK_TOK(tok, lex, TOK_EQUAL); AST::Expr val = Parse_Expr(lex, true); GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); - mod.add_static(is_public, name, AST::Static(::std::move(meta_items), AST::Static::CONST, type, val)); + mod.add_static(is_public, name, AST::Static(AST::Static::CONST, type, val), mv$(meta_items)); break; } - case TOK_RWORD_UNSAFE: + case TOK_RWORD_UNSAFE: { GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); GET_CHECK_TOK(tok, lex, TOK_IDENT); - mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); - break; + // TODO: Mark as const and unsafe + auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); + break; } case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); // - self not allowed, not prototype // TODO: Mark as const - mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); + auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); break; } default: throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_RWORD_FN}); @@ -1625,7 +1638,8 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); mod.add_static(is_public, name, - AST::Static(::std::move(meta_items), (is_mut ? AST::Static::MUT : AST::Static::STATIC), type, val) + AST::Static((is_mut ? AST::Static::MUT : AST::Static::STATIC), type, val), + mv$(meta_items) ); break; } @@ -1647,21 +1661,24 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c } GET_CHECK_TOK(tok, lex, TOK_RWORD_FN); GET_CHECK_TOK(tok, lex, TOK_IDENT); - mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, abi, ::std::move(meta_items), false)); + auto i = Parse_FunctionDefWithCode(lex, abi, meta_items, false); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); break; } // `unsafe fn` - case TOK_RWORD_FN: + case TOK_RWORD_FN: { GET_CHECK_TOK(tok, lex, TOK_IDENT); // - self not allowed, not prototype // TODO: Mark as unsafe - mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); - break; + auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); + mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items)); + break; } // `unsafe trait` case TOK_RWORD_TRAIT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); // TODO: Mark as unsafe - mod.add_trait(is_public, name, Parse_TraitDef(lex, meta_items)); + auto i = Parse_TraitDef(lex, meta_items); + mod.add_trait(is_public, name, mv$(i), meta_items); break; } // `unsafe impl` case TOK_RWORD_IMPL: @@ -1676,25 +1693,29 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); // - self not allowed, not prototype - mod.add_function(is_public, name, Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false)); + auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false); + mod.add_function(is_public, name, mv$(i), mv$(meta_items)); break; } // `type` case TOK_RWORD_TYPE: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = tok.str(); - mod.add_typealias(is_public, name, Parse_TypeAlias(lex, meta_items)); + auto name = mv$(tok.str()); + auto i = Parse_TypeAlias(lex, meta_items); + mod.add_typealias(is_public, mv$(name), mv$(i), mv$(meta_items)); break; } // `struct` case TOK_RWORD_STRUCT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = tok.str(); - mod.add_struct( is_public, name, Parse_Struct(lex, meta_items) ); + auto name = mv$(tok.str()); + auto i = Parse_Struct(lex, meta_items); + mod.add_struct( is_public, name, mv$(i), mv$(meta_items) ); break; } // `enum` case TOK_RWORD_ENUM: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); - mod.add_enum(is_public, name, Parse_EnumDef(lex, meta_items)); + auto i = Parse_EnumDef(lex, meta_items); + mod.add_enum(is_public, name, mv$(i), mv$(meta_items)); break; } // `impl` case TOK_RWORD_IMPL: @@ -1704,21 +1725,22 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c case TOK_RWORD_TRAIT: { GET_CHECK_TOK(tok, lex, TOK_IDENT); ::std::string name = tok.str(); - mod.add_trait(is_public, name, Parse_TraitDef(lex, meta_items)); + auto i = Parse_TraitDef(lex, meta_items); + mod.add_trait(is_public, name, mv$(i), mv$(meta_items)); break; } case TOK_RWORD_MOD: { GET_CHECK_TOK(tok, lex, TOK_IDENT); auto name = tok.str(); DEBUG("Sub module '" << name << "'"); - AST::Module submod( mv$(meta_items), mv$(tok.str())); + AST::Module submod( mv$(tok.str())); // Rules for external files (/ path handling): // - IF using stdin (path='-') - Disallow and propagate '-' as path // - IF a #[path] attribute was passed, allow // - IF in crate root or mod.rs, allow (input flag) // - else, disallow and set flag - ::std::string path_attr = (submod.attrs().has("path") ? submod.attrs().get("path")->string() : ""); + ::std::string path_attr = (meta_items.has("path") ? meta_items.get("path")->string() : ""); ::std::string sub_path; bool sub_file_controls_dir = true; @@ -1746,7 +1768,7 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c switch( GET_TOK(tok, lex) ) { case TOK_BRACE_OPEN: { - Parse_ModRoot(lex, submod, &modstack, sub_file_controls_dir, sub_path+"/"); + Parse_ModRoot(lex, submod, meta_items, &modstack, sub_file_controls_dir, sub_path+"/"); GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); break; } case TOK_SEMICOLON: @@ -1772,14 +1794,14 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c { // Load from dir Lexer sub_lex(newpath_dir + "mod.rs"); - Parse_ModRoot(sub_lex, submod, &modstack, sub_file_controls_dir, newpath_dir); + Parse_ModRoot(sub_lex, submod, meta_items, &modstack, sub_file_controls_dir, newpath_dir); GET_CHECK_TOK(tok, sub_lex, TOK_EOF); } else if( ifs_file.is_open() ) { // Load from file Lexer sub_lex(newpath_file); - Parse_ModRoot(sub_lex, submod, &modstack, sub_file_controls_dir, newpath_file); + Parse_ModRoot(sub_lex, submod, meta_items, &modstack, sub_file_controls_dir, newpath_file); GET_CHECK_TOK(tok, sub_lex, TOK_EOF); } else @@ -1793,7 +1815,7 @@ void Parse_Mod_Item(TokenStream& lex, LList& modstack, bool file_c throw ParseError::Generic("Expected { or ; after module name"); } submod.prescan(); - mod.add_submod(is_public, ::std::move(submod)); + mod.add_submod(is_public, ::std::move(submod), mv$(meta_items)); Macro_SetModule(modstack); break; } @@ -1865,7 +1887,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod, LList } } -void Parse_ModRoot(TokenStream& lex, AST::Module& mod, LList *prev_modstack, bool file_controls_dir, const ::std::string& path) +void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs, LList *prev_modstack, bool file_controls_dir, const ::std::string& path) { TRACE_FUNCTION; LList modstack(prev_modstack, &mod); @@ -1879,7 +1901,7 @@ void Parse_ModRoot(TokenStream& lex, AST::Module& mod, LList *prev AST::MetaItem item = Parse_MetaItem(lex); GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - mod.add_attr( item ); + mod_attrs.push_back( item ); } lex.putback(tok); @@ -1898,34 +1920,8 @@ AST::Crate Parse_Crate(::std::string mainfile) ::std::string mainpath = (p != ::std::string::npos ? ::std::string(mainfile.begin(), mainfile.begin()+p+1) : "./"); AST::Crate crate; - AST::Module& rootmod = crate.root_module(); - - // Attributes on module/crate - while( GET_TOK(tok, lex) == TOK_CATTR_OPEN ) - { - AST::MetaItem item = Parse_MetaItem(lex); - GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); - rootmod.add_attr( item ); - } - lex.putback(tok); - - // Check for crate attributes - for( const auto& attr : rootmod.attrs().m_items ) - { - if( attr.name() == "no_std" ) { - crate.m_load_std = false; - // TODO: Load core instead - } - else if( attr.name() == "no_core" ) { - crate.m_load_std = false; - } - else { - // TODO: - } - } - - Parse_ModRoot(lex, rootmod, NULL, true, mainpath); + Parse_ModRoot(lex, crate.root_module(), crate.m_attrs, NULL, true, mainpath); return crate; } diff --git a/src/synexts/derive.cpp b/src/synexts/derive.cpp index b8741cfe..17fb0a96 100644 --- a/src/synexts/derive.cpp +++ b/src/synexts/derive.cpp @@ -83,7 +83,7 @@ public: DEBUG("node = " << *node); AST::Function fcn( - AST::MetaItems(), AST::GenericParams(), + AST::GenericParams(), ret_type, vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), false, TypeRef("Self")) ), @@ -145,14 +145,21 @@ static void derive_item(AST::Module& mod, const AST::MetaItem& attr, const AST:: } class Decorator_Derive: - public CDecoratorHandler + public ExpandDecorator { public: - void handle_item(AST::Crate& , AST::Module& mod, const AST::MetaItem& attr, const AST::Path& path, AST::Struct& str) const override + bool expand_before_macros() const override { return false; } + void handle(const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override { - derive_item(mod, attr, path, str); + TU_MATCH_DEF(::AST::Item, (i), (e), + ( + ), + (Struct, + derive_item(mod, attr, path, e.e); + ) + ) } }; -STATIC_SYNEXT(Decorator, "derive", Decorator_Derive) +STATIC_DECORATOR("derive", Decorator_Derive) diff --git a/src/synexts/lang_item.cpp b/src/synexts/lang_item.cpp index fb831539..a38a73f3 100644 --- a/src/synexts/lang_item.cpp +++ b/src/synexts/lang_item.cpp @@ -8,6 +8,7 @@ #include #include "../common.hpp" #include "../ast/ast.hpp" +#include "../ast/crate.hpp" void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type) @@ -76,18 +77,28 @@ void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::str else { throw CompileError::Generic(FMT("Unknown lang item '" << name << "'")); } + + } class Decorator_LangItem: - public CDecoratorHandler + public ExpandDecorator { public: - void handle_item(AST::Crate& crate, AST::Module& mod, const AST::MetaItem& attr, const AST::Path& path, AST::Trait& t) const override + bool expand_before_macros() const override { return true; } + void handle(const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override { - handle_lang_item(crate, path, attr.string(), AST::ITEM_TRAIT); + TU_MATCH_DEF(::AST::Item, (i), (e), + ( + // TODO: Error + ), + (Trait, + handle_lang_item(crate, path, attr.string(), AST::ITEM_TRAIT); + ) + ) } }; -STATIC_SYNEXT(Decorator, "lang", Decorator_LangItem) +STATIC_DECORATOR("lang", Decorator_LangItem) diff --git a/src/types.cpp b/src/types.cpp index 454ed801..33bf38f8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -9,6 +9,7 @@ */ #include "types.hpp" #include "ast/ast.hpp" +#include "ast/crate.hpp" /// Mappings from internal type names to the core type enum static const struct { -- cgit v1.2.3