diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | src/ast/ast.hpp | 8 | ||||
-rw-r--r-- | src/ast/path.cpp | 407 | ||||
-rw-r--r-- | src/ast/path.hpp | 185 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 107 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 43 | ||||
-rw-r--r-- | src/parse/expr.cpp | 2 | ||||
-rw-r--r-- | src/parse/paths.cpp | 20 | ||||
-rw-r--r-- | src/parse/root.cpp | 16 | ||||
-rw-r--r-- | src/synexts/lang_item.cpp | 2 |
10 files changed, 496 insertions, 301 deletions
@@ -34,14 +34,17 @@ all: $(BIN) clean: $(RM) -r $(BIN) $(OBJ) + +PIPECMD ?= 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 + output/%.ast: samples/%.rs $(BIN) @mkdir -p output/ - $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 + $(DBG) $(BIN) $< --emit ast -o $@ $(PIPECMD) RUSTCSRC := ~/Source/rust/rustc-nightly/ output/core.ast: $(RUSTCSRC)src/libcore/lib.rs $(BIN) @mkdir -p output/ - $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 40 ; test $${PIPESTATUS[0]} -eq 0 + $(DBG) $(BIN) $< --emit ast -o $@ $(PIPECMD) test: output/core.ast $(BIN) diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 2376b054..b913e334 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -215,7 +215,7 @@ struct ItemNS ItemNS():
is_pub(false)
{}
- ItemNS(ItemNS&&) = default;
+ ItemNS(ItemNS&&) noexcept = default;
ItemNS(const ItemNS&) = default;
ItemNS(::std::string name, T data, bool is_pub):
name( ::std::move(name) ),
@@ -237,7 +237,7 @@ struct Item: Item():
ItemNS<T>()
{}
- Item(Item&&) = default;
+ 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 )
@@ -343,7 +343,7 @@ public: m_fcn_class(CLASS_UNBOUND)
{}
Function(const Function&) = delete;
- Function(Function&&) = default;
+ Function(Function&&) noexcept = default;
Function(MetaItems attrs, TypeParams params, Class fcn_class, TypeRef ret_type, Arglist args):
m_attrs( move(attrs) ),
m_fcn_class(fcn_class),
@@ -501,6 +501,7 @@ class ImplDef: TypeRef m_type;
public:
ImplDef() {}
+ ImplDef(ImplDef&&) noexcept = default;
ImplDef(MetaItems attrs, TypeParams params, Path trait_type, TypeRef impl_type):
m_attrs( move(attrs) ),
m_params( move(params) ),
@@ -536,6 +537,7 @@ class Impl: ::std::vector< ::std::pair< ::std::vector<TypeRef>, Impl > > m_concrete_impls;
public:
Impl() {}
+ Impl(Impl&&) noexcept = default;
Impl(MetaItems attrs, TypeParams params, TypeRef impl_type, Path trait_type):
m_def( move(attrs), move(params), move(trait_type), move(impl_type) )
{}
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 9757e576..b3b3ab56 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -63,37 +63,64 @@ typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector< // --- AST::Path AST::Path::Path(TagUfcs, TypeRef type, TypeRef trait): - m_class(UFCS), - m_ufcs({::std::move(type), ::std::move(trait)} ) + m_class( AST::Path::Class::make_UFCS({box$(type), box$(trait), {}}) ) { } +AST::Path::Path(const Path& x): + m_class() +{ + TU_MATCH(Class, (x.m_class), (ent), + (Invalid, m_class = Class::make_Invalid({});), + (Local, + m_class = Class::make_Local({name: ent.name}); + ), + (Relative, + m_class = Class::make_Relative({nodes: ent.nodes}); + ), + (Self, + m_class = Class::make_Self({nodes: ent.nodes}); + ), + (Super, + m_class = Class::make_Super({nodes: ent.nodes}); + ), + (Absolute, + m_class = Class::make_Absolute({nodes: ent.nodes}); + ), + (UFCS, + m_class = Class::make_UFCS({ box$(TypeRef(*ent.type)), box$(TypeRef(*ent.trait)), ent.nodes }); + ) + ) +} /// Resolve a path into a canonical form, and bind it to the target value void Path::resolve(const Crate& root_crate, bool expect_params) { TRACE_FUNCTION_F("*this = "<< *this); - if(m_class == ABSOLUTE) + if( m_class.is_Absolute() ) { resolve_absolute(root_crate, expect_params); - else if(m_class == UFCS) + } + else if(m_class.is_UFCS()) { resolve_ufcs(root_crate, expect_params); + } else throw ParseError::BugCheck("Calling Path::resolve on non-absolute path"); } void Path::resolve_absolute(const Crate& root_crate, bool expect_params) { + auto& nodes = m_class.as_Absolute().nodes; DEBUG("m_crate = '" << m_crate << "'"); unsigned int slice_from = 0; // Used when rewriting the path to be relative to its crate root ::std::vector<const Module*> mod_stack; const Module* mod = &root_crate.get_root_module(m_crate); - for(unsigned int i = 0; i < m_nodes.size(); i ++ ) + for(unsigned int i = 0; i < nodes.size(); i ++ ) { mod_stack.push_back(mod); - const bool is_last = (i+1 == m_nodes.size()); - const bool is_sec_last = (i+2 == m_nodes.size()); - const PathNode& node = m_nodes[i]; - DEBUG("[" << i << "/"<<m_nodes.size()<<"]: " << node); + const bool is_last = (i+1 == nodes.size()); + const bool is_sec_last = (i+2 == nodes.size()); + const PathNode& node = nodes[i]; + DEBUG("[" << i << "/"<<nodes.size()<<"]: " << node); if( node.name()[0] == '#' ) { @@ -122,13 +149,13 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) case AST::Module::ItemRef::ITEM_none: // If parent node is anon, backtrack and try again // TODO: I feel like this shouldn't be done here, instead perform this when absolutising (now that find_item is reusable) - if( i > 0 && m_nodes[i-1].name()[0] == '#' && m_nodes[i-1].name().size() > 1 ) + if( i > 0 && nodes[i-1].name()[0] == '#' && nodes[i-1].name().size() > 1 ) { i --; mod_stack.pop_back(); mod = mod_stack.back(); mod_stack.pop_back(); - m_nodes.erase(m_nodes.begin()+i); + nodes.erase(nodes.begin()+i); i --; DEBUG("Failed to locate item in nested, look upwards - " << *this); @@ -164,7 +191,7 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) // Make a copy of the path, replace params with it, then replace *this? // - Maybe leave that up to other code? if( is_last ) { - check_param_counts(ta.params(), expect_params, m_nodes[i]); + check_param_counts(ta.params(), expect_params, nodes[i]); m_binding = PathBinding(&ta); goto ret; } @@ -178,7 +205,7 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) const auto& fn = item.unwrap_Function(); DEBUG("Found function"); if( is_last ) { - check_param_counts(fn.params(), expect_params, m_nodes[i]); + check_param_counts(fn.params(), expect_params, nodes[i]); m_binding = PathBinding(&fn); goto ret; } @@ -192,12 +219,12 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) const auto& t = item.unwrap_Trait(); DEBUG("Found trait"); if( is_last ) { - check_param_counts(t.params(), expect_params, m_nodes[i]); + check_param_counts(t.params(), expect_params, nodes[i]); m_binding = PathBinding(&t); goto ret; } else if( is_sec_last ) { - check_param_counts(t.params(), expect_params, m_nodes[i]); + check_param_counts(t.params(), expect_params, nodes[i]); // TODO: Also check params on item m_binding = PathBinding(PathBinding::TagItem(), &t); goto ret; @@ -212,13 +239,13 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) const auto& str = item.unwrap_Struct(); DEBUG("Found struct"); if( is_last ) { - check_param_counts(str.params(), expect_params, m_nodes[i]); + check_param_counts(str.params(), expect_params, nodes[i]); bind_struct(str, node.args()); goto ret; } else if( is_sec_last ) { - check_param_counts(str.params(), expect_params, m_nodes[i]); - bind_struct_member(str, node.args(), m_nodes[i+1]); + check_param_counts(str.params(), expect_params, nodes[i]); + bind_struct_member(str, node.args(), nodes[i+1]); goto ret; } else { @@ -231,13 +258,13 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) const auto& enm = item.unwrap_Enum(); DEBUG("Found enum"); if( is_last ) { - check_param_counts(enm.params(), expect_params, m_nodes[i]); + check_param_counts(enm.params(), expect_params, nodes[i]); bind_enum(enm, node.args()); goto ret; } else if( is_sec_last ) { - check_param_counts(enm.params(), expect_params, m_nodes[i]); - bind_enum_var(enm, m_nodes[i+1].name(), node.args()); + check_param_counts(enm.params(), expect_params, nodes[i]); + bind_enum_var(enm, nodes[i+1].name(), node.args()); goto ret; } else { @@ -262,41 +289,33 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params) // Re-export case AST::Module::ItemRef::ITEM_Use: { const auto& imp = item.unwrap_Use(); + AST::Path newpath = imp.data; + auto& newnodes = newpath.m_class.as_Absolute().nodes; + DEBUG("Re-exported path " << imp.data); if( imp.name == "" ) { // Replace nodes 0:i-1 with source path, then recurse - AST::Path newpath = imp.data; - for( unsigned int j = i; j < m_nodes.size(); j ++ ) + for( unsigned int j = i; j < nodes.size(); j ++ ) { - newpath.m_nodes.push_back( m_nodes[j] ); + newnodes.push_back( nodes[j] ); } - - DEBUG("- newpath = " << newpath); - // TODO: This should check for recursion somehow - newpath.resolve(root_crate, expect_params); - - *this = newpath; - DEBUG("Alias resolved, *this = " << *this); - return; } else { // replace nodes 0:i with the source path - DEBUG("Re-exported path " << imp.data); - AST::Path newpath = imp.data; - for( unsigned int j = i+1; j < m_nodes.size(); j ++ ) + for( unsigned int j = i+1; j < nodes.size(); j ++ ) { - newpath.m_nodes.push_back( m_nodes[j] ); + newnodes.push_back( nodes[j] ); } - DEBUG("- newpath = " << newpath); - // TODO: This should check for recursion somehow - newpath.resolve(root_crate, expect_params); - - *this = newpath; - DEBUG("Alias resolved, *this = " << *this); - return; } - break; } + + DEBUG("- newpath = " << newpath); + // TODO: This should check for recursion somehow + newpath.resolve(root_crate, expect_params); + + *this = mv$(newpath); + DEBUG("Alias resolved, *this = " << *this); + return; } } } @@ -307,20 +326,21 @@ ret: if( slice_from > 0 ) { DEBUG("Removing " << slice_from << " nodes to rebase path to crate root"); - m_nodes.erase(m_nodes.begin(), m_nodes.begin()+slice_from); + nodes.erase(nodes.begin(), nodes.begin()+slice_from); } return ; } void Path::resolve_ufcs(const Crate& root_crate, bool expect_params) { - auto& type = m_ufcs.at(0); - auto& trait = m_ufcs.at(1); + auto& data = m_class.as_UFCS(); + auto& type = *data.type; + auto& trait = *data.trait; // TODO: I can forsee <T>::Assoc::Item desugaring into < <T>::Assoc >::Item, but that will be messy to code - assert(m_nodes.size()); - if(m_nodes.size() != 1) throw ParseError::Todo("Path::resolve_ufcs - Are multi-node UFCS paths valid?"); - auto& node = m_nodes.at(0); + assert(data.nodes.size()); + if(data.nodes.size() != 1) throw ParseError::Todo("Path::resolve_ufcs - Are multi-node UFCS paths valid?"); + auto& node = data.nodes.at(0); // If the type is unknown (at this time) if( type.is_wildcard() || type.is_type_param() ) @@ -517,26 +537,34 @@ void Path::bind_static(const Static& ent) void Path::resolve_args(::std::function<TypeRef(const char*)> fcn) { TRACE_FUNCTION_F(*this); - for(auto& n : nodes()) + + TU_MATCH(Path::Class, (m_class), (ent), + (Invalid), + (Local, ), + + (Relative, Path::resolve_args_nl(ent.nodes, fcn); ), + (Absolute, Path::resolve_args_nl(ent.nodes, fcn); ), + (Self , Path::resolve_args_nl(ent.nodes, fcn); ), + (Super , Path::resolve_args_nl(ent.nodes, fcn); ), + (UFCS, + ent.type->resolve_args(fcn); + ent.trait->resolve_args(fcn); + Path::resolve_args_nl(ent.nodes, fcn); + ) + ) +} +void Path::resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn) +{ + for(auto& n : nodes) { for(auto& p : n.args()) p.resolve_args(fcn); } - - switch(m_class) - { - case Path::UFCS: - m_ufcs[0].resolve_args(fcn); - m_ufcs[1].resolve_args(fcn); - break; - default: - break; - } } Path& Path::operator+=(const Path& other) { - for(auto& node : other.m_nodes) + for(auto& node : other.nodes()) append(node); // If the path is modified, clear the binding m_binding = PathBinding(); @@ -547,15 +575,32 @@ Path& Path::operator+=(const Path& other) void Path::match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const { // TODO: Ensure that the two paths are of a compatible class (same class?) - if( m_nodes.size() != other.m_nodes.size() ) + // - This will crash atm if they aren't the same + TU_MATCH(Path::Class, (m_class, other.m_class), (ent, x_ent), + (Invalid), + (Local, ), + + (Relative, Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), + (Absolute, Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), + (Self , Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), + (Super , Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), + (UFCS, + Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); + throw ::std::runtime_error("TODO: UFCS Path::match_args"); + ) + ) +} + +void Path::match_args_nl(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b, ::std::function<void(const char*,const TypeRef&)> fcn) +{ + if( nodes_a.size() != nodes_b.size() ) throw ::std::runtime_error("Type mismatch (path size)"); - for( unsigned int i = 0; i < m_nodes.size(); i++ ) + for( unsigned int i = 0; i < nodes_a.size(); i++ ) { - auto& pn1 = m_nodes[i]; - auto& pn2 = other.m_nodes[i]; + auto& pn1 = nodes_a[i]; + auto& pn2 = nodes_b[i]; if( pn1.name() != pn2.name() ) throw ::std::runtime_error("Type mismatch (path component)"); - if( pn1.args().size() != pn2.args().size() ) throw ::std::runtime_error("Type mismatch (path component param count)"); @@ -585,18 +630,38 @@ bool Path::is_concrete() const /// cause two different paths to look the same. int Path::equal_no_generic(const Path& x) const { - if( m_class != x.m_class ) + if( m_class.tag() != x.m_class.tag() ) return -1; if( m_crate != x.m_crate ) return -1; + TU_MATCH(Path::Class, (m_class, x.m_class), (ent, x_ent), + (Invalid, return 0; ), + (Local, return (ent.name == x_ent.name ? 0 : 1); ), + + (Relative, return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), + (Absolute, return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), + (Self , return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), + (Super , return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), + (UFCS, + throw ::std::runtime_error("TODO: UFCS Path::equal_no_generic"); + return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); + ) + ) + throw ::std::runtime_error("Path::equal_no_generic - fell off"); +} + +int Path::node_lists_equal_no_generic(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b) +{ + if( nodes_a.size() != nodes_b.size() ) { + return -1; + } + bool conditional_match = false; unsigned int i = 0; - for( const auto &e : m_nodes ) + for( const auto &e : nodes_a ) { - if( i >= x.m_nodes.size() ) - return -1; - const auto& xe = x.m_nodes[i]; + const auto& xe = nodes_b[i]; if( e.name() != xe.name() ) return -1; @@ -623,96 +688,121 @@ Ordering Path::ord(const Path& x) const { Ordering rv; - rv = ::ord( (unsigned)m_class, (unsigned)x.m_class ); + rv = ::ord( (unsigned)m_class.tag(), (unsigned)x.m_class.tag() ); if( rv != OrdEqual ) return rv; rv = ::ord( m_crate, x.m_crate ); if( rv != OrdEqual ) return rv; - rv = ::ord( m_nodes, x.m_nodes ); - if( rv != OrdEqual ) return rv; + TU_MATCH(Path::Class, (m_class, x.m_class), (ent, x_ent), + (Invalid, + return OrdEqual; + ), + (Local, + return ::ord(ent.name, x_ent.name); + ), + (Relative, + return ::ord(ent.nodes, x_ent.nodes); + ), + (Self, + return ::ord(ent.nodes, x_ent.nodes); + ), + (Super, + return ::ord(ent.nodes, x_ent.nodes); + ), + (Absolute, + return ::ord(ent.nodes, x_ent.nodes); + ), + (UFCS, + rv = ent.type->ord( *x_ent.type ); + if( rv != OrdEqual ) return rv; + rv = ent.trait->ord( *x_ent.trait ); + if( rv != OrdEqual ) return rv; + return ::ord(ent.nodes, x_ent.nodes); + ) + ) return OrdEqual; } void Path::print_pretty(::std::ostream& os) const { - switch(m_class) - { - case Path::INVALID: os << "/* inv */"; break; - case Path::VARIABLE:os << m_nodes[0].name(); break; - case Path::RELATIVE: - for(const auto& n : m_nodes) { - if( &n != &m_nodes[0] ) os << "::"; - os << "::" << n; - } - break; - case Path::SELF: + TU_MATCH(Path::Class, (m_class), (ent), + (Invalid, os << "/* inv */"; ), + (Local, os << ent.name;), + (Relative, + for(const auto& n : ent.nodes) os << "::" << n; + ), + (Self, os << "self"; - for(const auto& n : m_nodes) os << "::" << n; - break; - case Path::SUPER: + for(const auto& n : ent.nodes) os << "::" << n; + ), + (Super, os << "super"; - for(const auto& n : m_nodes) os << "::" << n; - break; - case Path::ABSOLUTE: + for(const auto& n : ent.nodes) os << "::" << n; + ), + (Absolute, if( m_crate != "" ) - os << "::" << m_crate; - for(const auto& n : m_nodes) + os << "::\"" << m_crate << "\""; + for(const auto& n : ent.nodes) os << "::" << n; - break; - case Path::UFCS: + ), + (UFCS, throw ParseError::Todo("Path::print_pretty - UFCS"); - } + ) + ) } ::std::ostream& operator<<(::std::ostream& os, const Path& path) { - if( path.m_nodes.size() == 0 && path.m_class == Path::RELATIVE ) - { - os << "/* null path */"; - return os; - } + //if( path.m_nodes.size() == 0 && path.m_class == Path::RELATIVE ) + //{ + // os << "/* null path */"; + // return os; + //} #if PRETTY_PATH_PRINT - switch(path.m_class) - { - case Path::INVALID: os << "/*inv*/"; break; - case Path::VARIABLE: os << "/*var*/" << path.m_nodes[0].name(); break; - case Path::RELATIVE: - for(const auto& n : path.m_nodes) + TU_MATCH(Path::Class, (path.m_class), (ent), + (Invalid, + os << "/*inv*/"; + ), + (Local, + os << "/*var*/" << ent.name; + ), + (Relative, + for(const auto& n : ent.nodes) { #if PRETTY_PATH_PRINT - if( &n != &path.m_nodes[0] ) { + if( &n != &ent.nodes[0] ) { os << "::"; } #endif os << n; } - break; - case Path::SELF: + ), + (Self, os << "self"; - for(const auto& n : path.m_nodes) + for(const auto& n : ent.nodes) { #if PRETTY_PATH_PRINT os << "::"; #endif os << n; } - break; - case Path::SUPER: + ), + (Super, os << "super"; - for(const auto& n : path.m_nodes) + for(const auto& n : ent.nodes) { #if PRETTY_PATH_PRINT os << "::"; #endif os << n; } - break; - case Path::ABSOLUTE: + ), + (Absolute, if( path.m_crate != "" ) os << "::\""<<path.m_crate<<"\""; - for(const auto& n : path.m_nodes) + for(const auto& n : ent.nodes) { #if PRETTY_PATH_PRINT os << "::"; @@ -720,12 +810,13 @@ void Path::print_pretty(::std::ostream& os) const os << n; } os << "/*" << path.m_binding << "*/"; - break; - case Path::UFCS: - os << "/*ufcs*/<" << path.m_ufcs[0] << " as " << path.m_ufcs[1] << ">"; - for(const auto& n : path.m_nodes) + ), + (UFCS, + os << "/*ufcs*/<" << *ent.type << " as " << *ent.trait << ">"; + for(const auto& n : ent.nodes) os << "::" << n; - } + ) + ) #else switch(path.m_class) { @@ -739,45 +830,49 @@ void Path::print_pretty(::std::ostream& os) const #endif return os; } -::Serialiser& operator<<(Serialiser& s, Path::Class pc) -{ - #define _(v) case Path::v: s << #v; break; - switch(pc) - { - _(INVALID ) - _(VARIABLE) - _(RELATIVE) - _(SELF ) - _(SUPER ) - _(ABSOLUTE) - _(UFCS ) - } - #undef _ - return s; +void operator%(Serialiser& s, Path::Class::Tag c) { + s << Path::Class::tag_to_str(c); } -void operator>>(Deserialiser& s, Path::Class& pc) -{ +void operator%(::Deserialiser& s, Path::Class::Tag& c) { ::std::string n; s.item(n); - #define _(v) if(n == #v) pc = Path::v; else - _(INVALID ) - _(VARIABLE) - _(RELATIVE) - _(SELF ) - _(SUPER ) - _(ABSOLUTE) - _(UFCS ) - throw ::std::runtime_error("Unknown path class : " + n); - #undef _ + c = Path::Class::tag_from_str(n); } +#define _D(VAR, ...) case Class::VAR: { m_class = Class::make_null_##VAR(); auto& ent = m_class.as_##VAR(); (void)&ent; __VA_ARGS__ } break; SERIALISE_TYPE(Path::, "AST_Path", { - s << m_class; - s << m_crate; - s << m_nodes; + s % m_class.tag(); + TU_MATCH(Path::Class, (m_class), (ent), + (Invalid), + (Local, s << ent.name; ), + (Relative, s.item(ent.nodes); ), + (Absolute, s.item(ent.nodes); ), + (Self , s.item(ent.nodes); ), + (Super , s.item(ent.nodes); ), + (UFCS, + s.item( ent.type ); + s.item( ent.trait ); + s.item( ent.nodes ); + ) + ) },{ - s >> m_class; - s.item(m_crate); - s.item(m_nodes); + Class::Tag tag; + s % tag; + switch(tag) + { + _D(Invalid) + _D(Local , s.item( ent.name ); ) + + _D(Relative, s.item(ent.nodes); ) + _D(Absolute, s.item(ent.nodes); ) + _D(Self , s.item(ent.nodes); ) + _D(Super , s.item(ent.nodes); ) + _D(UFCS, + s.item( ent.type ); + s.item( ent.trait ); + s.item( ent.nodes ); + ) + } }) +#undef _D } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 7cc4a181..7bb50bee 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -11,6 +11,7 @@ #include <cassert> #include <serialise.hpp> #include <tagged_union.hpp> +#include <string> class TypeRef; @@ -26,17 +27,17 @@ class Trait; class Static; class Function; -//TAGGED_ENUM(Binding, Unbound, -// (BndModule, (const Module* module_; ) ), -// (BndEnum, (const Enum* enum_; ) ), -// (BndStruct, (const Struct* struct_; ) ), -// (BndTrait, (const Trait* trait_; ) ), -// (BndStatic, (const Static* static_; ) ), -// (BndFunction, (const Function* func_; ) ), -// (BndEnumVar, (const Enum* enum_; unsigned int idx; ) ), -// (BndTypeAlias, (const TypeAlias* alias_; ) ), -// (BndStructMethod, (const Struct* struct_; ::std::string name; ) ), -// (BndTraitMethod, (const Trait* struct_; ::std::string name; ) ) +//TAGGED_UNION(PathBinding, Unbound, +// (Module, (const Module* module_; ) ), +// (Enum, (const Enum* enum_; ) ), +// (Struct, (const Struct* struct_; ) ), +// (Trait, (const Trait* trait_; ) ), +// (Static, (const Static* static_; ) ), +// (Function, (const Function* func_; ) ), +// (EnumVar, (const Enum* enum_; unsigned int idx; ) ), +// (TypeAlias, (const TypeAlias* alias_; ) ), +// (StructMethod, (const Struct* struct_; ::std::string name; ) ), +// (TraitMethod, (const Trait* struct_; ::std::string name; ) ) // ); class PathBinding { @@ -143,63 +144,64 @@ public: SERIALISABLE_PROTOTYPES(); }; -//TAGGED_ENUM(Class, Local, -// (Local, (::std:string name) ), -// (Variable, (::std:string name) ), -// (Relative, (::std::vector<PathNode> nodes) ), -// (Self, (::std::vector<PathNode> nodes) ), -// (Super, (::std::vector<PathNode> nodes) ), -// (Absolute, (::std::vector<PathNode> nodes) ), -// (UFCS, (TypeRef type; TypeRef trait; ::std::vector<PathNode> nodes) ), -// ); class Path: public ::Serialisable { public: - enum Class { - INVALID, // An empty path, usually invalid - ABSOLUTE, // root-relative path ("::path") - UFCS, // type-relative path ("<Type>::such") - VARIABLE, // Reference to a local variable - - RELATIVE, // Unadorned relative path (e.g. "path::to::item" or "generic_item::<>") - SELF, // module-relative path ("self::path") - SUPER, // parent-relative path ("super::path") - }; + TAGGED_UNION(Class, Invalid, + (Invalid, ()), + (Local, ( // Variable / Type param (resolved) + ::std::string name; + ) ), + (Relative, ( // General relative + ::std::vector<PathNode> nodes; + ) ), + (Self, ( // Module-relative + ::std::vector<PathNode> nodes; + ) ), + (Super, ( // Parent-relative + ::std::vector<PathNode> nodes; + ) ), + (Absolute, ( // Absolute + ::std::vector<PathNode> nodes; + ) ), + (UFCS, ( // Type-relative + ::std::unique_ptr<TypeRef> type; + ::std::unique_ptr<TypeRef> trait; + ::std::vector<PathNode> nodes; + ) ) + ); private: /// The crate defining the root of this path (used for path resolution) ::std::string m_crate; - /// Path class (absolute, relative, local) - /// - Absolute is "relative" to the crate root - /// - Relative doesn't have a set crate (and can't be resolved) - /// - Local is a special case to handle possible use of local varaibles - /// - UFCS is relative to a type +public: Class m_class; - ::std::vector<TypeRef> m_ufcs; - ::std::vector<PathNode> m_nodes; - + +private: PathBinding m_binding; public: // INVALID Path(): - m_class(INVALID) + m_class() {} + Path(Path&&) noexcept = default; + Path& operator=(AST::Path&&) = default; + + Path(const Path& x); // ABSOLUTE struct TagAbsolute {}; Path(TagAbsolute): - m_class(ABSOLUTE) + m_class( Class::make_Absolute({}) ) {} Path(::std::initializer_list<PathNode> l): - m_class(ABSOLUTE), - m_nodes(l) + Path("", l) {} Path(::std::string crate, ::std::vector<PathNode> nodes): m_crate( ::std::move(crate) ), - m_class(ABSOLUTE), - m_nodes( ::std::move(nodes) ) + m_class( Class::make_Absolute({nodes: mv$(nodes)}) ) {} // UFCS @@ -207,33 +209,28 @@ public: Path(TagUfcs, TypeRef type, TypeRef trait); // VARIABLE - struct TagVariable {}; - Path(TagVariable, ::std::string name): - m_class(VARIABLE), - m_nodes( {PathNode( ::std::move(name), {} )} ) + struct TagLocal {}; + Path(TagLocal, ::std::string name): + m_class( Class::make_Local({ mv$(name) }) ) + {} + Path(::std::string name): + m_class( Class::make_Local({name: mv$(name)}) ) {} // RELATIVE struct TagRelative {}; Path(TagRelative): - m_class(RELATIVE), - m_nodes({}) - {} - Path(::std::string name): - m_class(RELATIVE), - m_nodes( {PathNode( ::std::move(name), {} )} ) + m_class( Class::make_Relative({}) ) {} // SELF struct TagSelf {}; Path(TagSelf): - m_class(SELF), - m_nodes({}) + m_class( Class::make_Self({}) ) {} // SUPER struct TagSuper {}; Path(TagSuper): - m_class(SUPER), - m_nodes({}) + m_class( Class::make_Super({}) ) {} void set_crate(::std::string crate) { @@ -242,8 +239,10 @@ public: DEBUG("crate set to " << m_crate); } } - void set_local() { - assert(m_class == RELATIVE); + + + Class::Tag class_tag() const { + return m_class.tag(); } /// Add the all nodes except the first from 'b' to 'a' and return @@ -253,19 +252,21 @@ public: return ret; } /// Grab the args from the first node of b, and add the rest to the end of the path + // TODO: Args should probably be moved to the path, not the nodes void add_tailing(const Path& b) { - assert(this->m_class != INVALID); - assert(b.m_class != INVALID); - if( b.m_nodes.size() == 0 ) + assert( !this->m_class.is_Invalid() ); + assert( b.m_class.is_Relative() ); + const auto& b_r = b.m_class.as_Relative(); + if( b_r.nodes.size() == 0 ) ; - else if( m_nodes.size() > 0 ) - m_nodes.back().args() = b[0].args(); + else if( nodes().size() > 0 ) + nodes().back().args() = b[0].args(); else if( b[0].args().size() > 0 ) throw ::std::runtime_error("add_tail to empty path, but generics in source"); else ; - for(unsigned int i = 1; i < b.m_nodes.size(); i ++) - m_nodes.push_back(b.m_nodes[i]); + for(unsigned int i = 1; i < b_r.nodes.size(); i ++) + nodes().push_back(b_r.nodes[i]); m_binding = PathBinding(); } Path operator+(PathNode&& pn) const { @@ -284,9 +285,9 @@ public: Path& operator+=(const Path& x); void append(PathNode node) { - assert(this->m_class != INVALID); - assert(this->m_class != VARIABLE); - m_nodes.push_back(node); + if( m_class.is_Invalid() ) + m_class = Class::make_Relative({}); + nodes().push_back(node); m_binding = PathBinding(); } @@ -305,30 +306,44 @@ public: void match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const; bool is_trivial() const { - switch(m_class) + switch(m_class.tag()) { - case RELATIVE: return m_nodes.size() == 1 && m_nodes[0].args().size() == 0; + case Class::Local: return true; + case Class::Relative: { + auto& e = m_class.as_Relative(); + return e.nodes.size() == 1 && e.nodes[0].args().size() == 0; + } default: return false; } } - bool is_valid() const { return *this != Path(); } - Class type() const { return m_class; } - bool is_absolute() const { return m_class == ABSOLUTE; } - bool is_relative() const { return m_class == RELATIVE; } - size_t size() const { return m_nodes.size(); } + bool is_valid() const { return !m_class.is_Invalid(); } + bool is_absolute() const { return m_class.is_Absolute(); } + bool is_relative() const { return m_class.is_Relative() || m_class.is_Super() || m_class.is_Self(); } + size_t size() const { return nodes().size(); } bool is_concrete() const; const PathBinding& binding() const { return m_binding; } - ::std::vector<TypeRef>& ufcs() { return m_ufcs; } - - ::std::vector<PathNode>& nodes() { return m_nodes; } - const ::std::vector<PathNode>& nodes() const { return m_nodes; } + ::std::vector<PathNode>& nodes() { + TU_MATCH(Class, (m_class), (ent), + (Invalid, assert(!m_class.is_Invalid()); throw ::std::runtime_error("Path::nodes() on Invalid"); ), + (Local, assert(!m_class.is_Local()); throw ::std::runtime_error("Path::nodes() on Local"); ), + (Relative, return ent.nodes;), + (Self, return ent.nodes;), + (Super, return ent.nodes;), + (Absolute, return ent.nodes;), + (UFCS, return ent.nodes;) + ) + throw ::std::runtime_error("Path::nodes() fell off"); + } + const ::std::vector<PathNode>& nodes() const { + return ((Path*)this)->nodes(); + } - PathNode& operator[](int idx) { if(idx>=0) return m_nodes[idx]; else return m_nodes[size()+idx]; } - const PathNode& operator[](int idx) const { if(idx>=0) return m_nodes[idx]; else return m_nodes[size()+idx]; } + PathNode& operator[](int idx) { if(idx>=0) return nodes()[idx]; else return nodes()[size()+idx]; } + const PathNode& operator[](int idx) const { return (*(Path*)this)[idx]; } /// Returns 0 if paths are identical, 1 if TypeRef::TagArg is present in one, and -1 if a node differs int equal_no_generic(const Path& x) const; @@ -344,6 +359,10 @@ public: friend ::Serialiser& operator<<(Serialiser& s, Path::Class pc); friend void operator>>(Deserialiser& s, Path::Class& pc); private: + static void resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn); + static void match_args_nl(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b, ::std::function<void(const char*,const TypeRef&)> fcn); + static int node_lists_equal_no_generic(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b); + void check_param_counts(const TypeParams& params, bool expect_params, PathNode& node); void bind_module(const Module& mod); void bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args); diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 0891a748..901a3acb 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -394,28 +394,53 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) TRACE_FUNCTION_F("path = " << path << ", m_module_path = " << m_module_path);
handle_path_int(path, mode);
-
+
// Handle generic components of the path
// - Done AFTER resoltion, as binding might introduce defaults (which may not have been resolved)
- for( auto& ent : path.nodes() )
- {
- for( auto& arg : ent.args() )
- {
- handle_type(arg);
- }
- }
+ TU_MATCH(AST::Path::Class, (path.m_class), (info),
+ (Invalid),
+ (Local),
+ (Relative,
+ for( auto& ent : info.nodes )
+ for( auto& arg : ent.args() )
+ handle_type(arg);
+ ),
+ (Self,
+ for( auto& ent : info.nodes )
+ for( auto& arg : ent.args() )
+ handle_type(arg);
+ ),
+ (Super,
+ for( auto& ent : info.nodes )
+ for( auto& arg : ent.args() )
+ handle_type(arg);
+ ),
+ (Absolute,
+ for( auto& ent : info.nodes )
+ for( auto& arg : ent.args() )
+ handle_type(arg);
+ ),
+ (UFCS,
+ handle_type(*info.type);
+ handle_type(*info.trait);
+ for( auto& ent : info.nodes )
+ for( auto& arg : ent.args() )
+ handle_type(arg);
+ )
+ )
}
void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode)
{
// Convert to absolute
// - This means converting all partial forms (i.e. not UFCS, Variable, or Absolute)
- switch( path.type() )
+ switch( path.class_tag() )
{
- case AST::Path::INVALID:
+ case AST::Path::Class::Invalid:
+ assert( !path.m_class.is_Invalid() );
return;
// --- Already absolute forms
// > Absolute: Resolve
- case AST::Path::ABSOLUTE:
+ case AST::Path::Class::Absolute:
DEBUG("Absolute - binding");
INDENT();
// Already absolute, our job is done
@@ -429,20 +454,26 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode UNINDENT();
break;
// > UFCS: Expand the types
- case AST::Path::UFCS:
+ case AST::Path::Class::UFCS:
handle_path_ufcs(path, mode);
break;
// > Variable: (wait, how is this known already?)
// - 'self'
- case AST::Path::VARIABLE:
+ case AST::Path::Class::Local:
+ //if(
+ // 1. Check for local items
+ // 2. Type parameters (ONLY when in expression mode)
+ // 3. Module items
+ //throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int");
break;
- case AST::Path::RELATIVE:
+ case AST::Path::Class::Relative:
// 1. function scopes (variables and local items)
// > Return values: name or path
{
bool allow_variables = (mode == CASTIterator::MODE_EXPR && path.is_trivial());
if( this->find_local_item(path, allow_variables) ) {
+ //path.resolve(m_crate);
break ;
}
else {
@@ -463,16 +494,16 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode // Repalce with UFCS
auto newpath = AST::Path(AST::Path::TagUfcs(), TypeRef(TypeRef::TagArg(), path[0].name()), TypeRef());
newpath.add_tailing(path);
- path = newpath;
+ path = mv$(newpath);
}
else {
- // Replace with VARIABLE (not strictly speaking true... but close enough)
+ // Mark as local
+ // - TODO: Also need to annotate
// - TODO: Not being trivial is an error, not a bug
assert( path.is_trivial() );
- path = AST::Path(AST::Path::TagVariable(), path[0].name());
+ path = AST::Path(AST::Path::TagLocal(), path[0].name());
}
break;
- throw ParseError::Todo("Handle type param in RELATIVE");
}
}
@@ -492,7 +523,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode return ;
// Module relative
- case AST::Path::SELF:{
+ case AST::Path::Class::Self:{
if( this->find_mod_item(path) ) {
break;
}
@@ -503,7 +534,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed");
break; }
// Parent module relative
- case AST::Path::SUPER:{
+ case AST::Path::Class::Super:{
if( this->find_super_mod_item(path) ) {
break;
}
@@ -514,15 +545,18 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed");
break; }
}
+
+ // TODO: Are there any reasons not to be bound at this point?
+ //assert( path.binding().is_bound() );
}
void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mode)
{
- assert( path.type() == AST::Path::UFCS );
+ auto& info = path.m_class.as_UFCS();
// 1. Handle sub-types
- handle_type(path.ufcs().at(0));
- handle_type(path.ufcs().at(1));
+ handle_type(*info.type);
+ handle_type(*info.trait);
// 2. Handle wildcard traits (locate in inherent impl, or from an in-scope trait)
- if( path.ufcs().at(1).is_wildcard() )
+ if( info.trait->is_wildcard() )
{
DEBUG("Searching for impls when trait is _");
@@ -531,12 +565,12 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod // 1. Inherent
AST::Impl* impl_ptr;
::std::vector<TypeRef> params;
- if( m_crate.find_impl(AST::Path(), path.ufcs().at(0), &impl_ptr, ¶ms) )
+ if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, ¶ms) )
{
DEBUG("Found matching inherent impl");
// - Mark as being from the inherent, and move along
// > TODO: What about if this item is actually from a trait (due to genric restrictions)
- path.ufcs().at(1) = TypeRef(TypeRef::TagInvalid());
+ *info.trait = TypeRef(TypeRef::TagInvalid());
}
else
{
@@ -561,7 +595,7 @@ bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) { for( auto it2 = s.locals.rbegin(); it2 != s.locals.rend(); ++it2 )
{
if( *it2 == path[0].name() ) {
- path = AST::Path(AST::Path::TagVariable(), path[0].name());
+ path = AST::Path(AST::Path::TagLocal(), path[0].name());
return true;
}
}
@@ -694,7 +728,8 @@ void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) ::std::string name = pat.binding();
// Locate a _constant_ within the current namespace which matches this name
// - Variables don't count
- AST::Path newpath = AST::Path(name);
+ AST::Path newpath = AST::Path(AST::Path::TagRelative());
+ newpath.append(name);
handle_path(newpath, CASTIterator::MODE_BIND);
if( newpath.is_relative() )
{
@@ -719,8 +754,8 @@ void CPathResolver::handle_module(AST::Path path, AST::Module& mod) {
// NOTE: Assigning here is safe, as the CASTIterator handle_module iterates submodules as the last action
m_module = &mod;
- m_module_path = path;
- CASTIterator::handle_module(path, mod);
+ m_module_path = AST::Path(path);
+ CASTIterator::handle_module(mv$(path), mod);
}
void CPathResolver::handle_function(AST::Path path, AST::Function& fcn)
{
@@ -737,14 +772,14 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod {
AST::Path& p = imp.data;
DEBUG("p = " << p);
- switch( p.type() )
+ switch( p.class_tag() )
{
- case AST::Path::ABSOLUTE:
+ case AST::Path::Class::Absolute:
// - No action
break;
// 'super' - Add parent path
// - TODO: Handle nested modules correctly.
- case AST::Path::SUPER: {
+ case AST::Path::Class::Super: {
if( modpath.size() < 1 )
throw ParseError::Generic("Encountered 'super' at crate root");
auto newpath = modpath;
@@ -755,15 +790,17 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod break; }
// 'self' - Add parent path
// - TODO: Handle nested modules correctly.
- case AST::Path::SELF: {
+ case AST::Path::Class::Self: {
auto newpath = modpath + p;
// TODO: Undo anon modules until item is found
DEBUG("Absolutised path " << p << " into " << newpath);
p = ::std::move(newpath);
break; }
// Any other class is an error
+ case AST::Path::Class::Relative:
+ throw ParseError::Generic( FMT("Encountered relative path in 'use': " << p) );
default:
- throw ParseError::Generic( FMT("Invalid path type encounted in 'use' : " << p) );
+ throw ParseError::Generic( FMT("Invalid path type encounted in 'use' : " << p.class_tag() << " " << p) );
}
// Run resolution on import
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index 64e7f84a..24152b5e 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -13,6 +13,7 @@ #define TU_CASE(mod, class, var, name,src, ...) TU_CASE_BODY(mod,class,var, TU_CASE_ITEM(src,mod,var,name) __VA_ARGS__) #define TU_CASE2(mod, class, var, n1,s1, n2,s2, ...) TU_CASE_BODY(mod,class,var, TU_CASE_ITEM(s1,mod,var,n1) TU_CASE_ITEM(s2,mod,var,n2) __VA_ARGS__) + #define TU_DATANAME(name) Data_##name // Internals of TU_CONS #define TU_CONS_I(__tag, __type) \ @@ -31,6 +32,8 @@ // Define a tagged union constructor #define TU_CONS(name, _) TU_CONS_I(name, TU_DATANAME(name)) +#define TU_FIRST(a, ...) a + // Argument iteration #define _DISP2(n, _1, _2) n _1 n _2 #define _DISP3(n, v, v2, v3) n v n v2 n v3 // _DISP2(n, __VA_ARGS__) @@ -39,18 +42,32 @@ #define _DISP6(n, v, ...) n v _DISP5(n, __VA_ARGS__) #define _DISP7(n, v, ...) n v _DISP6(n, __VA_ARGS__) #define _DISP8(n, v, ...) n v _DISP7(n, __VA_ARGS__) -#define _DISP9(n, v, ...) n v _DISP8(n, __VA_ARGS__) -#define _DISP10(n, v, ...) n v _DISP9(n, __VA_ARGS__) -#define _DISP11(n, v, ...) n v _DISP10(n, __VA_ARGS__) +#define _DISP9(n, a1,a2,a3,a4, b1,b2,b3,b4, c1) _DISP4(n, a1,a2,a3,a4) _DISP3(n, b1,b2,b3) _DISP2(n, b4,c1) //n v _DISP8(n, __VA_ARGS__) +#define _DISP10(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP2(n, c1,c2) //n v _DISP9(n, __VA_ARGS__) +#define _DISP11(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP2(n, c1,c2,c3) //n v _DISP10(n, __VA_ARGS__) #define _DISP12(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3,c4) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP4(n, c1,c2,c3,c4) //n v _DISP11(n, __VA_ARGS__) +#define TU_DISPA(n, a) n a +#define TU_DISPA2(n, a, _1, _2) TU_DISPA(n, (TU_EXP a, TU_EXP _1))/* +*/ TU_DISPA(n, (TU_EXP a, TU_EXP _2)) +#define TU_DISPA3(n, a, _1, _2, _3) \ + TU_DISPA(n, (TU_EXP a, TU_EXP _1))/* +*/ TU_DISPA(n, (TU_EXP a, TU_EXP _2))/* +*/ TU_DISPA(n, (TU_EXP a, TU_EXP _3)) +#define TU_DISPA4(n, a, a1,a2, b1,b2) TU_DISPA2(n,a, a1,a2) TU_DISPA2(n,a, b1,b2) +#define TU_DISPA5(n, a, a1,a2,a3, b1,b2) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA2(n,a, b1,b2) +#define TU_DISPA6(n, a, a1,a2,a3, b1,b2,b3) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) +#define TU_DISPA7(n, a, a1,a2,a3, b1,b2, c1,c2) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA2(n,a, b1,b2) TU_DISPA2(n,a, c1,c2) +#define TU_DISPA8(n, a, a1,a2,a3, b1,b2,b3, c1,c2) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA2(n,a, c1,c2) +#define TU_DISPA9(n, a, a1,a2,a3, b1,b2,b3, c1,c2,c3) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA3(n,a, c1,c2,c3) + // Macro to obtain a numbered macro for argument counts // - Raw variant #define TU_GM_I(SUF,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,COUNT,...) SUF##COUNT -#define TU_GM(SUF,...) TU_GM_I(SUF,__VA_ARGS__,12,11,10,9,8,7,6,5,4,3,2,x) +#define TU_GM(SUF,...) TU_GM_I(SUF,__VA_ARGS__,12,11,10,9,8,7,6,5,4,3,2,1) // - _DISP based variant (for iteration) #define TU_GMX(...) TU_GM(_DISP,__VA_ARGS__) - +#define TU_GMA(...) TU_GM(TU_DISPA,__VA_ARGS__) // Sizes of structures #define TU_SO(name, _) sizeof(TU_DATANAME(name)) @@ -67,6 +84,20 @@ #define MAXS11(a, b, c, d, e, f, g, h, i, j, k) MAX2(MAXS6(a, b, c, d, e, f), MAXS5(g, h, i, j, k)) #define MAXS12(a, b, c, d, e, f, g, h, i, j, k, l) MAX2(MAXS6(a, b, c, d, e, f), MAXS6(g, h, i, j, k, l)) +// "match"-like statement +// TU_MATCH(Class, m_data, ent, (Variant, CODE), (Variant2, CODE)) +#define TU_MATCH(CLASS, VAR, NAME, ...) switch( TU_FIRST VAR.tag()) {/* +*/ TU_MATCH_ARMS(CLASS, VAR, NAME, __VA_ARGS__)/* +*/} +#define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ auto& NAME = VAR.as_##TAG(); (void)&NAME; +#define TU_MATCH_BIND2_(TAG, v1,v2, n1,n2) TU_MATCH_BIND1(TAG, v1, n1) TU_MATCH_BIND1(TAG, v2, n2) +#define TU_MATCH_BIND2(...) TU_MATCH_BIND2_(__VA_ARGS__) +#define TU_MATCH_ARM(CLASS, VAR, NAME, TAG, ...) case CLASS::TAG: {/* +*/ TU_GM(TU_MATCH_BIND, TU_EXP VAR)(TAG, TU_EXP VAR , TU_EXP NAME)/* +*/ __VA_ARGS__/* +*/} break; +#define TU_MATCH_ARMS(CLASS, VAR, NAME, ...) TU_GMA(__VA_ARGS__)(TU_MATCH_ARM, (CLASS, VAR, NAME), __VA_ARGS__) + // Type definitions #define TU_EXP(...) __VA_ARGS__ #define TU_TYPEDEF(name, content) struct TU_DATANAME(name) { TU_EXP content; };/* @@ -125,7 +156,7 @@ class _name { \ */ public:\ _name(): m_tag(_def) {}\ _name(const _name&) = delete; \ - _name(_name&& x): m_tag(x.m_tag) { x.m_tag = _def; switch(m_tag) { TU_MOVE_CASES(__VA_ARGS__) } } \ + _name(_name&& x) noexcept: m_tag(x.m_tag) { x.m_tag = _def; switch(m_tag) { TU_MOVE_CASES(__VA_ARGS__) } } \ _name& operator =(_name&& x) { this->~_name(); m_tag = x.m_tag; x.m_tag = _def; switch(m_tag) { TU_MOVE_CASES(__VA_ARGS__) }; return *this; } \ ~_name() { switch(m_tag) { TU_DEST_CASES(__VA_ARGS__) } } \ \ diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 15e983f7..eb53ac98 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -1001,7 +1001,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) case TOK_RWORD_SELF:
{
if( LOOK_AHEAD(lex) != TOK_DOUBLE_COLON ) {
- return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagVariable(), "self") );
+ return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") );
}
else
{
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index e3b290d0..43346172 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -41,9 +41,9 @@ AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode) } AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode) { + Token tok; if( is_abs ) { - Token tok; if( GET_TOK(tok, lex) == TOK_STRING ) { ::std::string cratename = tok.str(); GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); @@ -54,8 +54,16 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi return Parse_PathFrom(lex, AST::Path(AST::Path::TagAbsolute()), generic_mode); } } - else - return Parse_PathFrom(lex, AST::Path(AST::Path::TagRelative()), generic_mode); + else { + //assert( GET_TOK(tok, lex) == TOK_IDENT ); + //if( lex.lookahead(0) != TOK_DOUBLE_COLON ) { + // return AST::Path( tok.str() ); + //} + //else { + // lex.putback(tok); + return Parse_PathFrom(lex, AST::Path(AST::Path::TagRelative()), generic_mode); + //} + } } AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode generic_mode) @@ -145,9 +153,9 @@ AST::Path Parse_PathFrom(TokenStream& lex, AST::Path path, eParsePathGenericMode path.append( AST::PathNode(component, params) ); } lex.putback(tok); - if( path.is_trivial() ) { - path = AST::Path(path[0].name()); - } + //if( path.is_trivial() ) { + // path = AST::Path(path[0].name()); + //} DEBUG("path = " << path); return path; } diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 1fd62741..369cc95a 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -725,7 +725,7 @@ void Parse_Impl(TokenStream& lex, AST::Module& mod, bool is_unsafe/*=false*/) {
if( !impl_type.is_path() )
throw ParseError::Generic(lex, "Trait was not a path");
- trait_path = impl_type.path();
+ trait_path = mv$(impl_type.path());
// Implementing a trait for another type, get the target type
if( GET_TOK(tok, lex) == TOK_DOUBLE_DOT )
{
@@ -885,9 +885,9 @@ void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi) }
}
-void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function<void(AST::Path, ::std::string)> fcn)
+void Parse_Use_Wildcard(AST::Path base_path, ::std::function<void(AST::Path, ::std::string)> fcn)
{
- fcn(base_path, ""); // HACK! Empty path indicates wilcard import
+ fcn( mv$(base_path), ""); // HACK! Empty path indicates wilcard import
}
void Parse_Use_Set(TokenStream& lex, const AST::Path& base_path, ::std::function<void(AST::Path, ::std::string)> fcn)
{
@@ -911,7 +911,8 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> TRACE_FUNCTION;
Token tok;
- AST::Path path = AST::Path( AST::Path::TagAbsolute() );
+ AST::Path path = AST::Path(AST::Path::TagAbsolute());
+ ::std::vector<AST::PathNode> nodes;
switch( GET_TOK(tok, lex) )
{
@@ -945,7 +946,6 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> default:
throw ParseError::Unexpected(lex, tok);
}
- // TODO: Use from crate root
while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
{
if( GET_TOK(tok, lex) == TOK_IDENT )
@@ -961,7 +961,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
break ;
case TOK_STAR:
- Parse_Use_Wildcard(path, fcn);
+ Parse_Use_Wildcard( mv$(path), fcn );
break ;
default:
throw ParseError::Unexpected(lex, tok);
@@ -1309,7 +1309,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, case TOK_RWORD_USE:
Parse_Use(lex, [&mod,is_public,&path](AST::Path p, std::string s) {
DEBUG(path << " - use " << p << " as '" << s << "'");
- mod.add_alias(is_public, p, s);
+ mod.add_alias(is_public, mv$(p), s);
});
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break;
@@ -1614,7 +1614,7 @@ void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList< {
// Import the prelude
AST::Path prelude_path = AST::Path( "std", { AST::PathNode("prelude", {}), AST::PathNode("v1", {}) } );
- Parse_Use_Wildcard(prelude_path,
+ Parse_Use_Wildcard( mv$(prelude_path),
[&mod](AST::Path p, std::string s) {
mod.add_alias(false, p, s);
}
diff --git a/src/synexts/lang_item.cpp b/src/synexts/lang_item.cpp index 9f1838c5..9e3f0aa9 100644 --- a/src/synexts/lang_item.cpp +++ b/src/synexts/lang_item.cpp @@ -13,7 +13,7 @@ void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type) { if(name == "phantom_fn") { - crate.m_lang_item_PhantomFn = path; + crate.m_lang_item_PhantomFn = AST::Path(path); crate.m_lang_item_PhantomFn.nodes().back().args() = { TypeRef("A"), TypeRef("B") }; } else if( name == "send" ) { |