summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp130
-rw-r--r--src/ast/pattern.hpp62
-rw-r--r--src/convert/ast_iterate.cpp70
-rw-r--r--src/convert/resolve.cpp2
-rw-r--r--src/dump_as_rust.cpp61
-rw-r--r--src/include/tagged_enum.hpp51
-rw-r--r--src/parse/expr.cpp4
7 files changed, 244 insertions, 136 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 48517095..37cb17b6 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -40,62 +40,110 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", {
::std::ostream& operator<<(::std::ostream& os, const Pattern& pat)
{
- switch(pat.m_class)
+ os << "Pattern(" << pat.m_binding << " @ ";
+ switch(pat.m_data.tag())
{
- case Pattern::ANY:
- os << "Pattern(TagWildcard, '" << pat.m_binding << "' @ _)";
+ case Pattern::Data::Any:
+ os << "_";
break;
- case Pattern::MAYBE_BIND:
- os << "Pattern(TagMaybeBind, '" << pat.m_binding << "')";
+ case Pattern::Data::MaybeBind:
+ os << "?";
break;
- case Pattern::REF:
- os << "Pattern(TagReference, '" << pat.m_binding << "' @ " << pat.m_sub_patterns[0] << ")";
+ case Pattern::Data::Ref:
+ os << "&" << (pat.m_data.as_Ref().mut ? "mut " : "") << *pat.m_data.as_Ref().sub;
break;
- case Pattern::VALUE:
- os << "Pattern(TagValue, '" << pat.m_binding << "' @ TODO:ExprNode)";
+ case Pattern::Data::Value:
+ os << *pat.m_data.as_Value().start;
+ if( pat.m_data.as_Value().end.get() )
+ os << " ... " << *pat.m_data.as_Value().end;
break;
- case Pattern::TUPLE:
- os << "Pattern(TagTuple, '" << pat.m_binding << "' @ [" << pat.m_sub_patterns << "])";
+ case Pattern::Data::Tuple:
+ os << "(" << pat.m_data.as_Tuple().sub_patterns << ")";
break;
- case Pattern::TUPLE_STRUCT:
- os << "Pattern(TagEnumVariant, '" << pat.m_binding << "' @ " << pat.m_path << ", [" << pat.m_sub_patterns << "])";
+ case Pattern::Data::StructTuple:
+ os << pat.m_data.as_StructTuple().path << " (" << pat.m_data.as_StructTuple().sub_patterns << ")";
+ break;
+ case Pattern::Data::Struct:
+ os << pat.m_data.as_Struct().path << " {" << pat.m_data.as_Struct().sub_patterns << "}";
break;
}
+ os << ")";
return os;
}
-void operator%(Serialiser& s, Pattern::BindType c) {
- switch(c)
- {
- #define _(v) case Pattern::v: s << #v; return;
- _(ANY)
- _(MAYBE_BIND)
- _(REF)
- _(VALUE)
- _(TUPLE)
- _(TUPLE_STRUCT)
- #undef _
- }
+void operator%(Serialiser& s, Pattern::Data::Tag c) {
+ s << Pattern::Data::tag_to_str(c);
}
-void operator%(::Deserialiser& s, Pattern::BindType& c) {
+void operator%(::Deserialiser& s, Pattern::Data::Tag& c) {
::std::string n;
s.item(n);
- if(1) ;
- #define _(v) else if(n == #v) c = Pattern::v;
- _(ANY)
- _(MAYBE_BIND)
- _(REF)
- _(VALUE)
- _(TUPLE)
- _(TUPLE_STRUCT)
- #undef _
- else
- throw ::std::runtime_error("");
+ c = Pattern::Data::tag_from_str(n);
}
-SERIALISE_TYPE_S(Pattern, {
- s % m_class;
+SERIALISE_TYPE(Pattern::, "Pattern", {
+ s.item(m_binding);
+ s % m_data.tag();
+ switch(m_data.tag())
+ {
+ case Pattern::Data::Any:
+ break;
+ case Pattern::Data::MaybeBind:
+ break;
+ case Pattern::Data::Ref:
+ s << m_data.as_Ref().mut;
+ s << m_data.as_Ref().sub;
+ break;
+ case Pattern::Data::Value:
+ s << m_data.as_Value().start;
+ s << m_data.as_Value().end;
+ break;
+ case Pattern::Data::Tuple:
+ s << m_data.as_Tuple().sub_patterns;
+ break;
+ case Pattern::Data::StructTuple:
+ s << m_data.as_StructTuple().path;
+ s << m_data.as_StructTuple().sub_patterns;
+ break;
+ case Pattern::Data::Struct:
+ s << m_data.as_Struct().path;
+ s << m_data.as_Struct().sub_patterns;
+ break;
+ }
+},{
s.item(m_binding);
- s.item(m_sub_patterns);
- s.item(m_path);
+ Pattern::Data::Tag tag;
+ s % tag;
+ switch(tag)
+ {
+ case Pattern::Data::Any:
+ m_data = Pattern::Data::make_null_Any();
+ break;
+ case Pattern::Data::MaybeBind:
+ m_data = Pattern::Data::make_null_MaybeBind();
+ break;
+ case Pattern::Data::Ref:
+ m_data = Pattern::Data::make_null_Ref();
+ s.item( m_data.as_Ref().mut );
+ s.item( m_data.as_Ref().sub );
+ break;
+ case Pattern::Data::Value:
+ m_data = Pattern::Data::make_null_Value();
+ s.item( m_data.as_Value().start );
+ s.item( m_data.as_Value().end );
+ break;
+ case Pattern::Data::Tuple:
+ m_data = Pattern::Data::make_null_Tuple();
+ s.item( m_data.as_Tuple().sub_patterns );
+ break;
+ case Pattern::Data::StructTuple:
+ m_data = Pattern::Data::make_null_StructTuple();
+ s.item( m_data.as_StructTuple().path );
+ s.item( m_data.as_StructTuple().sub_patterns );
+ break;
+ case Pattern::Data::Struct:
+ m_data = Pattern::Data::make_null_Struct();
+ s.item( m_data.as_Struct().path );
+ s.item( m_data.as_Struct().sub_patterns );
+ break;
+ }
});
Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index fde31201..355b5c2a 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -18,80 +18,62 @@ class Pattern:
public Serialisable
{
public:
- enum BindType {
- MAYBE_BIND,
- ANY,
- REF,
- VALUE,
- TUPLE,
- TUPLE_STRUCT,
- };
-private:
- BindType m_class;
- ::std::string m_binding;
- Path m_path;
- ::std::vector<Pattern> m_sub_patterns;
-
TAGGED_ENUM(Data, Any,
(Any, () ),
(MaybeBind, () ),
- (Ref, (bool mut; unique_ptr<ExprNode> sub;) ),
+ (Ref, (bool mut; unique_ptr<Pattern> sub;) ),
(Value, (unique_ptr<ExprNode> start; unique_ptr<ExprNode> end;) ),
(Tuple, (::std::vector<Pattern> sub_patterns;) ),
(StructTuple, (Path path; ::std::vector<Pattern> sub_patterns;) ),
(Struct, (Path path; ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns;) )
- ) m_data;
+ );
+private:
+ ::std::string m_binding;
+ Data m_data;
public:
- Pattern():
- m_class(ANY)
+ Pattern()
{}
// Wildcard = '..', distinct from '_'
// TODO: Store wildcard as a different pattern type
struct TagWildcard {};
- Pattern(TagWildcard):
- m_class(ANY)
+ Pattern(TagWildcard)
{}
struct TagBind {};
Pattern(TagBind, ::std::string name):
- m_class(ANY),
m_binding(name)
{}
struct TagMaybeBind {};
Pattern(TagMaybeBind, ::std::string name):
- m_class(MAYBE_BIND),
- m_binding(name)
+ m_binding(name),
+ m_data( Data::make_MaybeBind({}) )
{}
struct TagValue {};
Pattern(TagValue, unique_ptr<ExprNode> node, unique_ptr<ExprNode> node2 = 0):
- m_class(VALUE),
m_data( Data::make_Value({ ::std::move(node), ::std::move(node2) }) )
{}
struct TagReference {};
Pattern(TagReference, Pattern sub_pattern):
- m_class(REF),
- m_sub_patterns()
+ m_data( Data::make_Ref( /*Data::Data_Ref */ {
+ false, unique_ptr<Pattern>(new Pattern(::std::move(sub_pattern)))
+ }) )
{
- m_sub_patterns.push_back( ::std::move(sub_pattern) );
}
struct TagTuple {};
Pattern(TagTuple, ::std::vector<Pattern> sub_patterns):
- m_class(TUPLE),
- m_sub_patterns( ::std::move(sub_patterns) )
+ m_data( Data::make_Tuple( { ::std::move(sub_patterns) } ) )
{}
struct TagEnumVariant {};
Pattern(TagEnumVariant, Path path, ::std::vector<Pattern> sub_patterns):
- m_class(TUPLE_STRUCT),
- m_path( ::std::move(path) ),
- m_sub_patterns( ::std::move(sub_patterns) )
+ m_data( Data::make_StructTuple( { ::std::move(path), ::std::move(sub_patterns) } ) )
{}
// Mutators
@@ -100,29 +82,31 @@ public:
}
::std::unique_ptr<ExprNode> take_node() {
- assert(m_class == VALUE);
- m_class = ANY;
assert(m_data.is_Value());
return ::std::move(m_data.unwrap_Value().start);
}
// Accessors
const ::std::string& binding() const { return m_binding; }
- BindType type() const { return m_class; }
+ Data& data() { return m_data; }
+ const Data& data() const { return m_data; }
ExprNode& node() {
return *m_data.as_Value().start;
}
const ExprNode& node() const {
return *m_data.as_Value().start;
}
- Path& path() { return m_path; }
- const Path& path() const { return m_path; }
- ::std::vector<Pattern>& sub_patterns() { return m_sub_patterns; }
- const ::std::vector<Pattern>& sub_patterns() const { return m_sub_patterns; }
+ Path& path() { return m_data.as_StructTuple().path; }
+ const Path& path() const { return m_data.as_StructTuple().path; }
friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat);
SERIALISABLE_PROTOTYPES();
+ static ::std::unique_ptr<Pattern> from_deserialiser(Deserialiser& s) {
+ ::std::unique_ptr<Pattern> ret(new Pattern);
+ s.item(*ret);
+ return ::std::move(ret);
+ }
};
};
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp
index e53e1ba8..02914c49 100644
--- a/src/convert/ast_iterate.cpp
+++ b/src/convert/ast_iterate.cpp
@@ -62,29 +62,34 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
{
//DEBUG("pat = " << pat);
// Resolve names
- switch(pat.type())
+ switch(pat.data().tag())
{
- case AST::Pattern::ANY:
+ case AST::Pattern::Data::Any:
// Wildcard, nothing to do
break;
- case AST::Pattern::REF:
+ case AST::Pattern::Data::Ref: {
+ auto& v = pat.data().as_Ref();
if( type_hint.is_wildcard() )
- handle_pattern(pat.sub_patterns()[0], (const TypeRef&)TypeRef());
+ handle_pattern(*v.sub, (const TypeRef&)TypeRef());
else if( type_hint.is_reference() )
throw ::std::runtime_error("Ref pattern on non-ref value");
else
- handle_pattern(pat.sub_patterns()[0], type_hint.sub_types()[0]);
- break;
- case AST::Pattern::MAYBE_BIND:
+ handle_pattern(*v.sub, type_hint.sub_types()[0]);
+ break; }
+ case AST::Pattern::Data::MaybeBind:
throw ::std::runtime_error("Calling CASTIterator::handle_pattern on MAYBE_BIND, not valid");
- case AST::Pattern::VALUE:
- handle_expr( pat.node() );
- break;
- case AST::Pattern::TUPLE:
+ case AST::Pattern::Data::Value: {
+ auto& v = pat.data().as_Value();
+ handle_expr( *v.start );
+ if( v.end.get() )
+ handle_expr( *v.end );
+ break; }
+ case AST::Pattern::Data::Tuple: {
+ auto& v = pat.data().as_Tuple();
// Tuple is handled by subpattern code
if( type_hint.is_wildcard() )
{
- for( auto& sp : pat.sub_patterns() )
+ for( auto& sp : v.sub_patterns )
handle_pattern(sp, (const TypeRef&)TypeRef());
}
else if( !type_hint.is_tuple() )
@@ -93,24 +98,41 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
}
else
{
- if( type_hint.sub_types().size() != pat.sub_patterns().size() )
+ if( type_hint.sub_types().size() != v.sub_patterns.size() )
{
throw ::std::runtime_error("Tuple pattern count doesn't match");
}
- for( unsigned int i = 0; i < pat.sub_patterns().size(); i ++ )
+ for( unsigned int i = 0; i < v.sub_patterns.size(); i ++ )
{
- handle_pattern(pat.sub_patterns()[i], type_hint.sub_types()[i]);
+ handle_pattern(v.sub_patterns[i], type_hint.sub_types()[i]);
}
}
- break;
- case AST::Pattern::TUPLE_STRUCT:
+ break; }
+ case AST::Pattern::Data::Struct: {
+ auto& v = pat.data().as_Struct();
+ handle_path( v.path, CASTIterator::MODE_TYPE );
+ if( type_hint.is_wildcard() )
+ {
+ for( auto& sp : v.sub_patterns )
+ handle_pattern(sp.second, (const TypeRef&)TypeRef());
+ }
+ else if( !type_hint.is_path() )
+ {
+ throw ::std::runtime_error("Tuple struct pattern on non-tuple value");
+ }
+ else
+ {
+ throw ::std::runtime_error("TODO: Struct typecheck/iterate");
+ }
+ break; }
+ case AST::Pattern::Data::StructTuple: {
+ auto& v = pat.data().as_StructTuple();
// Resolve the path!
- // - TODO: Restrict to types and enum variants
- handle_path( pat.path(), CASTIterator::MODE_TYPE );
+ handle_path( v.path, CASTIterator::MODE_TYPE );
// Handle sub-patterns
if( type_hint.is_wildcard() )
{
- for( auto& sp : pat.sub_patterns() )
+ for( auto& sp : v.sub_patterns )
handle_pattern(sp, (const TypeRef&)TypeRef());
}
else if( !type_hint.is_path() )
@@ -120,8 +142,8 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
else
{
auto& hint_path = type_hint.path();
- auto& pat_path = pat.path();
- DEBUG("Pat: " << pat.path() << ", Type: " << type_hint.path());
+ auto& pat_path = v.path;
+ DEBUG("Pat: " << pat_path << ", Type: " << type_hint.path());
switch( hint_path.binding_type() )
{
case AST::Path::UNBOUND:
@@ -136,13 +158,13 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
auto& enm = pat_path.bound_enum();
auto idx = pat_path.bound_idx();
auto& var = enm.variants().at(idx);
- handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, pat.sub_patterns());
+ handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, v.sub_patterns);
break; }
default:
throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path()));
}
}
- break;
+ break; }
}
// Extract bindings and add to namespace
if( pat.binding().size() > 0 )
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
index 9aae9847..49c2e2a9 100644
--- a/src/convert/resolve.cpp
+++ b/src/convert/resolve.cpp
@@ -344,7 +344,7 @@ void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
{
DEBUG("pat = " << pat);
// Resolve "Maybe Bind" entries
- if( pat.type() == AST::Pattern::MAYBE_BIND )
+ if( pat.data().tag() == AST::Pattern::Data::MaybeBind )
{
::std::string name = pat.binding();
// Locate a _constant_ within the current namespace which matches this name
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index 1d3fa300..e1c32a69 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -661,36 +661,55 @@ void RustPrinter::print_bounds(const AST::TypeParams& params)
void RustPrinter::print_pattern(const AST::Pattern& p)
{
- if( p.binding() != "" && p.type() == AST::Pattern::ANY ) {
- m_os << p.binding();
- return;
- }
-
if( p.binding() != "" )
m_os << p.binding() << " @ ";
- switch(p.type())
+ switch(p.data().tag())
{
- case AST::Pattern::ANY:
+ case AST::Pattern::Data::Any:
m_os << "_";
break;
- case AST::Pattern::REF:
- m_os << "& ";
- print_pattern(p.sub_patterns()[0]);
- break;
- case AST::Pattern::VALUE:
- m_os << p.node();
+ case AST::Pattern::Data::MaybeBind:
+ m_os << "_ /*?*/";
break;
- case AST::Pattern::MAYBE_BIND:
- m_os << "/*?*/" << p.path();
- break;
- case AST::Pattern::TUPLE_STRUCT:
- m_os << p.path();
- case AST::Pattern::TUPLE:
+ case AST::Pattern::Data::Ref: {
+ const auto& v = p.data().as_Ref();
+ m_os << "& ";
+ print_pattern(*v.sub);
+ break; }
+ case AST::Pattern::Data::Value: {
+ auto& v = p.data().as_Value();
+ m_os << *v.start;
+ if( v.end.get() )
+ m_os << " ... " << *v.end;
+ break; }
+ case AST::Pattern::Data::StructTuple: {
+ const auto& v = p.data().as_StructTuple();
+ m_os << v.path << "(";
+ for(const auto& sp : v.sub_patterns) {
+ print_pattern(sp);
+ m_os << ",";
+ }
+ m_os << ")";
+ break; }
+ case AST::Pattern::Data::Struct: {
+ const auto& v = p.data().as_Struct();
+ m_os << v.path << "(";
+ for(const auto& sp : v.sub_patterns) {
+ m_os << sp.first << ": ";
+ print_pattern(sp.second);
+ m_os << ",";
+ }
+ m_os << ")";
+ break; }
+ case AST::Pattern::Data::Tuple: {
+ const auto& v = p.data().as_Tuple();
m_os << "(";
- for(const auto& sp : p.sub_patterns())
+ for(const auto& sp : v.sub_patterns) {
print_pattern(sp);
+ m_os << ",";
+ }
m_os << ")";
- break;
+ break; }
}
}
diff --git a/src/include/tagged_enum.hpp b/src/include/tagged_enum.hpp
index 2ef1b034..08168fe5 100644
--- a/src/include/tagged_enum.hpp
+++ b/src/include/tagged_enum.hpp
@@ -1,6 +1,7 @@
#define TE_DATANAME(name) Data_##name
#define ENUM_CONS(__tag, __type) \
+ static self_t make_null_##__tag() { self_t ret; ret.m_tag = __tag; new (ret.m_data) __type; return ::std::move(ret); } \
static self_t make_##__tag(__type v) \
{\
self_t ret;\
@@ -65,23 +66,46 @@
#define TE_MOVE_CASE6(_1, ...) TE_MOVE_CASE _1 TE_MOVE_CASE5(__VA_ARGS__)
#define TE_MOVE_CASE7(_1, ...) TE_MOVE_CASE _1 TE_MOVE_CASE6(__VA_ARGS__)
+// "tag_to_str" internals
+#define TE_TOSTR_CASE(tag,_) case tag: return #tag;
+#define TE_TOSTR_CASE2(a,b) TE_TOSTR_CASE a TE_TOSTR_CASE b
+#define TE_TOSTR_CASE3(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE2(__VA_ARGS__)
+#define TE_TOSTR_CASE4(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE3(__VA_ARGS__)
+#define TE_TOSTR_CASE5(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE4(__VA_ARGS__)
+#define TE_TOSTR_CASE6(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE5(__VA_ARGS__)
+#define TE_TOSTR_CASE7(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE6(__VA_ARGS__)
+// "tag_from_str" internals
+#define TE_FROMSTR_CASE(tag,_) else if(str == #tag) return tag;
+#define TE_FROMSTR_CASE2(a,b) TE_FROMSTR_CASE a TE_FROMSTR_CASE b
+#define TE_FROMSTR_CASE3(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE2(__VA_ARGS__)
+#define TE_FROMSTR_CASE4(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE3(__VA_ARGS__)
+#define TE_FROMSTR_CASE5(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE4(__VA_ARGS__)
+#define TE_FROMSTR_CASE6(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE5(__VA_ARGS__)
+#define TE_FROMSTR_CASE7(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE6(__VA_ARGS__)
+
// Macro to obtain a numbered macro for argument counts
-#define TE_GM(SUF,_1,_2,_3,_4,_5,_6,_7,COUNT,...) SUF##COUNT
+#define TE_GM_I(SUF,_1,_2,_3,_4,_5,_6,_7,COUNT,...) SUF##COUNT
+#define TE_GM(SUF,...) TE_GM_I(SUF,__VA_ARGS__,7,6,5,4,3,2)
-#define MAXS(...) TE_GM(MAXS ,__VA_ARGS__,7,6,5,4,3,2)(__VA_ARGS__)
-#define TE_TYPEDEFS(...) TE_GM(TE_TYPEDEF ,__VA_ARGS__,7,6,5,4,3,2)(__VA_ARGS__)
-#define TE_TAGS(...) TE_GM(TE_TAG ,__VA_ARGS__,7,6,5,4,3,2)(__VA_ARGS__)
-#define TE_DEST_CASES(...) TE_GM(TE_DEST_CASE,__VA_ARGS__,7,6,5,4,3,2)(__VA_ARGS__)
-#define TE_MOVE_CASES(...) TE_GM(TE_MOVE_CASE,__VA_ARGS__,7,6,5,4,3,2)(__VA_ARGS__)
-#define TE_CONSS(...) TE_GM(TE_CONS ,__VA_ARGS__,7,6,5,4,3,2)(__VA_ARGS__)
+#define MAXS(...) TE_GM(MAXS ,__VA_ARGS__)(__VA_ARGS__)
+#define TE_TYPEDEFS(...) TE_GM(TE_TYPEDEF ,__VA_ARGS__)(__VA_ARGS__)
+#define TE_TAGS(...) TE_GM(TE_TAG ,__VA_ARGS__)(__VA_ARGS__)
+#define TE_DEST_CASES(...) TE_GM(TE_DEST_CASE,__VA_ARGS__)(__VA_ARGS__)
+#define TE_MOVE_CASES(...) TE_GM(TE_MOVE_CASE,__VA_ARGS__)(__VA_ARGS__)
+#define TE_TOSTR_CASES(...) TE_GM(TE_TOSTR_CASE ,__VA_ARGS__)(__VA_ARGS__)
+#define TE_FROMSTR_CASES(...) TE_GM(TE_FROMSTR_CASE,__VA_ARGS__)(__VA_ARGS__)
+#define TE_CONSS(...) TE_GM(TE_CONS ,__VA_ARGS__)(__VA_ARGS__)
#define TAGGED_ENUM(_name, _def, ...) \
class _name { \
typedef _name self_t; \
TE_TYPEDEFS(__VA_ARGS__) \
+public:\
enum Tag { \
TE_TAGS(__VA_ARGS__)\
- } m_tag; \
+ }; \
+private:\
+ Tag m_tag; \
char m_data[MAXS(__VA_ARGS__)]; \
public:\
_name(): m_tag(_def) {}\
@@ -89,7 +113,18 @@ public:\
_name(_name&& x): m_tag(x.m_tag) { x.m_tag = _def; switch(m_tag) { TE_MOVE_CASES(__VA_ARGS__) } } \
_name& operator =(_name&& x) { this->~_name(); m_tag = x.m_tag; x.m_tag = _def; switch(m_tag) { TE_MOVE_CASES(__VA_ARGS__) }; return *this; } \
~_name() { switch(m_tag) { TE_DEST_CASES(__VA_ARGS__) } } \
+ \
+ Tag tag() const { return m_tag; }\
TE_CONSS(__VA_ARGS__) \
+/*
+*/ static const char *tag_to_str(Tag tag) { \
+ switch(tag) { TE_TOSTR_CASES(__VA_ARGS__) } return ""; \
+ }/*
+*/ static Tag tag_from_str(const ::std::string& str) { \
+ if(0); \
+ TE_FROMSTR_CASES(__VA_ARGS__)\
+ else throw ::std::runtime_error("enum "#_name" No conversion"); \
+ }\
}
#define ENUM3(_name, _def, _t1, _v1, _t2, _v2, _t3, _v3)\
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index e217974a..af044ab3 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -134,11 +134,11 @@ AST::Pattern Parse_PatternReal(TokenStream& lex)
AST::Pattern ret = Parse_PatternReal1(lex);
if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT )
{
- if( ret.type() != AST::Pattern::VALUE )
+ if( !ret.data().is_Value() )
throw ParseError::Generic(lex, "Using '...' with a non-value on left");
auto leftval = ret.take_node();
auto right_pat = Parse_PatternReal1(lex);
- if( right_pat.type() != AST::Pattern::VALUE )
+ if( !right_pat.data().is_Value() )
throw ParseError::Generic(lex, "Using '...' with a non-value on right");
auto rightval = right_pat.take_node();