summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rw-r--r--src/ast/ast.hpp8
-rw-r--r--src/ast/path.cpp407
-rw-r--r--src/ast/path.hpp185
-rw-r--r--src/convert/resolve.cpp107
-rw-r--r--src/include/tagged_union.hpp43
-rw-r--r--src/parse/expr.cpp2
-rw-r--r--src/parse/paths.cpp20
-rw-r--r--src/parse/root.cpp16
-rw-r--r--src/synexts/lang_item.cpp2
10 files changed, 496 insertions, 301 deletions
diff --git a/Makefile b/Makefile
index dc8110d7..f720ae48 100644
--- a/Makefile
+++ b/Makefile
@@ -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, &params) )
+ if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, &params) )
{
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" ) {