From 7fef87364af0fea2ef5db89385674c9c3b892ec2 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 25 Mar 2015 22:41:25 +0800 Subject: Add flag for irrefutable matches, prevents arguments from being resolved --- src/ast/path.hpp | 4 ++++ src/parse/common.hpp | 2 +- src/parse/expr.cpp | 21 ++++++++++------- src/parse/pattern.cpp | 62 ++++++++++++++++++++++++++++----------------------- src/parse/root.cpp | 4 ++-- 5 files changed, 54 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/ast/path.hpp b/src/ast/path.hpp index c2b345df..03aeab23 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -188,6 +188,10 @@ public: void resolve(const Crate& crate); + bool is_trivial() const { + return m_class == RELATIVE && m_nodes.size() == 1 && m_nodes[0].args().size() == 0; + } + bool is_absolute() const { return m_class == ABSOLUTE; } bool is_relative() const { return m_class == RELATIVE; } size_t size() const { return m_nodes.size(); } diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 87c63bb9..d701f45a 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -34,7 +34,7 @@ extern ::std::vector Parse_Path_GenericList(TokenStream& lex); extern TypeRef Parse_Type(TokenStream& lex); -extern AST::Pattern Parse_Pattern(TokenStream& lex); +extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable); extern void Parse_Use(TokenStream& lex, ::std::function fcn); extern void Parse_Struct(AST::Module& mod, TokenStream& lex, bool is_public, const AST::MetaItems meta_items); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 9b3ce04b..61678eea 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -217,7 +217,7 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *expect_end) // let binding case TOK_RWORD_LET: { - AST::Pattern pat = Parse_Pattern(lex); + AST::Pattern pat = Parse_Pattern(lex, false); // irrefutable TypeRef type; if( GET_TOK(tok, lex) == TOK_COLON ) { type = Parse_Type(lex); @@ -325,7 +325,7 @@ ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime) Token tok; if( GET_TOK(tok, lex) == TOK_RWORD_LET ) { - auto pat = Parse_Pattern(lex); + auto pat = Parse_Pattern(lex, true); // Refutable pattern GET_CHECK_TOK(tok, lex, TOK_EQUAL); ExprNodeP val; { @@ -349,8 +349,9 @@ ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime) ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime) { Token tok; - - AST::Pattern pat = Parse_Pattern(lex); + + // Irrefutable pattern + AST::Pattern pat = Parse_Pattern(lex, false); GET_CHECK_TOK(tok, lex, TOK_RWORD_IN); ExprNodeP val; { @@ -375,7 +376,8 @@ ExprNodeP Parse_IfStmt(TokenStream& lex) SET_PARSE_FLAG(lex, disallow_struct_literal); if( GET_TOK(tok, lex) == TOK_RWORD_LET ) { if_let = true; - pat = Parse_Pattern(lex); + // Refutable pattern + pat = Parse_Pattern(lex, true); GET_CHECK_TOK(tok, lex, TOK_EQUAL); cond = Parse_Expr0(lex); } @@ -434,7 +436,8 @@ ExprNodeP Parse_Expr_Match(TokenStream& lex) lex.putback(tok); AST::ExprNode_Match::Arm arm; do { - arm.m_patterns.push_back( Parse_Pattern(lex) ); + // Refutable pattern + arm.m_patterns.push_back( Parse_Pattern(lex, true) ); } while( GET_TOK(tok, lex) == TOK_PIPE ); if( tok.type() == TOK_RWORD_IF ) @@ -861,7 +864,8 @@ ExprNodeP Parse_ExprVal_Closure(TokenStream& lex) while( GET_TOK(tok, lex) != TOK_PIPE ) { lex.putback(tok); - AST::Pattern pat = Parse_Pattern(lex); + // Irrefutable pattern + AST::Pattern pat = Parse_Pattern(lex, false); TypeRef type; if( GET_TOK(tok, lex) == TOK_COLON ) @@ -1226,7 +1230,8 @@ TokenTree Parse_TT_Pattern(TokenStream& lex) TTLexer wlex(lex); SET_PARSE_FLAG(wlex, no_expand_macros); - Parse_Pattern(wlex); + // Allow a refutable pattern here + Parse_Pattern(wlex, true); return wlex.get_output(); } diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index 6d26cd4a..97571bc2 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -14,11 +14,11 @@ typedef ::std::unique_ptr ExprNodeP; using AST::ExprNode; -::std::vector Parse_PatternList(TokenStream& lex); -AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path); -AST::Pattern Parse_PatternReal(TokenStream& lex); -AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path); +::std::vector Parse_PatternList(TokenStream& lex, bool is_refutable); +AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable); +AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); +AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refutable); /// Parse a pattern @@ -30,7 +30,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path); /// - `"string"` /// - `mut x` /// - `mut x @ 1 ... 2` -AST::Pattern Parse_Pattern(TokenStream& lex) +AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) { TRACE_FUNCTION; @@ -75,7 +75,8 @@ AST::Pattern Parse_Pattern(TokenStream& lex) lex.putback(tok); AST::Path path = Parse_Path(lex, false, PATH_GENERIC_EXPR); // - If the path is trivial - if( path.size() == 1 && path[0].args().size() == 0 ) + //if( path.is_relative() && path.size() == 1 && path[0].args().size() == 0 ) + if( path.is_trivial() ) { switch( GET_TOK(tok, lex) ) { @@ -89,39 +90,44 @@ AST::Pattern Parse_Pattern(TokenStream& lex) case TOK_BRACE_OPEN: case TOK_PAREN_OPEN: lex.putback(tok); - return Parse_PatternReal_Path(lex, path); + return Parse_PatternReal_Path(lex, path, is_refutable); // - Else, treat as a MaybeBind default: lex.putback(tok); - return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name()); + // if the pattern can be refuted (i.e this could be an enum variant), return MaybeBind + if( is_refutable ) + return AST::Pattern(AST::Pattern::TagMaybeBind(), path[0].name()); + // Otherwise, it IS a binding + else + return AST::Pattern(AST::Pattern::TagBind(), path[0].name()); } } else { // non-trivial path, has to be a pattern (not a bind) - return Parse_PatternReal_Path(lex, path); + return Parse_PatternReal_Path(lex, path, is_refutable); } } lex.putback(tok); - AST::Pattern pat = Parse_PatternReal(lex); + AST::Pattern pat = Parse_PatternReal(lex, is_refutable); pat.set_bind(bind_name, is_ref, is_mut); return ::std::move(pat); } -AST::Pattern Parse_PatternReal(TokenStream& lex); -AST::Pattern Parse_PatternReal1(TokenStream& lex); +AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); +AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternReal(TokenStream& lex) +AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable) { Token tok; - AST::Pattern ret = Parse_PatternReal1(lex); + AST::Pattern ret = Parse_PatternReal1(lex, is_refutable); if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) { 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); + 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(); @@ -134,7 +140,7 @@ AST::Pattern Parse_PatternReal(TokenStream& lex) return ret; } } -AST::Pattern Parse_PatternReal1(TokenStream& lex) +AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) { TRACE_FUNCTION; @@ -152,15 +158,15 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex) // NOTE: Falls back into "Pattern" not "PatternReal" to handle MaybeBind again if( GET_TOK(tok, lex) == TOK_RWORD_MUT ) // TODO: Actually use mutability - return AST::Pattern( AST::Pattern::TagReference(), Parse_Pattern(lex) ); + return AST::Pattern( AST::Pattern::TagReference(), Parse_Pattern(lex, is_refutable) ); lex.putback(tok); - return AST::Pattern( AST::Pattern::TagReference(), Parse_Pattern(lex) ); + return AST::Pattern( AST::Pattern::TagReference(), Parse_Pattern(lex, is_refutable) ); case TOK_IDENT: lex.putback(tok); - return Parse_PatternReal_Path( lex, Parse_Path(lex, false, PATH_GENERIC_EXPR) ); + return Parse_PatternReal_Path( lex, Parse_Path(lex, false, PATH_GENERIC_EXPR), is_refutable ); case TOK_DOUBLE_COLON: // 2. Paths are enum/struct names - return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR) ); + return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR), is_refutable ); case TOK_DASH: GET_CHECK_TOK(tok, lex, TOK_INTEGER); return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_Integer, -tok.intval(), tok.datatype()) ); @@ -173,30 +179,30 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex) case TOK_STRING: return AST::Pattern( AST::Pattern::TagValue(), NEWNODE(AST::ExprNode_String, tok.str()) ); case TOK_PAREN_OPEN: - return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex)); + return AST::Pattern(AST::Pattern::TagTuple(), Parse_PatternList(lex, is_refutable)); case TOK_SQUARE_OPEN: throw ParseError::Todo(lex, "array patterns"); default: throw ParseError::Unexpected(lex, tok); } } -AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path) +AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable) { Token tok; switch( GET_TOK(tok, lex) ) { case TOK_PAREN_OPEN: - return AST::Pattern(AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex)); + 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)); + 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))); } } -::std::vector Parse_PatternList(TokenStream& lex) +::std::vector Parse_PatternList(TokenStream& lex, bool is_refutable) { TRACE_FUNCTION; Token tok; @@ -209,7 +215,7 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path) else lex.putback(tok); - AST::Pattern pat = Parse_Pattern(lex); + AST::Pattern pat = Parse_Pattern(lex, is_refutable); DEBUG("pat = " << pat); child_pats.push_back( ::std::move(pat) ); } while( GET_TOK(tok, lex) == TOK_COMMA ); @@ -217,7 +223,7 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path) return child_pats; } -AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path) +AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refutable) { TRACE_FUNCTION; Token tok; @@ -254,7 +260,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path) } else { CHECK_TOK(tok, TOK_COLON); - pat = Parse_Pattern(lex); + pat = Parse_Pattern(lex, is_refutable); } subpats.push_back( ::std::make_pair(::std::move(field), ::std::move(pat)) ); diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 39776689..78ae4d2a 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -6,7 +6,6 @@ #include "../macros.hpp" #include -extern AST::Pattern Parse_Pattern(TokenStream& lex); AST::MetaItem Parse_MetaItem(TokenStream& lex); void Parse_ModRoot(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList *prev_modstack, const ::std::string& path); @@ -128,7 +127,8 @@ void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params) || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON) ) { - pat = Parse_Pattern(lex); + // Function args can't be refuted + pat = Parse_Pattern(lex, false); GET_CHECK_TOK(tok, lex, TOK_COLON); } -- cgit v1.2.3