diff options
author | Li Jin <dragon-fly@qq.com> | 2023-10-23 10:19:42 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2023-10-23 10:19:42 +0800 |
commit | 08fef1c7698cff09689e9965d993931ca6081257 (patch) | |
tree | 2d206d3b3b6cca927881a46873b53be3d0319221 /src/yuescript/yue_compiler.cpp | |
parent | 0ecd527e2b9e441c169bc66ecbac12d202b9d1f8 (diff) | |
download | yuescript-08fef1c7698cff09689e9965d993931ca6081257.tar.gz yuescript-08fef1c7698cff09689e9965d993931ca6081257.tar.bz2 yuescript-08fef1c7698cff09689e9965d993931ca6081257.zip |
fix chaining condition evaluation rules.v0.20.1
Diffstat (limited to '')
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 265 |
1 files changed, 164 insertions, 101 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index d32d9c1..7ec3b3a 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
75 | "close"s // Lua 5.4 | 75 | "close"s // Lua 5.4 |
76 | }; | 76 | }; |
77 | 77 | ||
78 | const std::string_view version = "0.20.0"sv; | 78 | const std::string_view version = "0.20.1"sv; |
79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
80 | 80 | ||
81 | class CompileError : public std::logic_error { | 81 | class CompileError : public std::logic_error { |
@@ -1207,19 +1207,16 @@ private: | |||
1207 | 1207 | ||
1208 | bool isConditionChaining(Exp_t* exp) { | 1208 | bool isConditionChaining(Exp_t* exp) { |
1209 | int conditionChaining = 0; | 1209 | int conditionChaining = 0; |
1210 | for (const auto& opValue_ : exp->opValues.objects()) { | 1210 | for (auto opValue_ : exp->opValues.objects()) { |
1211 | auto opValue = static_cast<ExpOpValue_t*>(opValue_); | 1211 | auto opValue = static_cast<ExpOpValue_t*>(opValue_); |
1212 | auto op = _parser.toString(opValue->op); | 1212 | auto op = _parser.toString(opValue->op); |
1213 | if (isConditionChainingOperator(op)) { | 1213 | if (isConditionChainingOperator(op)) { |
1214 | conditionChaining++; | 1214 | conditionChaining++; |
1215 | if (conditionChaining > 1) { | 1215 | } else if (conditionChaining > 0) { |
1216 | return true; | 1216 | return false; |
1217 | } | ||
1218 | } else { | ||
1219 | conditionChaining = 0; | ||
1220 | } | 1217 | } |
1221 | } | 1218 | } |
1222 | return false; | 1219 | return conditionChaining > 1 && conditionChaining == static_cast<int>(exp->opValues.size()); |
1223 | } | 1220 | } |
1224 | 1221 | ||
1225 | UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) { | 1222 | UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) { |
@@ -3369,14 +3366,14 @@ private: | |||
3369 | std::list<std::pair<std::string, ast_list<true, UnaryExp_t>*>> chains; | 3366 | std::list<std::pair<std::string, ast_list<true, UnaryExp_t>*>> chains; |
3370 | chains.emplace_back(std::string(), &exp->pipeExprs); | 3367 | chains.emplace_back(std::string(), &exp->pipeExprs); |
3371 | int conditionChainCount = 0; | 3368 | int conditionChainCount = 0; |
3372 | str_list evalLines; | 3369 | auto checkChains = [&]()-> ast_ptr<false, Exp_t> { |
3373 | auto checkChains = [&]() { | ||
3374 | std::optional<str_list> result; | 3370 | std::optional<str_list> result; |
3375 | if (conditionChainCount > 1) { | 3371 | if (conditionChainCount > 1) { |
3376 | bool needWrapping = false; | 3372 | ast_ptr<false, Exp_t> newCondExp; |
3377 | str_list conds; | 3373 | ast_ptr<false, ExpListAssign_t> preDefine; |
3378 | str_list preDefines; | 3374 | ast_sel_list<true, IfCond_t, Block_t, Statement_t>* nodes = nullptr; |
3379 | std::list<std::variant<std::string, ast_ptr<false, Exp_t>>> stack; | 3375 | std::list<std::variant<std::string, ast_list<true, UnaryExp_t>>> stack; |
3376 | pushScope(); | ||
3380 | for (const auto& item : chains) { | 3377 | for (const auto& item : chains) { |
3381 | if (!item.first.empty()) { | 3378 | if (!item.first.empty()) { |
3382 | stack.push_back(item.first); | 3379 | stack.push_back(item.first); |
@@ -3393,9 +3390,7 @@ private: | |||
3393 | if (varName.empty()) { | 3390 | if (varName.empty()) { |
3394 | if (auto sval = static_cast<Value_t*>(unary->expos.front())->item.as<SimpleValue_t>()) { | 3391 | if (auto sval = static_cast<Value_t*>(unary->expos.front())->item.as<SimpleValue_t>()) { |
3395 | if (ast_is<ConstValue_t, Num_t>(sval->value)) { | 3392 | if (ast_is<ConstValue_t, Num_t>(sval->value)) { |
3396 | auto condExp = unary->new_ptr<Exp_t>(); | 3393 | stack.push_back(*item.second); |
3397 | condExp->pipeExprs.dup(*item.second); | ||
3398 | stack.push_back(condExp); | ||
3399 | goto reduce; | 3394 | goto reduce; |
3400 | } | 3395 | } |
3401 | } | 3396 | } |
@@ -3404,77 +3399,125 @@ private: | |||
3404 | } | 3399 | } |
3405 | if (varName.empty() || !isLocal(varName)) { | 3400 | if (varName.empty() || !isLocal(varName)) { |
3406 | varName = getUnusedName("_cond_"sv); | 3401 | varName = getUnusedName("_cond_"sv); |
3402 | addToScope(varName); | ||
3407 | auto condExp = node->new_ptr<Exp_t>(); | 3403 | auto condExp = node->new_ptr<Exp_t>(); |
3408 | condExp->pipeExprs.dup(*item.second); | 3404 | condExp->pipeExprs.dup(*item.second); |
3409 | auto varExp = toAst<Exp_t>(varName, node); | 3405 | auto varExp = toAst<Exp_t>(varName, node); |
3410 | auto assignment = assignmentFrom(varExp, condExp, node); | 3406 | auto assignment = assignmentFrom(varExp, condExp, node); |
3411 | if (!needWrapping) { | 3407 | preDefine = assignment; |
3412 | needWrapping = true; | 3408 | stack.push_back(varExp->pipeExprs); |
3413 | if (usage == ExpUsage::Closure) { | ||
3414 | pushFunctionScope(); | ||
3415 | pushAnonVarArg(); | ||
3416 | pushScope(); | ||
3417 | } else if (usage == ExpUsage::Assignment) { | ||
3418 | pushScope(); | ||
3419 | } | ||
3420 | } | ||
3421 | transformAssignment(assignment, preDefines); | ||
3422 | stack.push_back(varExp); | ||
3423 | goto reduce; | 3409 | goto reduce; |
3424 | } | 3410 | } |
3425 | } | 3411 | } |
3426 | { | 3412 | { |
3427 | auto condExp = node->new_ptr<Exp_t>(); | 3413 | stack.push_back(*item.second); |
3428 | condExp->pipeExprs.dup(*item.second); | ||
3429 | stack.push_back(condExp); | ||
3430 | } | 3414 | } |
3431 | reduce: | 3415 | reduce: { |
3432 | if (stack.size() == 3) { | 3416 | if (stack.size() == 3) { |
3433 | str_list tmp; | 3417 | auto condExp = exp->new_ptr<Exp_t>(); |
3434 | auto one = std::get<ast_ptr<false, Exp_t>>(stack.front()).get(); | 3418 | const auto& one = std::get<ast_list<true, UnaryExp_t>>(stack.front()); |
3435 | transformExp(one, tmp, ExpUsage::Closure); | 3419 | condExp->pipeExprs.dup(one); |
3436 | stack.pop_front(); | 3420 | stack.pop_front(); |
3437 | auto two = std::get<std::string>(stack.front()); | 3421 | auto opValue = exp->new_ptr<ExpOpValue_t>(); |
3438 | tmp.push_back(two); | 3422 | const auto& two = std::get<std::string>(stack.front()); |
3423 | auto op = toAst<BinaryOperator_t>(two, exp); | ||
3424 | opValue->op.set(op); | ||
3439 | stack.pop_front(); | 3425 | stack.pop_front(); |
3440 | auto three = std::get<ast_ptr<false, Exp_t>>(stack.front()).get(); | 3426 | const auto& three = std::get<ast_list<true, UnaryExp_t>>(stack.front()); |
3441 | transformExp(three, tmp, ExpUsage::Closure); | 3427 | opValue->pipeExprs.dup(three); |
3442 | conds.push_back(join(tmp, " "sv)); | 3428 | condExp->opValues.push_back(opValue); |
3443 | } | 3429 | if (preDefine) { |
3444 | } | 3430 | auto ifNode = exp->new_ptr<If_t>(); |
3445 | auto condStr = join(conds, " and "sv); | 3431 | ifNode->type.set(toAst<IfType_t>("unless"sv, exp)); |
3446 | if (needWrapping && usage == ExpUsage::Closure) { | 3432 | auto ifCond = exp->new_ptr<IfCond_t>(); |
3447 | str_list closureLines{anonFuncStart() + nll(exp)}; | 3433 | ifCond->condition.set(condExp); |
3448 | closureLines.insert(closureLines.end(), preDefines.begin(), preDefines.end()); | 3434 | ifNode->nodes.push_back(ifCond); |
3449 | closureLines.push_back(indent() + "return "s + condStr + nll(exp)); | 3435 | ifNode->nodes.push_back(toAst<Statement_t>("false"sv, exp)); |
3450 | popScope(); | 3436 | if (newCondExp) { |
3451 | closureLines.push_back(indent() + anonFuncEnd()); | 3437 | if (nodes) { |
3452 | temp.push_back(join(closureLines)); | 3438 | auto block = exp->new_ptr<Block_t>(); |
3453 | popAnonVarArg(); | 3439 | auto stmt = exp->new_ptr<Statement_t>(); |
3454 | popFunctionScope(); | 3440 | stmt->content.set(preDefine); |
3455 | } else { | 3441 | preDefine.set(nullptr); |
3456 | temp.push_back(condStr); | 3442 | block->statements.push_back(stmt); |
3457 | if (!preDefines.empty()) { | 3443 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); |
3458 | evalLines.insert(evalLines.end(), preDefines.begin(), preDefines.end()); | 3444 | simpleValue->value.set(ifNode); |
3459 | if (usage == ExpUsage::Assignment) { | 3445 | auto explist = exp->new_ptr<ExpList_t>(); |
3460 | popScope(); | 3446 | explist->exprs.push_back(newExp(simpleValue, exp)); |
3447 | auto expListAssign = exp->new_ptr<ExpListAssign_t>(); | ||
3448 | expListAssign->expList.set(explist); | ||
3449 | stmt = exp->new_ptr<Statement_t>(); | ||
3450 | stmt->content.set(expListAssign); | ||
3451 | block->statements.push_back(stmt); | ||
3452 | nodes->push_back(block); | ||
3453 | nodes = &ifNode->nodes; | ||
3454 | } else { | ||
3455 | auto ifNodePrev = exp->new_ptr<If_t>(); | ||
3456 | ifNodePrev->type.set(toAst<IfType_t>("unless"sv, exp)); | ||
3457 | auto ifCondPrev = exp->new_ptr<IfCond_t>(); | ||
3458 | ifCondPrev->condition.set(newCondExp); | ||
3459 | ifNodePrev->nodes.push_back(ifCondPrev); | ||
3460 | ifNodePrev->nodes.push_back(toAst<Statement_t>("false", exp)); | ||
3461 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); | ||
3462 | simpleValue->value.set(ifNodePrev); | ||
3463 | newCondExp.set(newExp(simpleValue, exp)); | ||
3464 | nodes = &ifNodePrev->nodes; | ||
3465 | } | ||
3466 | } else { | ||
3467 | auto block = exp->new_ptr<Block_t>(); | ||
3468 | auto stmt = exp->new_ptr<Statement_t>(); | ||
3469 | stmt->content.set(preDefine); | ||
3470 | preDefine.set(nullptr); | ||
3471 | block->statements.push_back(stmt); | ||
3472 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); | ||
3473 | simpleValue->value.set(ifNode); | ||
3474 | auto explist = exp->new_ptr<ExpList_t>(); | ||
3475 | explist->exprs.push_back(newExp(simpleValue, exp)); | ||
3476 | auto expListAssign = exp->new_ptr<ExpListAssign_t>(); | ||
3477 | expListAssign->expList.set(explist); | ||
3478 | stmt = exp->new_ptr<Statement_t>(); | ||
3479 | stmt->content.set(expListAssign); | ||
3480 | block->statements.push_back(stmt); | ||
3481 | auto body = exp->new_ptr<Body_t>(); | ||
3482 | body->content.set(block); | ||
3483 | auto doNode = exp->new_ptr<Do_t>(); | ||
3484 | doNode->body.set(body); | ||
3485 | simpleValue = exp->new_ptr<SimpleValue_t>(); | ||
3486 | simpleValue->value.set(doNode); | ||
3487 | newCondExp.set(newExp(simpleValue, exp)); | ||
3488 | nodes = &ifNode->nodes; | ||
3489 | } | ||
3490 | } else { | ||
3491 | if (newCondExp) { | ||
3492 | if (nodes) { | ||
3493 | auto explist = exp->new_ptr<ExpList_t>(); | ||
3494 | explist->exprs.push_back(condExp); | ||
3495 | auto expListAssign = exp->new_ptr<ExpListAssign_t>(); | ||
3496 | expListAssign->expList.set(explist); | ||
3497 | auto stmt = exp->new_ptr<Statement_t>(); | ||
3498 | stmt->content.set(expListAssign); | ||
3499 | nodes->push_back(stmt); | ||
3500 | } else { | ||
3501 | auto opValue = exp->new_ptr<ExpOpValue_t>(); | ||
3502 | opValue->op.set(toAst<BinaryOperator_t>("and"sv, exp)); | ||
3503 | opValue->pipeExprs.dup(condExp->pipeExprs); | ||
3504 | newCondExp->opValues.push_back(opValue); | ||
3505 | newCondExp->opValues.dup(condExp->opValues); | ||
3506 | } | ||
3507 | } else { | ||
3508 | newCondExp.set(condExp); | ||
3509 | } | ||
3510 | } | ||
3461 | } | 3511 | } |
3462 | } | 3512 | } |
3463 | } | 3513 | } |
3464 | } else { | 3514 | popScope(); |
3465 | for (const auto& item : chains) { | 3515 | return newCondExp; |
3466 | if (!item.first.empty()) { | ||
3467 | temp.push_back(item.first); | ||
3468 | } | ||
3469 | transform_pipe_exp(item.second->objects(), temp, ExpUsage::Closure); | ||
3470 | } | ||
3471 | } | 3516 | } |
3472 | conditionChainCount = 0; | 3517 | return nullptr; |
3473 | chains.clear(); | ||
3474 | }; | 3518 | }; |
3475 | str_list preDefines; | 3519 | for (auto opValue_ : exp->opValues.objects()) { |
3476 | for (auto _opValue : exp->opValues.objects()) { | 3520 | auto opValue = static_cast<ExpOpValue_t*>(opValue_); |
3477 | auto opValue = static_cast<ExpOpValue_t*>(_opValue); | ||
3478 | transformBinaryOperator(opValue->op, temp); | 3521 | transformBinaryOperator(opValue->op, temp); |
3479 | auto op = temp.back(); | 3522 | auto op = temp.back(); |
3480 | temp.pop_back(); | 3523 | temp.pop_back(); |
@@ -3482,43 +3525,63 @@ private: | |||
3482 | conditionChainCount++; | 3525 | conditionChainCount++; |
3483 | chains.emplace_back(op, &opValue->pipeExprs); | 3526 | chains.emplace_back(op, &opValue->pipeExprs); |
3484 | } else { | 3527 | } else { |
3485 | checkChains(); | 3528 | if (auto e = checkChains()) { |
3529 | transformExp(e, temp, ExpUsage::Closure); | ||
3530 | } else { | ||
3531 | for (const auto& item : chains) { | ||
3532 | if (!item.first.empty()) { | ||
3533 | temp.push_back(item.first); | ||
3534 | } | ||
3535 | transform_pipe_exp(item.second->objects(), temp, ExpUsage::Closure); | ||
3536 | } | ||
3537 | } | ||
3538 | chains.clear(); | ||
3539 | conditionChainCount = 0; | ||
3486 | temp.push_back(op); | 3540 | temp.push_back(op); |
3487 | transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure); | 3541 | chains.emplace_back(Empty, &opValue->pipeExprs); |
3488 | } | 3542 | } |
3489 | } | 3543 | } |
3490 | checkChains(); | 3544 | if (auto e = checkChains()) { |
3491 | auto condStr = join(temp, " "sv); | 3545 | if (!temp.empty()) { |
3492 | switch (usage) { | 3546 | transformExp(e, temp, ExpUsage::Closure); |
3493 | case ExpUsage::Closure: { | 3547 | auto condStr = join(temp, " "sv); |
3494 | out.push_back(condStr); | 3548 | out.push_back(condStr); |
3495 | break; | 3549 | } else { |
3496 | } | 3550 | switch (usage) { |
3497 | case ExpUsage::Assignment: { | 3551 | case ExpUsage::Closure: |
3498 | auto assignment = exp->new_ptr<ExpListAssign_t>(); | 3552 | transformExp(e, out, ExpUsage::Closure); |
3499 | assignment->expList.set(assignList); | 3553 | break; |
3500 | auto assign = exp->new_ptr<Assign_t>(); | 3554 | case ExpUsage::Assignment: { |
3501 | assign->values.push_back(toAst<Exp_t>(condStr, exp)); | 3555 | auto assignment = exp->new_ptr<ExpListAssign_t>(); |
3502 | assignment->action.set(assign); | 3556 | assignment->expList.set(assignList); |
3503 | if (evalLines.empty()) { | 3557 | auto assign = exp->new_ptr<Assign_t>(); |
3504 | transformAssignment(assignment, out); | 3558 | assign->values.push_back(e); |
3505 | } else { | 3559 | assignment->action.set(assign); |
3506 | evalLines.push_front(indent() + "do"s + nll(exp)); | 3560 | transformAssignment(assignment, out); |
3507 | evalLines.push_front(getPreDefineLine(assignment)); | 3561 | break; |
3508 | pushScope(); | 3562 | } |
3509 | transformAssignment(assignment, evalLines); | 3563 | case ExpUsage::Return: { |
3510 | popScope(); | 3564 | auto expListLow = exp->new_ptr<ExpListLow_t>(); |
3511 | evalLines.push_back(indent() + "end"s + nlr(exp)); | 3565 | expListLow->exprs.push_back(e); |
3512 | out.push_back(join(evalLines)); | 3566 | auto returnNode = exp->new_ptr<Return_t>(); |
3567 | returnNode->valueList.set(expListLow); | ||
3568 | transformReturn(returnNode, out); | ||
3569 | break; | ||
3570 | } | ||
3571 | default: | ||
3572 | YUEE("invalid expression usage", exp); | ||
3573 | break; | ||
3513 | } | 3574 | } |
3514 | break; | ||
3515 | } | 3575 | } |
3516 | case ExpUsage::Return: { | 3576 | } else { |
3517 | evalLines.push_back(indent() + "return "s + condStr + nll(exp)); | 3577 | for (const auto& item : chains) { |
3518 | out.push_back(join(evalLines)); | 3578 | if (!item.first.empty()) { |
3519 | break; | 3579 | temp.push_back(item.first); |
3580 | } | ||
3581 | transform_pipe_exp(item.second->objects(), temp, ExpUsage::Closure); | ||
3520 | } | 3582 | } |
3521 | default: YUEE("invalid expression usage", exp); break; | 3583 | auto condStr = join(temp, " "sv); |
3584 | out.push_back(condStr); | ||
3522 | } | 3585 | } |
3523 | } | 3586 | } |
3524 | 3587 | ||