diff options
| author | Li Jin <dragon-fly@qq.com> | 2023-06-30 18:48:20 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2023-06-30 18:48:20 +0800 |
| commit | 85a2da5cbbbbfb27f3b65ac67d083dd2443d223d (patch) | |
| tree | 25ab99912ebf9a26f5c11f09518b47509d750b36 /src | |
| parent | ef64f6d54bfc25c35e9d3044e324c9a3da7c2b94 (diff) | |
| download | yuescript-85a2da5cbbbbfb27f3b65ac67d083dd2443d223d.tar.gz yuescript-85a2da5cbbbbfb27f3b65ac67d083dd2443d223d.tar.bz2 yuescript-85a2da5cbbbbfb27f3b65ac67d083dd2443d223d.zip | |
support list table checking to in-expression for issue #140
Diffstat (limited to '')
| -rw-r--r-- | src/yuescript/yue_ast.h | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 104 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 12 |
3 files changed, 110 insertions, 8 deletions
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 85a1e52..807d01b 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -452,7 +452,7 @@ AST_END(InDiscrete, "in_discrete"sv) | |||
| 452 | 452 | ||
| 453 | AST_NODE(In) | 453 | AST_NODE(In) |
| 454 | ast_ptr<false, NotIn_t> not_; | 454 | ast_ptr<false, NotIn_t> not_; |
| 455 | ast_sel<true, InRange_t, InDiscrete_t> item; | 455 | ast_sel<true, InRange_t, InDiscrete_t, Exp_t> item; |
| 456 | AST_MEMBER(In, ¬_, &item) | 456 | AST_MEMBER(In, ¬_, &item) |
| 457 | AST_END(In, "in"sv) | 457 | AST_END(In, "in"sv) |
| 458 | 458 | ||
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index efd0aed..3dc8e19 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -72,7 +72,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 72 | "close"s // Lua 5.4 | 72 | "close"s // Lua 5.4 |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | const std::string_view version = "0.17.3"sv; | 75 | const std::string_view version = "0.17.4"sv; |
| 76 | const std::string_view extension = "yue"sv; | 76 | const std::string_view extension = "yue"sv; |
| 77 | 77 | ||
| 78 | class CompileError : public std::logic_error { | 78 | class CompileError : public std::logic_error { |
| @@ -5385,6 +5385,108 @@ private: | |||
| 5385 | varName.clear(); | 5385 | varName.clear(); |
| 5386 | } | 5386 | } |
| 5387 | } | 5387 | } |
| 5388 | if (auto inExp = unary_exp->inExp->item.as<Exp_t>()) { | ||
| 5389 | str_list temp; | ||
| 5390 | auto checkVar = singleVariableFrom(inExp, false); | ||
| 5391 | if (usage == ExpUsage::Assignment) { | ||
| 5392 | auto block = x->new_ptr<Block_t>(); | ||
| 5393 | if (checkVar.empty() || !isLocal(checkVar)) { | ||
| 5394 | checkVar = getUnusedName("_check_"sv); | ||
| 5395 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), inExp, inExp); | ||
| 5396 | auto stmt = x->new_ptr<Statement_t>(); | ||
| 5397 | stmt->content.set(assignment); | ||
| 5398 | block->statements.push_back(stmt); | ||
| 5399 | } | ||
| 5400 | if (varName.empty()) { | ||
| 5401 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); | ||
| 5402 | newUnaryExp->ops.dup(unary_exp->ops); | ||
| 5403 | newUnaryExp->expos.dup(unary_exp->expos); | ||
| 5404 | auto exp = newExp(newUnaryExp, x); | ||
| 5405 | varName = getUnusedName("_val_"sv); | ||
| 5406 | auto assignExp = toAst<Exp_t>(varName, x); | ||
| 5407 | auto assignment = assignmentFrom(assignExp, exp, x); | ||
| 5408 | auto stmt = x->new_ptr<Statement_t>(); | ||
| 5409 | stmt->content.set(assignment); | ||
| 5410 | block->statements.push_back(stmt); | ||
| 5411 | } | ||
| 5412 | auto findVar = getUnusedName("_find_"); | ||
| 5413 | auto itemVar = getUnusedName("_item_"); | ||
| 5414 | _buf << findVar << "=false\n"sv; | ||
| 5415 | _buf << "for "sv << itemVar << " in *"sv << checkVar << '\n'; | ||
| 5416 | _buf << "\tif "sv << itemVar << "=="sv << varName << '\n'; | ||
| 5417 | _buf << "\t\t"sv << findVar << "=true\n"sv; | ||
| 5418 | _buf << "\t\tbreak\n"sv; | ||
| 5419 | _buf << findVar; | ||
| 5420 | auto blockStr = clearBuf(); | ||
| 5421 | auto checkBlock = toAst<Block_t>(blockStr, inExp); | ||
| 5422 | block->statements.dup(checkBlock->statements); | ||
| 5423 | auto body = x->new_ptr<Body_t>(); | ||
| 5424 | body->content.set(block); | ||
| 5425 | auto doNode = x->new_ptr<Do_t>(); | ||
| 5426 | doNode->body.set(body); | ||
| 5427 | auto assign = x->new_ptr<Assign_t>(); | ||
| 5428 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 5429 | simpleValue->value.set(doNode); | ||
| 5430 | auto value = x->new_ptr<Value_t>(); | ||
| 5431 | value->item.set(simpleValue); | ||
| 5432 | assign->values.push_back(newExp(value, x)); | ||
| 5433 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 5434 | assignment->action.set(assign); | ||
| 5435 | assignment->expList.set(assignList); | ||
| 5436 | transformAssignment(assignment, temp); | ||
| 5437 | out.push_back(join(temp)); | ||
| 5438 | return; | ||
| 5439 | } else { | ||
| 5440 | pushFunctionScope(); | ||
| 5441 | pushAnonVarArg(); | ||
| 5442 | pushScope(); | ||
| 5443 | auto arrayCheck = [&]() { | ||
| 5444 | auto indexVar = getUnusedName("_index_"); | ||
| 5445 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x); | ||
| 5446 | incIndentOffset(); | ||
| 5447 | _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x); | ||
| 5448 | incIndentOffset(); | ||
| 5449 | _buf << indent() << "return true"sv << nll(x); | ||
| 5450 | decIndentOffset(); | ||
| 5451 | _buf << indent() << "end"sv << nll(x); | ||
| 5452 | decIndentOffset(); | ||
| 5453 | _buf << indent() << "end"sv << nll(x); | ||
| 5454 | _buf << indent() << "return false"sv << nll(x); | ||
| 5455 | temp.push_back(clearBuf()); | ||
| 5456 | }; | ||
| 5457 | bool useShortCheck = !varName.empty() && !checkVar.empty() && isLocal(checkVar); | ||
| 5458 | if (useShortCheck) { | ||
| 5459 | arrayCheck(); | ||
| 5460 | temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); | ||
| 5461 | popScope(); | ||
| 5462 | temp.push_back(indent() + anonFuncEnd() + ')'); | ||
| 5463 | } else { | ||
| 5464 | if (checkVar.empty() || !isLocal(checkVar)) { | ||
| 5465 | checkVar = getUnusedName("_check_"sv); | ||
| 5466 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), inExp, inExp); | ||
| 5467 | transformAssignment(assignment, temp); | ||
| 5468 | } | ||
| 5469 | if (varName.empty()) { | ||
| 5470 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); | ||
| 5471 | newUnaryExp->ops.dup(unary_exp->ops); | ||
| 5472 | newUnaryExp->expos.dup(unary_exp->expos); | ||
| 5473 | auto exp = newExp(newUnaryExp, x); | ||
| 5474 | varName = getUnusedName("_val_"sv); | ||
| 5475 | auto assignExp = toAst<Exp_t>(varName, x); | ||
| 5476 | auto assignment = assignmentFrom(assignExp, exp, x); | ||
| 5477 | transformAssignment(assignment, temp); | ||
| 5478 | } | ||
| 5479 | arrayCheck(); | ||
| 5480 | temp.push_front(anonFuncStart() + nll(x)); | ||
| 5481 | popScope(); | ||
| 5482 | temp.push_back(indent() + anonFuncEnd()); | ||
| 5483 | } | ||
| 5484 | popAnonVarArg(); | ||
| 5485 | popFunctionScope(); | ||
| 5486 | out.push_back(join(temp)); | ||
| 5487 | return; | ||
| 5488 | } | ||
| 5489 | } | ||
| 5388 | if (varName.empty()) { | 5490 | if (varName.empty()) { |
| 5389 | str_list temp; | 5491 | str_list temp; |
| 5390 | if (usage == ExpUsage::Closure) { | 5492 | if (usage == ExpUsage::Closure) { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index f72407d..294f1e5 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -317,18 +317,18 @@ YueParser::YueParser() { | |||
| 317 | with_exp = ExpList >> -(space >> Assign); | 317 | with_exp = ExpList >> -(space >> Assign); |
| 318 | 318 | ||
| 319 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 319 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); |
| 320 | SwitchCase = key("when") >> (disable_chain_rule(disable_arg_table_block_rule(SwitchList)) | space >> In) >> space >> body_with("then"); | 320 | SwitchCase = key("when") >> space >> (disable_chain_rule(disable_arg_table_block_rule(SwitchList)) | In) >> space >> body_with("then"); |
| 321 | switch_else = key("else") >> space >> body; | 321 | switch_else = key("else") >> space >> body; |
| 322 | 322 | ||
| 323 | switch_block = | 323 | switch_block = |
| 324 | *(line_break >> *space_break >> check_indent_match >> space >> SwitchCase) >> | 324 | *(line_break >> *space_break >> check_indent_match >> space >> SwitchCase) >> |
| 325 | -(line_break >> *space_break >> check_indent_match >> space >> switch_else); | 325 | -(line_break >> *space_break >> check_indent_match >> space >> switch_else); |
| 326 | 326 | ||
| 327 | exp_not_tab = not_(SimpleTable | TableLit) >> space >> Exp; | 327 | exp_not_tab = not_(SimpleTable | TableLit) >> Exp; |
| 328 | 328 | ||
| 329 | SwitchList = Seperator >> ( | 329 | SwitchList = Seperator >> ( |
| 330 | and_(SimpleTable | TableLit) >> space >> Exp | | 330 | and_(SimpleTable | TableLit) >> Exp | |
| 331 | exp_not_tab >> *(space >> ',' >> exp_not_tab) | 331 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) |
| 332 | ); | 332 | ); |
| 333 | Switch = key("switch") >> space >> Exp >> | 333 | Switch = key("switch") >> space >> Exp >> |
| 334 | space >> Seperator >> ( | 334 | space >> Seperator >> ( |
| @@ -458,8 +458,8 @@ YueParser::YueParser() { | |||
| 458 | InRangeClose = true_(); | 458 | InRangeClose = true_(); |
| 459 | NotIn = true_(); | 459 | NotIn = true_(); |
| 460 | InRange = ('(' >> InRangeOpen | '[' >> InRangeClose) >> space >> Exp >> space >> ',' >> space >> Exp >> space >> (')' >> InRangeOpen | ']' >> InRangeClose); | 460 | InRange = ('(' >> InRangeOpen | '[' >> InRangeClose) >> space >> Exp >> space >> ',' >> space >> Exp >> space >> (')' >> InRangeOpen | ']' >> InRangeClose); |
| 461 | InDiscrete = '{' >> Seperator >> space >> Exp >> *(space >> ',' >> space >> Exp) >> space >> '}'; | 461 | InDiscrete = '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) >> space >> '}'; |
| 462 | In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InRange | InDiscrete); | 462 | In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InRange | InDiscrete | Exp); |
| 463 | 463 | ||
| 464 | UnaryOperator = | 464 | UnaryOperator = |
| 465 | '-' >> not_(set(">=") | space_one) | | 465 | '-' >> not_(set(">=") | space_one) | |
