summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-03-06 17:41:46 +0800
committerJohn Hodge <tpg@mutabah.net>2016-03-06 17:41:46 +0800
commit859d43ae7012da10a58de5926d096dc817596fce (patch)
tree66a0dc09e8be4e5c7763bfc4af0cfae488c2c595
parentf430222343e18fec9f97c9b9fdfdc17667b94505 (diff)
downloadmrust-859d43ae7012da10a58de5926d096dc817596fce.tar.gz
HUGE REFACTOR - Move named module items into a tagged union
- Item attributes now "owned" by the parent
-rw-r--r--Makefile7
-rw-r--r--src/ast/ast.cpp503
-rw-r--r--src/ast/ast.hpp514
-rw-r--r--src/ast/crate.cpp345
-rw-r--r--src/ast/crate.hpp102
-rw-r--r--src/ast/generics.hpp138
-rw-r--r--src/ast/item.hpp57
-rw-r--r--src/ast/path.cpp4
-rw-r--r--src/ast/provided_module.cpp4
-rw-r--r--src/convert/ast_iterate.cpp80
-rw-r--r--src/convert/ast_iterate.hpp2
-rw-r--r--src/convert/decorators.cpp1
-rw-r--r--src/convert/resolve.cpp49
-rw-r--r--src/convert/typecheck_bounds.cpp1
-rw-r--r--src/convert/typecheck_expr.cpp2
-rw-r--r--src/convert/typecheck_params.cpp1
-rw-r--r--src/dump_as_rust.cpp101
-rw-r--r--src/expand/expand.hpp1
-rw-r--r--src/expand/mod.cpp115
-rw-r--r--src/include/main_bindings.hpp16
-rw-r--r--src/include/synext.hpp52
-rw-r--r--src/main.cpp17
-rw-r--r--src/parse/common.hpp4
-rw-r--r--src/parse/expr.cpp8
-rw-r--r--src/parse/root.cpp160
-rw-r--r--src/synexts/derive.cpp17
-rw-r--r--src/synexts/lang_item.cpp19
-rw-r--r--src/types.cpp1
28 files changed, 1295 insertions, 1026 deletions
diff --git a/Makefile b/Makefile
index f79ecf7d..dd677c89 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ LINKFLAGS := -g
LIBS :=
CXXFLAGS := -g -Wall -std=c++11 -Werror
#CXXFLAGS += -O3
-CPPFLAGS := -I src/include/
+CPPFLAGS := -I src/include/ -I src/
SHELL = bash
@@ -25,13 +25,14 @@ BIN := bin/mrustc$(EXESUF)
OBJ := main.o macros.o types.o serialise.o
OBJ += span.o
-OBJ += ast/ast.o ast/path.o ast/expr.o ast/pattern.o
+OBJ += ast/ast.o ast/crate.o ast/path.o ast/expr.o ast/pattern.o
OBJ += ast/provided_module.o
OBJ += parse/parseerror.o parse/lex.o
OBJ += parse/root.o parse/paths.o parse/types.o parse/expr.o parse/pattern.o
+OBJ += expand/mod.o
OBJ += dump_as_rust.o
OBJ += convert/ast_iterate.o
-OBJ += convert/decorators.o
+#OBJ += convert/decorators.o
OBJ += convert/resolve.o convert/typecheck_bounds.o convert/typecheck_params.o convert/typecheck_expr.o
OBJ += convert/flatten.o convert/render.o
OBJ += synexts/derive.o synexts/lang_item.o
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 <iostream>
@@ -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<char> 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<void(Module& mod)> 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<Module&>( const_cast<const Crate*>(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<TypeRef> _params;
- TRACE_FUNCTION_F("trait="<<trait<<", type="<<type);
-
- // 1. Look for a negative impl for this type
- for( auto implptr : m_neg_impl_index )
- {
- const ImplDef& neg_impl = *implptr;
-
- if( neg_impl.matches(_params, trait, type) )
- {
- return false;
- }
- }
- DEBUG("No negative impl of " << trait << " for " << type);
-
- // 2. Look for a positive impl for this type (i.e. an unsafe impl)
- for( auto implptr : m_impl_index )
- {
- const Impl& impl = *implptr;
- if( impl.def().matches(_params, trait, type) )
- {
- return true;
- }
- }
- DEBUG("No positive impl of " << trait << " for " << type);
-
- // 3. If none found, destructure the type
- return type.impls_wildcard(*this, trait);
-}
-
-
-bool Crate::find_inherent_impls(const TypeRef& type, ::std::function<bool(const Impl& , ::std::vector<TypeRef> )> 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<TypeRef> out_params;
- if( impl.def().matches(out_params, AST::Path(), type) )
- {
- if( callback(impl, out_params) ) {
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-::rust::option<ImplRef> Crate::find_impl(const Path& trait, const TypeRef& type) const
-{
- ::std::vector<TypeRef> params;
- Impl *out_impl;
- if( find_impl(trait, type, &out_impl, &params) )
- {
- return ::rust::Some( ImplRef(*out_impl, params) );
- }
- else {
- return ::rust::None<ImplRef>();
- }
-}
-
-bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_params) const
-{
- TRACE_FUNCTION_F("trait = " << trait << ", type = " << type);
-
- // If no params output provided, use a dud locaton
- ::std::vector<TypeRef> dud_params;
- if(out_params)
- *out_params = ::std::vector<TypeRef>();
- 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<TypeRef> _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 "<<name<<" for type " <<type));
-}
-
-void Crate::load_extern_crate(::std::string name)
-{
- ::std::ifstream is("output/"+name+".ast");
- if( !is.is_open() )
- {
- throw ParseError::Generic("Can't open crate '" + name + "'");
- }
- Deserialiser_TextTree ds(is);
- Deserialiser& d = ds;
-
- ExternCrate ret;
- d.item( ret.crate() );
-
- ret.prescan();
-
- m_extern_crates.insert( make_pair(::std::move(name), ::std::move(ret)) );
-}
-SERIALISE_TYPE_A(Crate::, "AST_Crate", {
- s.item(m_load_std);
- s.item(m_extern_crates);
- s.item(m_root_module);
-})
-
-ExternCrate::ExternCrate()
-{
-}
-
-ExternCrate::ExternCrate(const char *path)
-{
- throw ParseError::Todo("Load extern crate from a file");
-}
-
-// Fill runtime-generated structures in the crate
-void ExternCrate::prescan()
-{
- TRACE_FUNCTION;
-
- Crate& cr = m_crate;
-
- cr.m_root_module.prescan();
-
- for( const auto& mi : cr.m_root_module.macro_imports_res() )
- {
- DEBUG("Macro (I) '"<<mi.name<<"' is_pub="<<mi.is_pub);
- if( mi.is_pub )
- {
- m_crate.m_exported_macros.insert( ::std::make_pair(mi.name, mi.data) );
- }
- }
- for( const auto& mi : cr.m_root_module.macros() )
- {
- DEBUG("Macro '"<<mi.name<<"' is_pub="<<mi.is_pub);
- if( mi.is_pub )
- {
- m_crate.m_exported_macros.insert( ::std::make_pair(mi.name, &mi.data) );
- }
- }
-}
-
-SERIALISE_TYPE(ExternCrate::, "AST_ExternCrate", {
-},{
-})
-
SERIALISE_TYPE_A(MacroInvocation::, "AST_MacroInvocation", {
s.item(m_attrs);
s.item(m_macro_name);
@@ -509,43 +203,71 @@ SERIALISE_TYPE_A(MacroInvocation::, "AST_MacroInvocation", {
SERIALISE_TYPE_A(Module::, "AST_Module", {
s.item(m_name);
- s.item(m_attrs);
- s.item(m_extern_crates);
- s.item(m_submods);
+ s.item(m_items);
s.item(m_macros);
s.item(m_imports);
- s.item(m_type_aliases);
-
- s.item(m_traits);
- s.item(m_enums);
- s.item(m_structs);
- s.item(m_statics);
- s.item(m_functions);
s.item(m_impls);
})
+void Module::add_item(bool is_pub, ::std::string name, Item it, MetaItems attrs) {
+ m_items.push_back( Named<Item>( 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<Path>( 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_name<<"'");
-
- for( auto& sm_p : m_submods )
- {
- sm_p.first.prescan();
- }
-
- for( const auto& macro_imp : m_macro_imports )
- {
- resolve_macro_import( *(Crate*)0, macro_imp.first, macro_imp.second );
- }
+ //TRACE_FUNCTION;
+ //DEBUG("- '"<<m_name<<"'");
+ //
+ //for( auto& sm_p : m_submods )
+ //{
+ // sm_p.first.prescan();
+ //}
+ //
+ ///*
+ //for( const auto& macro_imp : m_macro_imports )
+ //{
+ // resolve_macro_import( *(Crate*)0, macro_imp.first, macro_imp.second );
+ //}
+ //*/
}
void Module::resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name)
{
+ /*
DEBUG("Import macros from " << modname << " matching '" << macro_name << "'");
for( const auto& sm_p : m_submods )
{
@@ -601,20 +323,26 @@ void Module::resolve_macro_import(const Crate& crate, const ::std::string& modna
}
throw ::std::runtime_error( FMT("Could not find sub-module '" << modname << "' for macro import") );
+ */
}
void Module::iterate_functions(fcn_visitor_t *visitor, const Crate& crate)
{
- for( auto& fcn_item : this->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 T>
-typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector<Item<T> >& vec, const ::std::string& name)
+typename ::std::vector<Named<T> >::const_iterator find_named(const ::std::vector<Named<T> >& vec, const ::std::string& name)
{
- return ::std::find_if(vec.begin(), vec.end(), [&name](const Item<T>& x) {
+ return ::std::find_if(vec.begin(), vec.end(), [&name](const Named<T>& 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<Module,bool>& 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<TypeParam> m_type_params;
- ::std::vector< ::std::string > m_lifetime_params;
- ::std::vector<GenericBound> 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<TypeParam>& ty_params() const { return m_type_params; }
- const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; }
- const ::std::vector<GenericBound>& bounds() const { return m_bounds; }
- ::std::vector<TypeParam>& ty_params() { return m_type_params; }
- ::std::vector<GenericBound>& 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<TypeRef>& types) const;
- bool check_params(Crate& crate, ::std::vector<TypeRef>& 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 <typename T>
-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 <typename T>
-struct Item:
- public ItemNS<T>,
- public Serialisable
-{
- Item():
- ItemNS<T>()
- {}
- Item(Item&&) noexcept = default;
- Item(const Item&) = default;
- Item(::std::string name, T data, bool is_pub):
- ItemNS<T>( ::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 <typename T>
-using ItemList = ::std::vector<Item<T> >;
-
-typedef Item<TypeRef> StructItem;
+typedef Named<TypeRef> 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<AST::Pattern,TypeRef> > 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<AST::Path> m_supertraits;
- ItemList<TypeAlias> m_types;
- ItemList<Function> m_functions;
- ItemList<Static> m_statics;
+ NamedList<TypeAlias> m_types;
+ NamedList<Function> m_functions;
+ NamedList<Static> m_statics;
public:
Trait() {}
- Trait(MetaItems attrs, GenericParams params, ::std::vector<Path> supertraits):
- m_attrs( mv$(attrs) ),
+ Trait(GenericParams params, ::std::vector<Path> 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<Path>& supertraits() const { return m_supertraits; }
- const ItemList<Function>& functions() const { return m_functions; }
- const ItemList<TypeAlias>& types() const { return m_types; }
- const ItemList<Static>& statics() const { return m_statics; }
+ const NamedList<Function>& functions() const { return m_functions; }
+ const NamedList<TypeAlias>& types() const { return m_types; }
+ const NamedList<Static>& statics() const { return m_statics; }
GenericParams& params() { return m_params; }
::std::vector<Path>& supertraits() { return m_supertraits; }
- ItemList<Function>& functions() { return m_functions; }
- ItemList<TypeAlias>& types() { return m_types; }
+ NamedList<Function>& functions() { return m_functions; }
+ NamedList<TypeAlias>& types() { return m_types; }
void add_type(::std::string name, TypeRef type) {
- m_types.push_back( Item<TypeAlias>(move(name), TypeAlias(MetaItems(), GenericParams(), move(type)), true) );
+ m_types.push_back( Named<TypeAlias>(move(name), TypeAlias(GenericParams(), move(type)), true) );
}
void add_function(::std::string name, Function fcn) {
- m_functions.push_back( Item<Function>(::std::move(name), ::std::move(fcn), true) );
+ m_functions.push_back( Named<Function>(::std::move(name), ::std::move(fcn), true) );
}
void add_static(::std::string name, Static v) {
- m_statics.push_back( Item<Static>(mv$(name), mv$(v), true) );
+ m_statics.push_back( Named<Static>(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<TypeRef> 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<StructItem> 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<EnumVariant> m_variants;
public:
Enum() {}
- Enum( MetaItems attrs, GenericParams params, ::std::vector<EnumVariant> variants ):
- m_attrs( move(attrs) ),
+ Enum( GenericParams params, ::std::vector<EnumVariant> 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<EnumVariant>& variants() const { return m_variants; }
@@ -446,22 +262,18 @@ public:
class Struct:
public Serialisable
{
- MetaItems m_attrs;
GenericParams m_params;
::std::vector<StructItem> m_fields;
public:
Struct() {}
- Struct( MetaItems attrs, GenericParams params, ::std::vector<StructItem> fields ):
- m_attrs( move(attrs) ),
+ Struct( GenericParams params, ::std::vector<StructItem> 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<StructItem>& fields() const { return m_fields; }
- MetaItems& attrs() { return m_attrs; }
GenericParams& params() { return m_params; }
::std::vector<StructItem>& fields() { return m_fields; }
@@ -509,9 +321,9 @@ class Impl:
{
ImplDef m_def;
- ItemList<TypeRef> m_types;
- ItemList<Function> m_functions;
- ItemList<Static> m_statics;
+ NamedList<TypeRef> m_types;
+ NamedList<Function> m_functions;
+ NamedList<Static> m_statics;
::std::vector<MacroInvocation> m_macro_invocations;
::std::vector< ::std::pair< ::std::vector<TypeRef>, 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<Function>( ::std::move(name), ::std::move(fcn), is_public ) );
+ m_functions.push_back( Named<Function>( ::std::move(name), ::std::move(fcn), is_public ) );
}
void add_type(bool is_public, ::std::string name, TypeRef type) {
- m_types.push_back( Item<TypeRef>( ::std::move(name), ::std::move(type), is_public ) );
+ m_types.push_back( Named<TypeRef>( ::std::move(name), ::std::move(type), is_public ) );
}
void add_static(bool is_public, ::std::string name, Static v) {
- m_statics.push_back( Item<Static>( mv$(name), mv$(v), is_public ) );
+ m_statics.push_back( Named<Static>( 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<Function>& functions() const { return m_functions; }
- const ItemList<TypeRef>& types() const { return m_types; }
+ const NamedList<Function>& functions() const { return m_functions; }
+ const NamedList<TypeRef>& types() const { return m_types; }
ImplDef& def() { return m_def; }
- ItemList<Function>& functions() { return m_functions; }
- ItemList<TypeRef>& types() { return m_types; }
+ NamedList<Function>& functions() { return m_functions; }
+ NamedList<TypeRef>& 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<Function> > itemlist_fcn_t;
- typedef ::std::vector< ::std::pair<Module, bool> > itemlist_mod_t;
- typedef ::std::vector< Item<Path> > itemlist_use_t;
- typedef ::std::vector< Item< ::std::string> > itemlist_ext_t;
- typedef ::std::vector< Item<Static> > itemlist_static_t;
- typedef ::std::vector< Item<Enum> > itemlist_enum_t;
- typedef ::std::vector< Item<Struct> > itemlist_struct_t;
- typedef ::std::vector< Item<MacroRules> > itemlist_macros_t;
- typedef ::std::multimap< ::std::string, ::std::string > macro_imports_t;
+ typedef ::std::vector< Named<Path> > 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<Named<Item>> m_items;
+ /// `use` imports (public and private)
itemlist_use_t m_imports;
- ::std::vector<Item<TypeAlias> > m_type_aliases;
- itemlist_ext_t m_extern_crates;
- ::std::vector<Module*> m_anon_modules; // TODO: Should this be serialisable?
-
- itemlist_macros_t m_macros;
- macro_imports_t m_macro_imports; // module => macro
- ::std::vector< ItemNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
+ /// Macro invocations
::std::vector<MacroInvocation> m_macro_invocations;
-
-
- itemlist_static_t m_statics;
- ItemList<Trait> m_traits;
- itemlist_enum_t m_enums;
- itemlist_struct_t m_structs;
+ /// Impl blocks
::std::vector<Impl> m_impls;
+ /// Negative impl blocks
::std::vector<ImplDef> m_neg_impls;
+
+
+ // --- Runtime caches and state ---
+ ::std::vector<Module*> m_anon_modules; // TODO: Should this be serialisable?
+
+ ::std::vector< NamedNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
+ ::std::vector< Named<MacroRules> > 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<Path>( move(name), move(path), is_public) );
- }
- void add_typealias(bool is_public, ::std::string name, TypeAlias alias) {
- m_type_aliases.push_back( Item<TypeAlias>( move(name), move(alias), is_public ) );
- }
- //void add_constant(bool is_public, ::std::string name, TypeRef type, Expr val) {
- // m_statics.push_back( Item<Static>( 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<Static>( 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<Static>( move(name), ::std::move(item), is_public) );
- }
- void add_trait(bool is_public, ::std::string name, Trait trait) {
- m_traits.push_back( Item<Trait>( move(name), move(trait), is_public) );
- }
- void add_struct(bool is_public, ::std::string name, Struct item) {
- m_structs.push_back( Item<Struct>( move(name), move(item), is_public) );
- }
- void add_enum(bool is_public, ::std::string name, Enum inst) {
- m_enums.push_back( Item<Enum>( move(name), move(inst), is_public ) );
- }
- void add_function(bool is_public, ::std::string name, Function func) {
- m_functions.push_back( Item<Function>( 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<MacroRules>( move(name), move(macro), is_exported ) );
+ m_macros.push_back( Named<MacroRules>( 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<Path>, Use)
+ _(AST::Named<Path>, Use)
#undef _
};
ItemRef find_item(const ::std::string& needle, bool allow_leaves = true, bool ignore_private_wildcard = true) const;
+
+ ::std::vector<Named<Item>>& items() { return m_items; }
+ const ::std::vector<Named<Item>>& 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<Item<TypeAlias> >& type_aliases() { return m_type_aliases; }
- itemlist_ext_t& extern_crates() { return m_extern_crates; }
- ::std::vector<Impl>& impls() { return m_impls; }
- itemlist_static_t& statics() { return m_statics; }
- ItemList<Trait>& traits() { return m_traits; }
- itemlist_enum_t& enums () { return m_enums; }
- itemlist_struct_t& structs() { return m_structs; }
- ::std::vector<Module*>& 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<Item<TypeAlias> >& type_aliases() const { return m_type_aliases; }
- const itemlist_ext_t& extern_crates() const { return m_extern_crates; }
+
+ ::std::vector<Impl>& impls() { return m_impls; }
const ::std::vector<Impl>& impls() const { return m_impls; }
- const itemlist_static_t& statics() const { return m_statics; }
- const ItemList<Trait>& 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<Module*>& anon_mods() const { return m_anon_modules; }
+ // No need to mutate this list
const ::std::vector<ImplDef>& neg_impls() const { return m_neg_impls; }
+
+ ::std::vector<Module*>& anon_mods() { return m_anon_modules; }
+ const ::std::vector<Module*>& 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<ItemNS<const MacroRules*> > macro_imports_res() const { return m_macro_import_res; }
+
+ const NamedList<MacroRules>& macros() const { return m_macros; }
+ const ::std::vector<NamedNS<const MacroRules*> > 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<char> find_named_item(const ::std::string& name) const;
};
-class Crate:
- public Serialisable
-{
-public:
- ::std::map< TypeRef, ::std::vector<Impl*> > m_impl_map;
- ::std::vector<Impl*> m_impl_index;
- ::std::vector<const ImplDef*> 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<ImplRef> find_inherent_impls(const TypeRef& type) const;
- bool find_inherent_impls(const TypeRef& type, ::std::function<bool(const Impl& , ::std::vector<TypeRef> )>) const;
- ::rust::option<ImplRef> find_impl(const Path& trait, const TypeRef& type) const;
- bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_prams=nullptr) const;
- const ::rust::option<Impl&> get_impl(const Path& trait, const TypeRef& type) {
- Impl* impl_ptr;
- ::std::vector<TypeRef> params;
- if( find_impl(trait, type, &impl_ptr, &params) ) {
- return ::rust::option<Impl&>( impl_ptr->get_concrete(params) );
- }
- else {
- return ::rust::option<Impl&>();
- }
- }
- 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<StructItem> 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 <serialiser_texttree.hpp>
+
+namespace {
+ void iterate_module(::AST::Module& mod, ::std::function<void(::AST::Module& mod)> 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<Module&>( const_cast<const Crate*>(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<TypeRef> _params;
+ TRACE_FUNCTION_F("trait="<<trait<<", type="<<type);
+
+ // 1. Look for a negative impl for this type
+ for( auto implptr : m_neg_impl_index )
+ {
+ const ImplDef& neg_impl = *implptr;
+
+ if( neg_impl.matches(_params, trait, type) )
+ {
+ return false;
+ }
+ }
+ DEBUG("No negative impl of " << trait << " for " << type);
+
+ // 2. Look for a positive impl for this type (i.e. an unsafe impl)
+ for( auto implptr : m_impl_index )
+ {
+ const Impl& impl = *implptr;
+ if( impl.def().matches(_params, trait, type) )
+ {
+ return true;
+ }
+ }
+ DEBUG("No positive impl of " << trait << " for " << type);
+
+ // 3. If none found, destructure the type
+ return type.impls_wildcard(*this, trait);
+}
+
+
+bool Crate::find_inherent_impls(const TypeRef& type, ::std::function<bool(const Impl& , ::std::vector<TypeRef> )> 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<TypeRef> out_params;
+ if( impl.def().matches(out_params, AST::Path(), type) )
+ {
+ if( callback(impl, out_params) ) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+::rust::option<ImplRef> Crate::find_impl(const Path& trait, const TypeRef& type) const
+{
+ ::std::vector<TypeRef> params;
+ Impl *out_impl;
+ if( find_impl(trait, type, &out_impl, &params) )
+ {
+ return ::rust::Some( ImplRef(*out_impl, params) );
+ }
+ else {
+ return ::rust::None<ImplRef>();
+ }
+}
+
+bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_params) const
+{
+ TRACE_FUNCTION_F("trait = " << trait << ", type = " << type);
+
+ // If no params output provided, use a dud locaton
+ ::std::vector<TypeRef> dud_params;
+ if(out_params)
+ *out_params = ::std::vector<TypeRef>();
+ 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<TypeRef> _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 "<<name<<" for type " <<type));
+}
+
+void Crate::load_extern_crate(::std::string name)
+{
+ ::std::ifstream is("output/"+name+".ast");
+ if( !is.is_open() )
+ {
+ throw ParseError::Generic("Can't open crate '" + name + "'");
+ }
+ Deserialiser_TextTree ds(is);
+ Deserialiser& d = ds;
+
+ ExternCrate ret;
+ ret.deserialise( d );
+
+ m_extern_crates.insert( make_pair(::std::move(name), ::std::move(ret)) );
+}
+SERIALISE_TYPE_A(Crate::, "AST_Crate", {
+ s.item(m_load_std);
+ s.item(m_extern_crates);
+ s.item(m_root_module);
+})
+
+ExternCrate::ExternCrate()
+{
+}
+
+ExternCrate::ExternCrate(const char *path)
+{
+ throw ParseError::Todo("Load extern crate from a file");
+}
+
+// Fill runtime-generated structures in the crate
+#if 0
+void ExternCrate::prescan()
+{
+ TRACE_FUNCTION;
+
+ Crate& cr = m_crate;
+
+ cr.m_root_module.prescan();
+
+ for( const auto& mi : cr.m_root_module.macro_imports_res() )
+ {
+ DEBUG("Macro (I) '"<<mi.name<<"' is_pub="<<mi.is_pub);
+ if( mi.is_pub )
+ {
+ m_crate.m_exported_macros.insert( ::std::make_pair(mi.name, mi.data) );
+ }
+ }
+ for( const auto& mi : cr.m_root_module.macros() )
+ {
+ DEBUG("Macro '"<<mi.name<<"' is_pub="<<mi.is_pub);
+ if( mi.is_pub )
+ {
+ m_crate.m_exported_macros.insert( ::std::make_pair(mi.name, &mi.data) );
+ }
+ }
+}
+#endif
+
+SERIALISE_TYPE(ExternCrate::, "AST_ExternCrate", {
+},{
+})
+
+
+} // namespace AST
+
diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp
new file mode 100644
index 00000000..769f78b8
--- /dev/null
+++ b/src/ast/crate.hpp
@@ -0,0 +1,102 @@
+
+#pragma once
+
+#include "ast.hpp"
+#include "../types.hpp"
+
+namespace AST {
+
+
+class ExternCrate;
+
+class Crate:
+ public Serialisable
+{
+public:
+ ::std::map< TypeRef, ::std::vector<Impl*> > m_impl_map;
+ ::std::vector<Impl*> m_impl_index;
+ ::std::vector<const ImplDef*> 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<ImplRef> find_inherent_impls(const TypeRef& type) const;
+ bool find_inherent_impls(const TypeRef& type, ::std::function<bool(const Impl& , ::std::vector<TypeRef> )>) const;
+ ::rust::option<ImplRef> find_impl(const Path& trait, const TypeRef& type) const;
+ bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_prams=nullptr) const;
+ const ::rust::option<Impl&> get_impl(const Path& trait, const TypeRef& type) {
+ Impl* impl_ptr;
+ ::std::vector<TypeRef> params;
+ if( find_impl(trait, type, &impl_ptr, &params) ) {
+ return ::rust::option<Impl&>( impl_ptr->get_concrete(params) );
+ }
+ else {
+ return ::rust::option<Impl&>();
+ }
+ }
+ 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 <string>
+#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<TypeParam> m_type_params;
+ ::std::vector< ::std::string > m_lifetime_params;
+ ::std::vector<GenericBound> 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<TypeParam>& ty_params() const { return m_type_params; }
+ const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; }
+ const ::std::vector<GenericBound>& bounds() const { return m_bounds; }
+ ::std::vector<TypeParam>& ty_params() { return m_type_params; }
+ ::std::vector<GenericBound>& 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<TypeRef>& types) const;
+ bool check_params(Crate& crate, ::std::vector<TypeRef>& 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 <string>
+#include <serialise.hpp>
+
+namespace AST {
+
+template <typename T>
+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 <typename T>
+struct Named:
+ public NamedNS<T>,
+ public Serialisable
+{
+ Named():
+ NamedNS<T>()
+ {}
+ Named(Named&&) noexcept = default;
+ Named(const Named&) = default;
+ Named(::std::string name, T data, bool is_pub):
+ NamedNS<T>( ::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 <typename T>
+using NamedList = ::std::vector<Named<T> >;
+
+} // 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 T>
-typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector<Item<T> >& vec, const ::std::string& name)
+typename ::std::vector<Named<T> >::const_iterator find_named(const ::std::vector<Named<T> >& vec, const ::std::string& name)
{
- return ::std::find_if(vec.begin(), vec.end(), [&name](const Item<T>& x) {
+ return ::std::find_if(vec.begin(), vec.end(), [&name](const Named<T>& 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::StructItem> {
+ AST::Struct( AST::GenericParams(), ::std::vector<AST::StructItem> {
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<typename T> struct Item;
+template<typename T> 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 <main_bindings.hpp>
#include <unordered_map> // C++11, hashmap
#include <synext.hpp>
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<AST::Path, const AST::Trait&> tr(trait_path, t.data);
- ret.push_back( tr );
+ ret.push_back( ::std::pair<AST::Path, const AST::Trait&>(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<AST::Path, const AST::Trait&> tr(trait_path, t.data);
- ret.push_back( tr );
+ ret.push_back( ::std::pair<AST::Path, const AST::Trait&>(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<AST::Function>& a) { DEBUG("fcn " << a.name); return a.name == item_name; } );
+ auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Named<AST::Function>& 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<AST::TypeAlias>& a) { DEBUG("type " << a.name); return a.name == item_name; } );
+ auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Named<AST::TypeAlias>& 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 <main_bindings.hpp>
#include "ast_iterate.hpp"
+#include "../ast/crate.hpp"
#include "../common.hpp"
#include <stdexcept>
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 <main_bindings.hpp>
#include "ast_iterate.hpp"
+#include "../ast/expr.hpp"
+#include "../ast/crate.hpp"
#include "../common.hpp"
#include <stdexcept>
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 <main_bindings.hpp>
#include "ast_iterate.hpp"
+#include "../ast/crate.hpp"
#include "../common.hpp"
#include <stdexcept>
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 <main_bindings.hpp>
@@ -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<AST::Function>& 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<AST::Function>& 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<AST::Function>& 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 <ast/ast.hpp>
+#include <ast/crate.hpp>
+#include <main_bindings.hpp>
+#include <synext.hpp>
+#include <map>
+
+::std::map< ::std::string, ::std::unique_ptr<ExpandDecorator> > g_decorators;
+::std::map< ::std::string, ::std::unique_ptr<ExpandProcMacro> > g_macros;
+
+void init() __attribute__((constructor(101)));
+void init()
+{
+}
+
+void Register_Synext_Decorator(::std::string name, ::std::unique_ptr<ExpandDecorator> 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 <string>
+
+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 <string>
-#include <memory>
+#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 <string>
+#include <memory>
+
+
+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<C##_type##Handler>(new _typename()) ); \
+#define STATIC_DECORATOR(ident, _handler_class) \
+ struct register_##_handler_class##_c {\
+ register_##_handler_class##_c() {\
+ Register_Synext_Decorator( ident, ::std::unique_ptr<ExpandDecorator>(new _handler_class()) ); \
} \
- } s_register_##_typename;
+ } s_register_##_handler_class;
-extern void Register_Synext_Decorator(::std::string name, ::std::unique_ptr<CDecoratorHandler> handler);
+extern void Register_Synext_Decorator(::std::string name, ::std::unique_ptr<ExpandDecorator> 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 <serialiser_texttree.hpp>
#include <cstring>
#include <main_bindings.hpp>
@@ -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<void(AST::Path, ::std::string)> 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<AST::Function> >& imports);
+void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Named<AST::Function> >& imports);
ExprNodeP Parse_ExprBlockNode(TokenStream& lex)
{
@@ -52,7 +52,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex)
::std::vector<ExprNodeP> nodes;
- ::std::unique_ptr<AST::Module> local_mod( new AST::Module(AST::MetaItems(),"") );
+ ::std::unique_ptr<AST::Module> local_mod( new AST::Module("") );
bool keep_mod = false;
const LList<AST::Module*>* 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<AST::Function> >& imports)
+void Parse_ExternBlock(TokenStream& lex, AST::MetaItems attrs, ::std::vector< AST::Named<AST::Function> >& 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<AST::Function>(
+ imports.push_back( AST::Named<AST::Function>(
::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<AST::Module*> *prev_modstack, bool file_controls_dir, const ::std::string& path);
+void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs, LList<AST::Module*> *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<AST::StructItem>());
+ return AST::Struct(::std::move(params), ::std::vector<AST::StructItem>());
}
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<TypeRef>(mv$(name), mv$(ty), true) );
+ fields.push_back( ::AST::Named<TypeRef>(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<AST::Module*>& 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<AST::Module*>& modstack, bool file_c
switch(GET_TOK(tok, lex))
{
// `extern "<ABI>" 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 "<ABI>" { ...`
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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>& 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<AST::Module*>
}
}
-void Parse_ModRoot(TokenStream& lex, AST::Module& mod, LList<AST::Module*> *prev_modstack, bool file_controls_dir, const ::std::string& path)
+void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs, LList<AST::Module*> *prev_modstack, bool file_controls_dir, const ::std::string& path)
{
TRACE_FUNCTION;
LList<AST::Module*> modstack(prev_modstack, &mod);
@@ -1879,7 +1901,7 @@ void Parse_ModRoot(TokenStream& lex, AST::Module& mod, LList<AST::Module*> *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 <synext.hpp>
#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 {