summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/path.hpp4
-rw-r--r--src/parse/common.hpp2
-rw-r--r--src/parse/expr.cpp21
-rw-r--r--src/parse/pattern.cpp62
-rw-r--r--src/parse/root.cpp4
5 files changed, 54 insertions, 39 deletions
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<TypeRef> 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<void(AST::Path, ::std::string)> 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<AST::ExprNode> ExprNodeP;
using AST::ExprNode;
-::std::vector<AST::Pattern> 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<AST::Pattern> 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<AST::Pattern> Parse_PatternList(TokenStream& lex)
+::std::vector<AST::Pattern> 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 <cassert>
-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<AST::Module*> *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);
}