aboutsummaryrefslogtreecommitdiff
path: root/src/yuescript/yue_compiler.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2023-10-23 10:19:42 +0800
committerLi Jin <dragon-fly@qq.com>2023-10-23 10:19:42 +0800
commit08fef1c7698cff09689e9965d993931ca6081257 (patch)
tree2d206d3b3b6cca927881a46873b53be3d0319221 /src/yuescript/yue_compiler.cpp
parent0ecd527e2b9e441c169bc66ecbac12d202b9d1f8 (diff)
downloadyuescript-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.cpp265
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
78const std::string_view version = "0.20.0"sv; 78const std::string_view version = "0.20.1"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class 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