diff options
author | Li Jin <dragon-fly@qq.com> | 2024-02-05 11:24:41 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2024-02-05 11:24:41 +0800 |
commit | 018b9408f167067c596fc23781bc945edb9f4d89 (patch) | |
tree | 3e2aeff3b1750d6d4ad997e561da055d1ce6e4be | |
parent | ef0ff9c4c523980d71e49d65e8db57d670daf85c (diff) | |
download | yuescript-0.21.7.tar.gz yuescript-0.21.7.tar.bz2 yuescript-0.21.7.zip |
fix in-expression format issue.v0.21.7
-rw-r--r-- | spec/inputs/in_expression.yue | 1 | ||||
-rw-r--r-- | spec/inputs/unicode/in_expression.yue | 39 | ||||
-rw-r--r-- | spec/outputs/in_expression.lua | 4 | ||||
-rw-r--r-- | spec/outputs/unicode/in_expression.lua | 52 | ||||
-rw-r--r-- | src/yuescript/yue_ast.cpp | 9 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 11 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 291 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 5 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 1 |
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 | ||
4 | has = "foo" in { "bar", "foo" } | 3 | has = "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 | ||
32 | do | ||
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 | |||
32 | nil | 71 | nil |
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 |
4 | end)()) | 4 | end)()) |
5 | f((function() | ||
6 | local _val_0 = -a ^ 2 | ||
7 | return 1 == _val_0 or 2 == _val_0 or 3 == _val_0 | ||
8 | end)()) | ||
9 | local has | 5 | local has |
10 | do | 6 | do |
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) |
155 | end | 155 | end |
156 | do | ||
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 | ||
207 | end | ||
156 | return nil | 208 | return 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 | } |
1408 | std::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 | } | ||
1415 | std::string In_t::to_string(void* ud) const { | 1408 | std::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 | } |
1418 | std::string ExpListAssign_t::to_string(void* ud) const { | 1411 | std::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; | |||
81 | class NormalDef_t; | 81 | class NormalDef_t; |
82 | class SpreadListExp_t; | 82 | class SpreadListExp_t; |
83 | class Comprehension_t; | 83 | class Comprehension_t; |
84 | class Value_t; | ||
84 | } // namespace yue | 85 | } // namespace yue |
85 | 86 | ||
86 | AST_LEAF(Num) | 87 | AST_LEAF(Num) |
@@ -445,16 +446,10 @@ AST_END(UnaryOperator, "unary_op"sv) | |||
445 | AST_LEAF(NotIn) | 446 | AST_LEAF(NotIn) |
446 | AST_END(NotIn, "not_in"sv) | 447 | AST_END(NotIn, "not_in"sv) |
447 | 448 | ||
448 | AST_NODE(InDiscrete) | ||
449 | ast_ptr<true, Seperator_t> sep; | ||
450 | ast_list<true, Exp_t> values; | ||
451 | AST_MEMBER(InDiscrete, &sep, &values) | ||
452 | AST_END(InDiscrete, "in_discrete"sv) | ||
453 | |||
454 | AST_NODE(In) | 449 | AST_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, ¬_, &item) | 452 | AST_MEMBER(In, ¬_, &value) |
458 | AST_END(In, "in"sv) | 453 | AST_END(In, "in"sv) |
459 | 454 | ||
460 | AST_NODE(Assignable) | 455 | AST_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); |