aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/inputs/in_expression.yue1
-rw-r--r--spec/inputs/unicode/in_expression.yue39
-rw-r--r--spec/outputs/in_expression.lua4
-rw-r--r--spec/outputs/unicode/in_expression.lua52
-rw-r--r--src/yuescript/yue_ast.cpp9
-rw-r--r--src/yuescript/yue_ast.h11
-rw-r--r--src/yuescript/yue_compiler.cpp291
-rw-r--r--src/yuescript/yue_parser.cpp5
-rw-r--r--src/yuescript/yue_parser.h1
9 files changed, 238 insertions, 175 deletions
diff --git a/spec/inputs/in_expression.yue b/spec/inputs/in_expression.yue
index 7ee0816..0b2a87a 100644
--- a/spec/inputs/in_expression.yue
+++ b/spec/inputs/in_expression.yue
@@ -1,5 +1,4 @@
1-a^2 in {1, 2, 3} |> f 1-a^2 in {1, 2, 3} |> f
2-a^2 in [1, 2, 3] |> f
3 2
4has = "foo" in { "bar", "foo" } 3has = "foo" in { "bar", "foo" }
5 4
diff --git a/spec/inputs/unicode/in_expression.yue b/spec/inputs/unicode/in_expression.yue
index e068cbf..4a87099 100644
--- a/spec/inputs/unicode/in_expression.yue
+++ b/spec/inputs/unicode/in_expression.yue
@@ -29,5 +29,44 @@ do
29 检查 -> return 对象x in 数组tb 29 检查 -> return 对象x in 数组tb
30 检查 -> 对象x not in 数组tb 30 检查 -> 对象x not in 数组tb
31 31
32do
33 函数1 = ->
34 变量a = 2
35 变量a in [
36 1
37 2
38 3
39 4
40 ]
41 函数2 = ->
42 变量a not in [
43 1
44 2
45 3
46 4
47 ]
48 函数3 = ->
49 变量a = 2
50 变量a in { 变量b, 变量c, 变量d
51 变量e, 变量f
52 变量g
53 }
54 函数4 = ->
55 变量a = 2
56 变量b = a in [ 1, 2
57 3, 4
58 ]
59 函数5 = ->
60 a变量 = 2
61 return a变量 in [ 1, 2
62 3, 4
63 ]
64 函数6 = ->
65 b变量 = a变量 not in {
66 1
67 2
68 字段x: 3
69 }
70
32nil 71nil
33 72
diff --git a/spec/outputs/in_expression.lua b/spec/outputs/in_expression.lua
index afcc030..b99be8a 100644
--- a/spec/outputs/in_expression.lua
+++ b/spec/outputs/in_expression.lua
@@ -2,10 +2,6 @@ f((function()
2 local _val_0 = -a ^ 2 2 local _val_0 = -a ^ 2
3 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0 3 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0
4end)()) 4end)())
5f((function()
6 local _val_0 = -a ^ 2
7 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0
8end)())
9local has 5local has
10do 6do
11 local _val_0 = "foo" 7 local _val_0 = "foo"
diff --git a/spec/outputs/unicode/in_expression.lua b/spec/outputs/unicode/in_expression.lua
index 7c584f3..2f47b1f 100644
--- a/spec/outputs/unicode/in_expression.lua
+++ b/spec/outputs/unicode/in_expression.lua
@@ -153,4 +153,56 @@ do
153 return true 153 return true
154 end) 154 end)
155end 155end
156do
157 local _u51fd_u65701
158 _u51fd_u65701 = function()
159 local _u53d8_u91cfa = 2
160 return (1 == _u53d8_u91cfa or 2 == _u53d8_u91cfa or 3 == _u53d8_u91cfa or 4 == _u53d8_u91cfa)
161 end
162 local _u51fd_u65702
163 _u51fd_u65702 = function()
164 local _val_0 = _u53d8_u91cfa
165 return not (1 == _val_0 or 2 == _val_0 or 3 == _val_0 or 4 == _val_0)
166 end
167 local _u51fd_u65703
168 _u51fd_u65703 = function()
169 local _u53d8_u91cfa = 2
170 return (_u53d8_u91cfb == _u53d8_u91cfa or _u53d8_u91cfc == _u53d8_u91cfa or _u53d8_u91cfd == _u53d8_u91cfa or _u53d8_u91cfe == _u53d8_u91cfa or _u53d8_u91cff == _u53d8_u91cfa or _u53d8_u91cfg == _u53d8_u91cfa)
171 end
172 local _u51fd_u65704
173 _u51fd_u65704 = function()
174 local _u53d8_u91cfa = 2
175 local _u53d8_u91cfb
176 do
177 local _val_0 = a
178 _u53d8_u91cfb = 1 == _val_0 or 2 == _val_0 or 3 == _val_0 or 4 == _val_0
179 end
180 end
181 local _u51fd_u65705
182 _u51fd_u65705 = function()
183 local a_u53d8_u91cf = 2
184 return (1 == a_u53d8_u91cf or 2 == a_u53d8_u91cf or 3 == a_u53d8_u91cf or 4 == a_u53d8_u91cf)
185 end
186 local _u51fd_u65706
187 _u51fd_u65706 = function()
188 local b_u53d8_u91cf
189 do
190 local _check_0 = {
191 1,
192 2,
193 ["字段x"] = 3
194 }
195 local _val_0 = a_u53d8_u91cf
196 local _find_0 = false
197 for _index_0 = 1, #_check_0 do
198 local _item_0 = _check_0[_index_0]
199 if _item_0 == _val_0 then
200 _find_0 = true
201 break
202 end
203 end
204 b_u53d8_u91cf = not _find_0
205 end
206 end
207end
156return nil 208return nil
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index c25f42d..faa175d 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -1405,15 +1405,8 @@ std::string UnaryExp_t::to_string(void* ud) const {
1405 } 1405 }
1406 return line; 1406 return line;
1407} 1407}
1408std::string InDiscrete_t::to_string(void* ud) const {
1409 str_list temp;
1410 for (auto value : values.objects()) {
1411 temp.emplace_back(value->to_string(ud));
1412 }
1413 return '[' + join(temp, ", "sv) + (temp.size() == 1 ? ",]"s : "]"s);
1414}
1415std::string In_t::to_string(void* ud) const { 1408std::string In_t::to_string(void* ud) const {
1416 return (not_ ? "not "s : ""s) + "in "s + item->to_string(ud); 1409 return (not_ ? "not "s : ""s) + "in "s + value->to_string(ud);
1417} 1410}
1418std::string ExpListAssign_t::to_string(void* ud) const { 1411std::string ExpListAssign_t::to_string(void* ud) const {
1419 if (action) { 1412 if (action) {
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index fc07370..90dce7a 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -81,6 +81,7 @@ class In_t;
81class NormalDef_t; 81class NormalDef_t;
82class SpreadListExp_t; 82class SpreadListExp_t;
83class Comprehension_t; 83class Comprehension_t;
84class Value_t;
84} // namespace yue 85} // namespace yue
85 86
86AST_LEAF(Num) 87AST_LEAF(Num)
@@ -445,16 +446,10 @@ AST_END(UnaryOperator, "unary_op"sv)
445AST_LEAF(NotIn) 446AST_LEAF(NotIn)
446AST_END(NotIn, "not_in"sv) 447AST_END(NotIn, "not_in"sv)
447 448
448AST_NODE(InDiscrete)
449 ast_ptr<true, Seperator_t> sep;
450 ast_list<true, Exp_t> values;
451 AST_MEMBER(InDiscrete, &sep, &values)
452AST_END(InDiscrete, "in_discrete"sv)
453
454AST_NODE(In) 449AST_NODE(In)
455 ast_ptr<false, NotIn_t> not_; 450 ast_ptr<false, NotIn_t> not_;
456 ast_sel<true, InDiscrete_t, Exp_t> item; 451 ast_ptr<true, Value_t> value;
457 AST_MEMBER(In, &not_, &item) 452 AST_MEMBER(In, &not_, &value)
458AST_END(In, "in"sv) 453AST_END(In, "in"sv)
459 454
460AST_NODE(Assignable) 455AST_NODE(Assignable)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 3892d72..5cdbfda 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -1231,7 +1231,7 @@ private:
1231 auto unary = static_cast<UnaryExp_t*>(exp->pipeExprs.back()); 1231 auto unary = static_cast<UnaryExp_t*>(exp->pipeExprs.back());
1232 BREAK_IF(unary->expos.size() != 1); 1232 BREAK_IF(unary->expos.size() != 1);
1233 BREAK_IF(!unary->inExp); 1233 BREAK_IF(!unary->inExp);
1234 if (unary->inExp->item.is<Exp_t>()) { 1234 if (unary->inExp) {
1235 return unary; 1235 return unary;
1236 } 1236 }
1237 auto value = static_cast<Value_t*>(unary->expos.back()); 1237 auto value = static_cast<Value_t*>(unary->expos.back());
@@ -5946,62 +5946,146 @@ private:
5946 varName.clear(); 5946 varName.clear();
5947 } 5947 }
5948 } 5948 }
5949 ast_ptr<false, InDiscrete_t> discrete; 5949 ast_ptr<false, ExpList_t> discrete;
5950 if (auto inExp = unary_exp->inExp->item.as<Exp_t>()) { 5950 auto inExp = unary_exp->inExp->value.get();
5951 BLOCK_START 5951 BLOCK_START
5952 auto value = singleValueFrom(inExp); 5952 auto sval = inExp->item.as<SimpleValue_t>();
5953 BREAK_IF(!value); 5953 BREAK_IF(!sval);
5954 auto sval = value->item.as<SimpleValue_t>(); 5954 if (auto table = sval->value.as<TableLit_t>()) {
5955 BREAK_IF(!sval); 5955 discrete = inExp->new_ptr<ExpList_t>();
5956 if (auto table = sval->value.as<TableLit_t>()) { 5956 for (ast_node* val : table->values.objects()) {
5957 discrete = inExp->new_ptr<InDiscrete_t>(); 5957 if (auto def = ast_cast<NormalDef_t>(val)) {
5958 for (ast_node* val : table->values.objects()) { 5958 if (def->defVal) {
5959 discrete = nullptr;
5960 break;
5961 } else {
5962 discrete->exprs.push_back(def->item);
5963 }
5964 } else if (ast_is<Exp_t>(val)) {
5965 discrete->exprs.push_back(val);
5966 } else {
5967 discrete = nullptr;
5968 break;
5969 }
5970 }
5971 } else if (auto comp = sval->value.as<Comprehension_t>()) {
5972 if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) {
5973 discrete = inExp->new_ptr<ExpList_t>();
5974 for (ast_node* val : comp->items.objects()) {
5959 if (auto def = ast_cast<NormalDef_t>(val)) { 5975 if (auto def = ast_cast<NormalDef_t>(val)) {
5960 if (def->defVal) { 5976 if (def->defVal) {
5961 discrete = nullptr; 5977 discrete = nullptr;
5962 break; 5978 break;
5963 } else { 5979 } else {
5964 discrete->values.push_back(def->item); 5980 discrete->exprs.push_back(def->item);
5965 } 5981 }
5966 } else if (ast_is<Exp_t>(val)) {
5967 discrete->values.push_back(val);
5968 } else { 5982 } else {
5969 discrete = nullptr; 5983 discrete = nullptr;
5970 break; 5984 break;
5971 } 5985 }
5972 } 5986 }
5973 } else if (auto comp = sval->value.as<Comprehension_t>()) { 5987 }
5974 if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { 5988 }
5975 discrete = inExp->new_ptr<InDiscrete_t>(); 5989 BLOCK_END
5976 for (ast_node* val : comp->items.objects()) { 5990 BLOCK_START
5977 if (auto def = ast_cast<NormalDef_t>(val)) { 5991 BREAK_IF(discrete);
5978 if (def->defVal) { 5992 str_list temp;
5979 discrete = nullptr; 5993 auto checkVar = singleVariableFrom(inExp, false);
5980 break; 5994 if (usage == ExpUsage::Assignment) {
5981 } else { 5995 auto block = x->new_ptr<Block_t>();
5982 discrete->values.push_back(def->item); 5996 if (checkVar.empty() || !isLocal(checkVar)) {
5983 } 5997 checkVar = getUnusedName("_check_"sv);
5984 } else { 5998 auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp);
5985 discrete = nullptr; 5999 auto stmt = x->new_ptr<Statement_t>();
5986 break; 6000 stmt->content.set(assignment);
5987 } 6001 block->statements.push_back(stmt);
6002 }
6003 if (varName.empty()) {
6004 auto newUnaryExp = x->new_ptr<UnaryExp_t>();
6005 newUnaryExp->ops.dup(unary_exp->ops);
6006 newUnaryExp->expos.dup(unary_exp->expos);
6007 auto exp = newExp(newUnaryExp, x);
6008 varName = getUnusedName("_val_"sv);
6009 auto assignExp = toAst<Exp_t>(varName, x);
6010 auto assignment = assignmentFrom(assignExp, exp, x);
6011 auto stmt = x->new_ptr<Statement_t>();
6012 stmt->content.set(assignment);
6013 block->statements.push_back(stmt);
6014 }
6015 auto findVar = getUnusedName("_find_");
6016 auto itemVar = getUnusedName("_item_");
6017 _buf << findVar << "=false\n"sv;
6018 _buf << "for "sv << itemVar << " in *"sv << checkVar << '\n';
6019 _buf << "\tif "sv << itemVar << "=="sv << varName << '\n';
6020 _buf << "\t\t"sv << findVar << "=true\n"sv;
6021 _buf << "\t\tbreak\n"sv;
6022 if (unary_exp->inExp->not_) {
6023 _buf << "not "sv << findVar;
6024 } else {
6025 _buf << findVar;
6026 }
6027 auto blockStr = clearBuf();
6028 auto checkBlock = toAst<Block_t>(blockStr, inExp);
6029 block->statements.dup(checkBlock->statements);
6030 auto body = x->new_ptr<Body_t>();
6031 body->content.set(block);
6032 auto doNode = x->new_ptr<Do_t>();
6033 doNode->body.set(body);
6034 auto assign = x->new_ptr<Assign_t>();
6035 auto simpleValue = x->new_ptr<SimpleValue_t>();
6036 simpleValue->value.set(doNode);
6037 auto value = x->new_ptr<Value_t>();
6038 value->item.set(simpleValue);
6039 assign->values.push_back(newExp(value, x));
6040 auto assignment = x->new_ptr<ExpListAssign_t>();
6041 assignment->action.set(assign);
6042 assignment->expList.set(assignList);
6043 transformAssignment(assignment, temp);
6044 out.push_back(join(temp));
6045 return;
6046 } else {
6047 auto arrayCheck = [&](bool exist) {
6048 auto indexVar = getUnusedName("_index_");
6049 _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x);
6050 incIndentOffset();
6051 _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x);
6052 incIndentOffset();
6053 _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x);
6054 decIndentOffset();
6055 _buf << indent() << "end"sv << nll(x);
6056 decIndentOffset();
6057 _buf << indent() << "end"sv << nll(x);
6058 _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x);
6059 temp.push_back(clearBuf());
6060 };
6061 bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar);
6062 if (useShortCheck) {
6063 if (usage == ExpUsage::Return) {
6064 arrayCheck(!unary_exp->inExp->not_);
6065 } else {
6066 pushFunctionScope();
6067 pushAnonVarArg();
6068 pushScope();
6069 arrayCheck(true);
6070 temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x));
6071 popScope();
6072 temp.push_back(indent() + anonFuncEnd() + ')');
6073 if (unary_exp->inExp->not_) {
6074 temp.front().insert(0, "not "s);
5988 } 6075 }
6076 popAnonVarArg();
6077 popFunctionScope();
6078 }
6079 } else {
6080 if (usage == ExpUsage::Closure) {
6081 pushFunctionScope();
6082 pushAnonVarArg();
6083 pushScope();
5989 } 6084 }
5990 }
5991 BLOCK_END
5992
5993 BLOCK_START
5994 BREAK_IF(discrete);
5995 str_list temp;
5996 auto checkVar = singleVariableFrom(inExp, false);
5997 if (usage == ExpUsage::Assignment) {
5998 auto block = x->new_ptr<Block_t>();
5999 if (checkVar.empty() || !isLocal(checkVar)) { 6085 if (checkVar.empty() || !isLocal(checkVar)) {
6000 checkVar = getUnusedName("_check_"sv); 6086 checkVar = getUnusedName("_check_"sv);
6001 auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), inExp, inExp); 6087 auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp);
6002 auto stmt = x->new_ptr<Statement_t>(); 6088 transformAssignment(assignment, temp);
6003 stmt->content.set(assignment);
6004 block->statements.push_back(stmt);
6005 } 6089 }
6006 if (varName.empty()) { 6090 if (varName.empty()) {
6007 auto newUnaryExp = x->new_ptr<UnaryExp_t>(); 6091 auto newUnaryExp = x->new_ptr<UnaryExp_t>();
@@ -6011,117 +6095,26 @@ private:
6011 varName = getUnusedName("_val_"sv); 6095 varName = getUnusedName("_val_"sv);
6012 auto assignExp = toAst<Exp_t>(varName, x); 6096 auto assignExp = toAst<Exp_t>(varName, x);
6013 auto assignment = assignmentFrom(assignExp, exp, x); 6097 auto assignment = assignmentFrom(assignExp, exp, x);
6014 auto stmt = x->new_ptr<Statement_t>(); 6098 transformAssignment(assignment, temp);
6015 stmt->content.set(assignment);
6016 block->statements.push_back(stmt);
6017 } 6099 }
6018 auto findVar = getUnusedName("_find_"); 6100 if (usage == ExpUsage::Return) {
6019 auto itemVar = getUnusedName("_item_"); 6101 arrayCheck(!unary_exp->inExp->not_);
6020 _buf << findVar << "=false\n"sv;
6021 _buf << "for "sv << itemVar << " in *"sv << checkVar << '\n';
6022 _buf << "\tif "sv << itemVar << "=="sv << varName << '\n';
6023 _buf << "\t\t"sv << findVar << "=true\n"sv;
6024 _buf << "\t\tbreak\n"sv;
6025 if (unary_exp->inExp->not_) {
6026 _buf << "not "sv << findVar;
6027 } else { 6102 } else {
6028 _buf << findVar; 6103 arrayCheck(!unary_exp->inExp->not_);
6029 } 6104 temp.push_front(anonFuncStart() + nll(x));
6030 auto blockStr = clearBuf(); 6105 popScope();
6031 auto checkBlock = toAst<Block_t>(blockStr, inExp); 6106 temp.push_back(indent() + anonFuncEnd());
6032 block->statements.dup(checkBlock->statements); 6107 popAnonVarArg();
6033 auto body = x->new_ptr<Body_t>(); 6108 popFunctionScope();
6034 body->content.set(block);
6035 auto doNode = x->new_ptr<Do_t>();
6036 doNode->body.set(body);
6037 auto assign = x->new_ptr<Assign_t>();
6038 auto simpleValue = x->new_ptr<SimpleValue_t>();
6039 simpleValue->value.set(doNode);
6040 auto value = x->new_ptr<Value_t>();
6041 value->item.set(simpleValue);
6042 assign->values.push_back(newExp(value, x));
6043 auto assignment = x->new_ptr<ExpListAssign_t>();
6044 assignment->action.set(assign);
6045 assignment->expList.set(assignList);
6046 transformAssignment(assignment, temp);
6047 out.push_back(join(temp));
6048 return;
6049 } else {
6050 auto arrayCheck = [&](bool exist) {
6051 auto indexVar = getUnusedName("_index_");
6052 _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x);
6053 incIndentOffset();
6054 _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x);
6055 incIndentOffset();
6056 _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x);
6057 decIndentOffset();
6058 _buf << indent() << "end"sv << nll(x);
6059 decIndentOffset();
6060 _buf << indent() << "end"sv << nll(x);
6061 _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x);
6062 temp.push_back(clearBuf());
6063 };
6064 bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar);
6065 if (useShortCheck) {
6066 if (usage == ExpUsage::Return) {
6067 arrayCheck(!unary_exp->inExp->not_);
6068 } else {
6069 pushFunctionScope();
6070 pushAnonVarArg();
6071 pushScope();
6072 arrayCheck(true);
6073 temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x));
6074 popScope();
6075 temp.push_back(indent() + anonFuncEnd() + ')');
6076 if (unary_exp->inExp->not_) {
6077 temp.front().insert(0, "not "s);
6078 }
6079 popAnonVarArg();
6080 popFunctionScope();
6081 }
6082 } else {
6083 if (usage == ExpUsage::Closure) {
6084 pushFunctionScope();
6085 pushAnonVarArg();
6086 pushScope();
6087 }
6088 if (checkVar.empty() || !isLocal(checkVar)) {
6089 checkVar = getUnusedName("_check_"sv);
6090 auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), inExp, inExp);
6091 transformAssignment(assignment, temp);
6092 }
6093 if (varName.empty()) {
6094 auto newUnaryExp = x->new_ptr<UnaryExp_t>();
6095 newUnaryExp->ops.dup(unary_exp->ops);
6096 newUnaryExp->expos.dup(unary_exp->expos);
6097 auto exp = newExp(newUnaryExp, x);
6098 varName = getUnusedName("_val_"sv);
6099 auto assignExp = toAst<Exp_t>(varName, x);
6100 auto assignment = assignmentFrom(assignExp, exp, x);
6101 transformAssignment(assignment, temp);
6102 }
6103 if (usage == ExpUsage::Return) {
6104 arrayCheck(!unary_exp->inExp->not_);
6105 } else {
6106 arrayCheck(!unary_exp->inExp->not_);
6107 temp.push_front(anonFuncStart() + nll(x));
6108 popScope();
6109 temp.push_back(indent() + anonFuncEnd());
6110 popAnonVarArg();
6111 popFunctionScope();
6112 }
6113 } 6109 }
6114 out.push_back(join(temp));
6115 return;
6116 } 6110 }
6117 BLOCK_END 6111 out.push_back(join(temp));
6118 } 6112 return;
6119 if (!discrete) {
6120 discrete = unary_exp->inExp->item.to<InDiscrete_t>();
6121 } 6113 }
6122 if (usage == ExpUsage::Closure && discrete->values.size() == 1) { 6114 BLOCK_END
6115 if (usage == ExpUsage::Closure && discrete->exprs.size() == 1) {
6123 str_list tmp; 6116 str_list tmp;
6124 transformExp(static_cast<Exp_t*>(discrete->values.front()), tmp, ExpUsage::Closure); 6117 transformExp(static_cast<Exp_t*>(discrete->exprs.front()), tmp, ExpUsage::Closure);
6125 tmp.push_back(" == "s); 6118 tmp.push_back(" == "s);
6126 auto newUnaryExp = x->new_ptr<UnaryExp_t>(); 6119 auto newUnaryExp = x->new_ptr<UnaryExp_t>();
6127 newUnaryExp->ops.dup(unary_exp->ops); 6120 newUnaryExp->ops.dup(unary_exp->ops);
@@ -6156,7 +6149,7 @@ private:
6156 transformAssignment(assignment, temp); 6149 transformAssignment(assignment, temp);
6157 6150
6158 str_list tmp; 6151 str_list tmp;
6159 for (auto exp : discrete->values.objects()) { 6152 for (auto exp : discrete->exprs.objects()) {
6160 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); 6153 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure);
6161 } 6154 }
6162 if (usage == ExpUsage::Assignment) { 6155 if (usage == ExpUsage::Assignment) {
@@ -6196,7 +6189,7 @@ private:
6196 } 6189 }
6197 } else { 6190 } else {
6198 str_list tmp; 6191 str_list tmp;
6199 for (auto exp : discrete->values.objects()) { 6192 for (auto exp : discrete->exprs.objects()) {
6200 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); 6193 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure);
6201 } 6194 }
6202 if (usage == ExpUsage::Assignment) { 6195 if (usage == ExpUsage::Assignment) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 6aa0954..d138979 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -519,10 +519,7 @@ YueParser::YueParser() {
519 expo_exp = Value >> *(space >> expo_value); 519 expo_exp = Value >> *(space >> expo_value);
520 520
521 NotIn = true_(); 521 NotIn = true_();
522 InDiscrete = 522 In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (and_(key("not")) >> confusing_unary_not_error | Value);
523 '[' >> Seperator >> space >> exp_not_tab >> (+(space >> ',' >> space >> exp_not_tab) | space >> ',') >> space >> ']' |
524 '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab | space >> ',') >> space >> '}';
525 In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InDiscrete | and_(key("not")) >> confusing_unary_not_error | Exp);
526 523
527 UnaryOperator = 524 UnaryOperator =
528 '-' >> not_(set(">=") | space_one) | 525 '-' >> not_(set(">=") | space_one) |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 213d33e..39b7cce 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -402,7 +402,6 @@ private:
402 AST_RULE(UnaryValue); 402 AST_RULE(UnaryValue);
403 AST_RULE(UnaryExp); 403 AST_RULE(UnaryExp);
404 AST_RULE(NotIn); 404 AST_RULE(NotIn);
405 AST_RULE(InDiscrete);
406 AST_RULE(In); 405 AST_RULE(In);
407 AST_RULE(ExpListAssign); 406 AST_RULE(ExpListAssign);
408 AST_RULE(IfLine); 407 AST_RULE(IfLine);