diff options
author | John Hodge <tpg@mutabah.net> | 2016-03-06 17:41:46 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-03-06 17:41:46 +0800 |
commit | 859d43ae7012da10a58de5926d096dc817596fce (patch) | |
tree | 66a0dc09e8be4e5c7763bfc4af0cfae488c2c595 | |
parent | f430222343e18fec9f97c9b9fdfdc17667b94505 (diff) | |
download | mrust-859d43ae7012da10a58de5926d096dc817596fce.tar.gz |
HUGE REFACTOR - Move named module items into a tagged union
- Item attributes now "owned" by the parent
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | src/ast/ast.cpp | 503 | ||||
-rw-r--r-- | src/ast/ast.hpp | 514 | ||||
-rw-r--r-- | src/ast/crate.cpp | 345 | ||||
-rw-r--r-- | src/ast/crate.hpp | 102 | ||||
-rw-r--r-- | src/ast/generics.hpp | 138 | ||||
-rw-r--r-- | src/ast/item.hpp | 57 | ||||
-rw-r--r-- | src/ast/path.cpp | 4 | ||||
-rw-r--r-- | src/ast/provided_module.cpp | 4 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 80 | ||||
-rw-r--r-- | src/convert/ast_iterate.hpp | 2 | ||||
-rw-r--r-- | src/convert/decorators.cpp | 1 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 49 | ||||
-rw-r--r-- | src/convert/typecheck_bounds.cpp | 1 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 2 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 1 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 101 | ||||
-rw-r--r-- | src/expand/expand.hpp | 1 | ||||
-rw-r--r-- | src/expand/mod.cpp | 115 | ||||
-rw-r--r-- | src/include/main_bindings.hpp | 16 | ||||
-rw-r--r-- | src/include/synext.hpp | 52 | ||||
-rw-r--r-- | src/main.cpp | 17 | ||||
-rw-r--r-- | src/parse/common.hpp | 4 | ||||
-rw-r--r-- | src/parse/expr.cpp | 8 | ||||
-rw-r--r-- | src/parse/root.cpp | 160 | ||||
-rw-r--r-- | src/synexts/derive.cpp | 17 | ||||
-rw-r--r-- | src/synexts/lang_item.cpp | 19 | ||||
-rw-r--r-- | src/types.cpp | 1 |
28 files changed, 1295 insertions, 1026 deletions
@@ -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, ¶ms) )
- {
- 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, ¶ms) ) {
- 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, ¶ms) ) + { + 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, ¶ms) ) { + 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 { |