diff options
-rw-r--r-- | src/ast/pattern.cpp | 94 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 30 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 14 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 2 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 12 | ||||
-rw-r--r-- | src/expand/mod.cpp | 4 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 43 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 26 |
8 files changed, 162 insertions, 63 deletions
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp index 35df2a1e..cf72d345 100644 --- a/src/ast/pattern.cpp +++ b/src/ast/pattern.cpp @@ -11,6 +11,36 @@ namespace AST { +::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& val) +{ + TU_MATCH(Pattern::Value, (val), (e), + (Invalid, + os << "/*BAD PAT VAL*/"; + ), + (Integer, + switch(e.type) + { + case CORETYPE_BOOL: + os << (e.value ? "true" : "false"); + break; + case CORETYPE_F32: + case CORETYPE_F64: + BUG(Span(), "Hit F32/f64 in printing pattern literal"); + break; + default: + os << e.value; + break; + } + ), + (String, + os << "\"" << e << "\""; + ), + (Named, + os << e; + ) + ) + return os; +} ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat) { os << "Pattern(" << pat.m_binding << " @ "; @@ -31,9 +61,9 @@ namespace AST { os << "&" << (ent.mut ? "mut " : "") << *ent.sub; ), (Value, - os << *ent.start; - if( ent.end.get() ) - os << " ... " << *ent.end; + os << ent.start; + if( ! ent.end.is_Invalid() ) + os << " ... " << ent.end; ), (Tuple, os << "(" << ent.sub_patterns << ")"; @@ -72,6 +102,56 @@ namespace AST { os << ")"; return os; } +void operator%(Serialiser& s, Pattern::Value::Tag c) { + s << Pattern::Value::tag_to_str(c); +} +void operator%(::Deserialiser& s, Pattern::Value::Tag& c) { + ::std::string n; + s.item(n); + c = Pattern::Value::tag_from_str(n); +} +void operator%(::Serialiser& s, const Pattern::Value& v) { + s % v.tag(); + TU_MATCH(Pattern::Value, (v), (e), + (Invalid, ), + (Integer, + s % e.type; + s.item( e.value ); + ), + (String, + s.item( e ); + ), + (Named, + s.item(e); + ) + ) +} +void operator%(::Deserialiser& s, Pattern::Value& v) { + Pattern::Value::Tag tag; + s % tag; + switch(tag) + { + case Pattern::Value::TAG_Invalid: + v = Pattern::Value::make_Invalid({}); + break; + case Pattern::Value::TAG_Integer: { + enum eCoreType ct; s % ct; + uint64_t val; s.item( val ); + v = Pattern::Value::make_Integer({ct, val}); + break; } + case Pattern::Value::TAG_String: { + ::std::string val; + s.item( val ); + v = Pattern::Value::make_String(val); + break; } + case Pattern::Value::TAG_Named: { + ::AST::Path val; + s.item( val ); + v = Pattern::Value::make_Named(val); + break; } + } +} + void operator%(Serialiser& s, Pattern::Data::Tag c) { s << Pattern::Data::tag_to_str(c); } @@ -100,8 +180,8 @@ SERIALISE_TYPE(Pattern::, "Pattern", { s << e.sub; ), (Value, - s << e.start; - s << e.end; + s % e.start; + s % e.end; ), (Tuple, s << e.sub_patterns; @@ -140,8 +220,8 @@ SERIALISE_TYPE(Pattern::, "Pattern", { s.item( ent.sub ); ) _D(Value, - s.item( ent.start ); - s.item( ent.end ); + s % ent.start; + s % ent.end; ) _D(Tuple, s.item( ent.sub_patterns ); diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index b8e86b70..77e1142c 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -13,8 +13,6 @@ using ::std::unique_ptr; using ::std::move; class MacroInvocation; -class ExprNode; - class Pattern: public Serialisable { @@ -24,13 +22,23 @@ public: BIND_REF, BIND_MUTREF, }; + TAGGED_UNION(Value, Invalid, + (Invalid, struct {}), + (Integer, struct { + enum eCoreType type; + uint64_t value; // Signed numbers are encoded as 2's complement + }), + (String, ::std::string), + (Named, Path) + ); + TAGGED_UNION(Data, Any, (MaybeBind, struct { } ), (Macro, struct { unique_ptr<::AST::MacroInvocation> inv; } ), (Any, struct { } ), (Box, struct { unique_ptr<Pattern> sub; } ), (Ref, struct { bool mut; unique_ptr<Pattern> sub; } ), - (Value, struct { unique_ptr<ExprNode> start; unique_ptr<ExprNode> end; } ), + (Value, struct { Value start; Value end; } ), (Tuple, struct { ::std::vector<Pattern> sub_patterns; } ), (StructTuple, struct { Path path; ::std::vector<Pattern> sub_patterns; } ), (Struct, struct { Path path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; } ), @@ -74,8 +82,8 @@ public: {} struct TagValue {}; - Pattern(TagValue, unique_ptr<ExprNode> node, unique_ptr<ExprNode> node2 = 0): - m_data( Data::make_Value({ ::std::move(node), ::std::move(node2) }) ) + Pattern(TagValue, Value val, Value end = Value()): + m_data( Data::make_Value({ ::std::move(val), ::std::move(end) }) ) {} @@ -114,21 +122,11 @@ public: m_binding_mut = is_mut; } - ::std::unique_ptr<ExprNode> take_node() { - assert(m_data.is_Value()); - return ::std::move(m_data.unwrap_Value().start); - } // Accessors const ::std::string& binding() const { return m_binding; } 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_data.as_StructTuple().path; } const Path& path() const { return m_data.as_StructTuple().path; } @@ -142,6 +140,8 @@ public: } }; +::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& val); + }; #endif diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 5909d689..7e70f1f0 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -148,12 +148,14 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) (MaybeBind, throw ::std::runtime_error("Calling CASTIterator::handle_pattern on MAYBE_BIND, not valid"); ), - (Value, { - auto& v = pat.data().as_Value(); - handle_expr( *v.start ); - if( v.end.get() ) - handle_expr( *v.end ); - }), + (Value, + TU_IFLET(AST::Pattern::Value, v.start, Named, e, + handle_path(e, CASTIterator::MODE_TYPE); + ) + TU_IFLET(AST::Pattern::Value, v.end, Named, e, + handle_path(e, CASTIterator::MODE_TYPE); + ) + ), (Tuple, { auto& v = pat.data().as_Tuple(); // Tuple is handled by subpattern code diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index ebfe2998..a240c6fc 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -1652,7 +1652,7 @@ void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) // It's a constant (enum variant usually)
pat = AST::Pattern(
AST::Pattern::TagValue(),
- ::std::unique_ptr<AST::ExprNode>( new AST::ExprNode_NamedValue( ::std::move(newpath) ) )
+ AST::Pattern::Value::make_Named( mv$(newpath) )
);
}
}
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 357795c5..361bd245 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -801,14 +801,12 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) m_os << "& "; print_pattern(*v.sub, is_refutable); }), - (Value, { - auto& v = p.data().as_Value(); - v.start->visit(*this); - if( v.end.get() ) { - m_os << " ... "; - v.end->visit(*this); + (Value, + m_os << v.start; + if( ! v.end.is_Invalid() ) { + m_os << " ... " << v.end; } - }), + ), (StructTuple, { const auto& v = p.data().as_StructTuple(); m_os << v.path << "("; diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index bbe4db85..2f4fe0be 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -150,8 +150,8 @@ void Expand_Pattern(bool is_early, ::AST::Crate& crate, LList<const AST::Module* Expand_Pattern(is_early, crate, modstack, mod, *e.sub); ), (Value, - Expand_Expr(is_early, crate, modstack, e.start); - Expand_Expr(is_early, crate, modstack, e.end); + //Expand_Expr(is_early, crate, modstack, e.start); + //Expand_Expr(is_early, crate, modstack, e.end); ), (Tuple, for(auto& sp : e.sub_patterns) diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index dcbc8c5d..bb697618 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -140,13 +140,15 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable) { if( !ret.data().is_Value() ) throw ParseError::Generic(lex, "Using '...' with a non-value on left"); - auto leftval = ret.take_node(); + auto& ret_v = ret.data().as_Value(); + auto right_pat = Parse_PatternReal1(lex, is_refutable); if( !right_pat.data().is_Value() ) throw ParseError::Generic(lex, "Using '...' with a non-value on right"); - auto rightval = right_pat.take_node(); + auto rightval = mv$( right_pat.data().as_Value().start ); + ret_v.end = mv$(rightval); - return AST::Pattern(AST::Pattern::TagValue(), ::std::move(leftval), ::std::move(rightval)); + return ret; } else { @@ -193,31 +195,32 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) auto dt = tok.datatype(); if(dt == CORETYPE_ANY) dt = CORETYPE_I32; - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, -tok.intval(), dt) ); - } - else if( tok.type() == TOK_FLOAT ) - { - auto dt = tok.datatype(); - if(dt == CORETYPE_ANY) - dt = CORETYPE_F32; - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Float, -tok.floatval(), dt) ); + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({dt, -tok.intval()}) ); } + //else if( tok.type() == TOK_FLOAT ) + //{ + // auto dt = tok.datatype(); + // if(dt == CORETYPE_ANY) + // dt = CORETYPE_F32; + // return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({dt, reinterpret_cast<uint64_t>(-tok.floatval()), dt}) ); + //} else { throw ParseError::Unexpected(lex, tok, {TOK_INTEGER, TOK_FLOAT}); } - case TOK_FLOAT: - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Float, tok.floatval(), tok.datatype()) ); + //case TOK_FLOAT: + // return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({tok.datatype(), reinterpret_cast<uint64_t>(tok.floatval())}) ); case TOK_INTEGER: - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, tok.intval(), tok.datatype()) ); + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({tok.datatype(), tok.intval()}) ); case TOK_RWORD_TRUE: - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, true ) ); + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 1}) ); case TOK_RWORD_FALSE: - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE( AST::ExprNode_Bool, false ) ); + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 0}) ); case TOK_STRING: - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) ); + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); case TOK_BYTESTRING: - return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) ); + // TODO: Differentiate byte and UTF-8 strings + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); case TOK_PAREN_OPEN: return AST::Pattern( AST::Pattern::TagTuple(), Parse_PatternList(lex, is_refutable) ); case TOK_SQUARE_OPEN: @@ -233,12 +236,12 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_re switch( GET_TOK(tok, lex) ) { case TOK_PAREN_OPEN: - return AST::Pattern(AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex, is_refutable)); + return AST::Pattern( AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex, is_refutable) ); case TOK_BRACE_OPEN: return Parse_PatternStruct(lex, ::std::move(path), is_refutable); default: lex.putback(tok); - return AST::Pattern(AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_NamedValue, ::std::move(path))); + return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(mv$(path)) ); } } diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index de555c37..7d521686 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -351,6 +351,19 @@ void Resolve_Absolute_Generic(const Context& context, ::AST::GenericParams& para } } +// Locals shouldn't be possible, as they'd end up as MaybeBind. Will assert the path class. +void Resolve_Absolute_PatternValue(const Context& context, ::AST::Pattern::Value& val) +{ + TU_MATCH(::AST::Pattern::Value, (val), (e), + (Invalid, ), + (Integer, ), + (String, ), + (Named, + assert( ! e.is_trivial() ); + Resolve_Absolute_Path(context, Span(), true, e); + ) + ) +} void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pattern& pat) { if( pat.binding() != "" ) { @@ -361,7 +374,12 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa TU_MATCH( ::AST::Pattern::Data, (pat.data()), (e), (MaybeBind, - BUG(Span(), "Resolve_Absolute_Pattern - Encountered MaybeBind"); + if( allow_refutable ) { + TODO(Span(), "Resolve_Absolute_Pattern - Encountered MaybeBind in refutable context"); + } + else { + TODO(Span(), "Resolve_Absolute_Pattern - Encountered MaybeBind in irrefutable context - replace with binding"); + } ), (Macro, BUG(Span(), "Resolve_Absolute_Pattern - Encountered Macro"); @@ -378,10 +396,8 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa (Value, if( ! allow_refutable ) BUG(Span(), "Resolve_Absolute_Pattern - Enountered refutable pattern where only irrefutable allowed"); - // TODO: Value patterns should be resolved with a different context (disallowing locals) - Resolve_Absolute_Expr(context, *e.start); - if( e.end ) - Resolve_Absolute_Expr(context, *e.end); + Resolve_Absolute_PatternValue(context, e.start); + Resolve_Absolute_PatternValue(context, e.end); ), (Tuple, for(auto& sp : e.sub_patterns) |