diff options
author | Li Jin <dragon-fly@qq.com> | 2022-04-24 15:35:53 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-04-24 15:35:53 +0800 |
commit | 249e1de1d32dda2b60b9116c5a4e538475de0192 (patch) | |
tree | d62b95ba79cd8b226fe2f8ae172bf646c12bff91 /src | |
parent | fe6d146bc4454d8096ddd0543d7142db3da5da5b (diff) | |
download | yuescript-249e1de1d32dda2b60b9116c5a4e538475de0192.tar.gz yuescript-249e1de1d32dda2b60b9116c5a4e538475de0192.tar.bz2 yuescript-249e1de1d32dda2b60b9116c5a4e538475de0192.zip |
add support for the Fill Operator. fix issue #39.
Diffstat (limited to 'src')
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 326 |
1 files changed, 168 insertions, 158 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 4dacf42..6a0fba6 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -1358,7 +1358,7 @@ private: | |||
1358 | if (hasSpreadExp(tableLit)) { | 1358 | if (hasSpreadExp(tableLit)) { |
1359 | auto expList = assignment->expList.get(); | 1359 | auto expList = assignment->expList.get(); |
1360 | std::string preDefine = getPredefine(assignment); | 1360 | std::string preDefine = getPredefine(assignment); |
1361 | transformTableLit(tableLit, out, true, ExpUsage::Assignment, expList); | 1361 | transformSpreadTableLit(tableLit, out, ExpUsage::Assignment, expList); |
1362 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); | 1362 | out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); |
1363 | return; | 1363 | return; |
1364 | } | 1364 | } |
@@ -2675,7 +2675,7 @@ private: | |||
2675 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; | 2675 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; |
2676 | case id<unary_value_t>(): transform_unary_value(static_cast<unary_value_t*>(value), out); break; | 2676 | case id<unary_value_t>(): transform_unary_value(static_cast<unary_value_t*>(value), out); break; |
2677 | case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; | 2677 | case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; |
2678 | case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out, false, ExpUsage::Closure); break; | 2678 | case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break; |
2679 | case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; | 2679 | case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; |
2680 | case id<FunLit_t>(): transformFunLit(static_cast<FunLit_t*>(value), out); break; | 2680 | case id<FunLit_t>(): transformFunLit(static_cast<FunLit_t*>(value), out); break; |
2681 | case id<Num_t>(): transformNum(static_cast<Num_t*>(value), out); break; | 2681 | case id<Num_t>(): transformNum(static_cast<Num_t*>(value), out); break; |
@@ -3287,7 +3287,7 @@ private: | |||
3287 | case id<TableLit_t>(): { | 3287 | case id<TableLit_t>(): { |
3288 | auto tableLit = static_cast<TableLit_t*>(value); | 3288 | auto tableLit = static_cast<TableLit_t*>(value); |
3289 | if (hasSpreadExp(tableLit)) { | 3289 | if (hasSpreadExp(tableLit)) { |
3290 | transformTableLit(tableLit, out, true, ExpUsage::Return); | 3290 | transformSpreadTableLit(tableLit, out, ExpUsage::Return); |
3291 | return; | 3291 | return; |
3292 | } | 3292 | } |
3293 | } | 3293 | } |
@@ -4452,7 +4452,7 @@ private: | |||
4452 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(arg), temp); break; | 4452 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(arg), temp); break; |
4453 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(arg), temp); break; | 4453 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(arg), temp); break; |
4454 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(arg), temp); break; | 4454 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(arg), temp); break; |
4455 | case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(arg), temp, false, ExpUsage::Closure); break; | 4455 | case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(arg), temp); break; |
4456 | default: YUEE("AST node mismatch", arg); break; | 4456 | default: YUEE("AST node mismatch", arg); break; |
4457 | } | 4457 | } |
4458 | } | 4458 | } |
@@ -4502,173 +4502,183 @@ private: | |||
4502 | return false; | 4502 | return false; |
4503 | } | 4503 | } |
4504 | 4504 | ||
4505 | void transformTableLit(TableLit_t* table, str_list& out, bool spreading, ExpUsage usage, ExpList_t* assignList = nullptr) { | 4505 | void transformTableLit(TableLit_t* table, str_list& out) { |
4506 | if (spreading) { | 4506 | if (hasSpreadExp(table)) { |
4507 | auto x = table; | 4507 | transformSpreadTableLit(table, out, ExpUsage::Closure); |
4508 | switch (usage) { | 4508 | } else { |
4509 | case ExpUsage::Closure: | 4509 | transformTable(table, table->values.objects(), out); |
4510 | _enableReturn.push(true); | 4510 | } |
4511 | pushAnonVarArg(); | 4511 | } |
4512 | pushScope(); | 4512 | |
4513 | break; | 4513 | void transformSpreadTableLit(TableLit_t* table, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
4514 | case ExpUsage::Assignment: | 4514 | auto x = table; |
4515 | pushScope(); | 4515 | switch (usage) { |
4516 | break; | 4516 | case ExpUsage::Closure: |
4517 | default: | 4517 | _enableReturn.push(true); |
4518 | break; | 4518 | pushAnonVarArg(); |
4519 | pushScope(); | ||
4520 | break; | ||
4521 | case ExpUsage::Assignment: | ||
4522 | pushScope(); | ||
4523 | break; | ||
4524 | default: | ||
4525 | break; | ||
4526 | } | ||
4527 | str_list temp; | ||
4528 | std::string tableVar = getUnusedName("_tab_"sv); | ||
4529 | forceAddToScope(tableVar); | ||
4530 | auto it = table->values.objects().begin(); | ||
4531 | if (ast_is<SpreadExp_t>(*it)) { | ||
4532 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | ||
4533 | } else { | ||
4534 | auto initialTab = x->new_ptr<TableLit_t>(); | ||
4535 | while (it != table->values.objects().end() && !ast_is<SpreadExp_t>(*it)) { | ||
4536 | initialTab->values.push_back(*it); | ||
4537 | ++it; | ||
4519 | } | 4538 | } |
4520 | str_list temp; | 4539 | transformTable(table, initialTab->values.objects(), temp); |
4521 | std::string tableVar = getUnusedName("_tab_"sv); | 4540 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it); |
4522 | forceAddToScope(tableVar); | 4541 | } |
4523 | auto it = table->values.objects().begin(); | 4542 | for (; it != table->values.objects().end(); ++it) { |
4524 | if (ast_is<SpreadExp_t>(*it)) { | 4543 | auto item = *it; |
4525 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | 4544 | switch (item->getId()) { |
4526 | } else { | 4545 | case id<SpreadExp_t>(): { |
4527 | auto initialTab = x->new_ptr<TableLit_t>(); | 4546 | auto spread = static_cast<SpreadExp_t*>(item); |
4528 | while (it != table->values.objects().end() && !ast_is<SpreadExp_t>(*it)) { | 4547 | std::string indexVar = getUnusedName("_idx_"sv); |
4529 | initialTab->values.push_back(*it); | 4548 | std::string keyVar = getUnusedName("_key_"sv); |
4530 | ++it; | 4549 | std::string valueVar = getUnusedName("_value_"sv); |
4531 | } | 4550 | auto objVar = singleVariableFrom(spread->exp); |
4532 | transformTableLit(initialTab, temp, false, ExpUsage::Closure); | 4551 | if (objVar.empty()) { |
4533 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it); | 4552 | objVar = getUnusedName("_obj_"); |
4534 | } | 4553 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); |
4535 | for (; it != table->values.objects().end(); ++it) { | ||
4536 | auto item = *it; | ||
4537 | switch (item->getId()) { | ||
4538 | case id<SpreadExp_t>(): { | ||
4539 | auto spread = static_cast<SpreadExp_t*>(item); | ||
4540 | std::string valueVar = getUnusedName("_value_"sv); | ||
4541 | auto objVar = singleVariableFrom(spread->exp); | ||
4542 | if (objVar.empty()) { | ||
4543 | objVar = getUnusedName("_obj_"); | ||
4544 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, spread); | ||
4545 | auto assign = assignment->action.to<Assign_t>(); | ||
4546 | assign->values.clear(); | ||
4547 | assign->values.push_back(spread->exp); | ||
4548 | transformAssignment(assignment, temp); | ||
4549 | } | ||
4550 | _buf << "for "sv << valueVar | ||
4551 | << " in *"sv << objVar << " do "sv | ||
4552 | << tableVar << "[]="sv << valueVar; | ||
4553 | auto forEach = toAst<ForEach_t>(clearBuf(), spread); | ||
4554 | transformForEach(forEach, temp); | ||
4555 | break; | ||
4556 | } | ||
4557 | case id<variable_pair_t>(): { | ||
4558 | auto variablePair = static_cast<variable_pair_t*>(item); | ||
4559 | auto nameStr = _parser.toString(variablePair->name); | ||
4560 | auto assignment = toAst<ExpListAssign_t>(tableVar + '.' + nameStr + '=' + nameStr, item); | ||
4561 | transformAssignment(assignment, temp); | ||
4562 | break; | ||
4563 | } | ||
4564 | case id<normal_pair_t>(): { | ||
4565 | auto normalPair = static_cast<normal_pair_t*>(item); | ||
4566 | auto assignment = toAst<ExpListAssign_t>(tableVar + "=nil"s, item); | ||
4567 | auto chainValue = singleValueFrom(ast_to<Exp_t>(assignment->expList->exprs.front()))->item.to<ChainValue_t>(); | ||
4568 | auto key = normalPair->key.get(); | ||
4569 | switch (key->getId()) { | ||
4570 | case id<KeyName_t>(): { | ||
4571 | auto keyName = static_cast<KeyName_t*>(key); | ||
4572 | ast_ptr<false, ast_node> chainItem; | ||
4573 | if (auto name = keyName->name.as<Name_t>()) { | ||
4574 | auto dotItem = x->new_ptr<DotChainItem_t>(); | ||
4575 | dotItem->name.set(name); | ||
4576 | chainItem = dotItem.get(); | ||
4577 | } else { | ||
4578 | auto selfName = keyName->name.to<SelfName_t>(); | ||
4579 | auto callable = x->new_ptr<Callable_t>(); | ||
4580 | callable->item.set(selfName); | ||
4581 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
4582 | chainValue->items.push_back(callable); | ||
4583 | auto value = x->new_ptr<Value_t>(); | ||
4584 | value->item.set(chainValue); | ||
4585 | auto exp = newExp(value, key); | ||
4586 | chainItem = exp.get(); | ||
4587 | } | ||
4588 | chainValue->items.push_back(chainItem); | ||
4589 | break; | ||
4590 | } | ||
4591 | case id<Exp_t>(): | ||
4592 | chainValue->items.push_back(key); | ||
4593 | break; | ||
4594 | case id<DoubleString_t>(): | ||
4595 | case id<SingleString_t>(): | ||
4596 | case id<LuaString_t>(): { | ||
4597 | auto strNode = x->new_ptr<String_t>(); | ||
4598 | strNode->str.set(key); | ||
4599 | chainValue->items.push_back(strNode); | ||
4600 | break; | ||
4601 | } | ||
4602 | default: YUEE("AST node mismatch", key); break; | ||
4603 | } | ||
4604 | auto assign = assignment->action.to<Assign_t>(); | 4554 | auto assign = assignment->action.to<Assign_t>(); |
4605 | assign->values.clear(); | 4555 | assign->values.clear(); |
4606 | assign->values.push_back(normalPair->value); | 4556 | assign->values.push_back(spread->exp); |
4607 | transformAssignment(assignment, temp); | 4557 | transformAssignment(assignment, temp); |
4608 | break; | ||
4609 | } | ||
4610 | case id<Exp_t>(): { | ||
4611 | bool lastVarArg = false; | ||
4612 | BLOCK_START | ||
4613 | BREAK_IF(item != table->values.back()); | ||
4614 | auto value = singleValueFrom(item); | ||
4615 | BREAK_IF(!value); | ||
4616 | auto chainValue = value->item.as<ChainValue_t>(); | ||
4617 | BREAK_IF(!chainValue); | ||
4618 | BREAK_IF(chainValue->items.size() != 1); | ||
4619 | BREAK_IF((!chainValue->getByPath<Callable_t,VarArg_t>())); | ||
4620 | auto indexVar = getUnusedName("_index_"); | ||
4621 | _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv; | ||
4622 | transformFor(toAst<For_t>(clearBuf(), item), temp); | ||
4623 | lastVarArg = true; | ||
4624 | BLOCK_END | ||
4625 | if (!lastVarArg) { | ||
4626 | auto assignment = toAst<ExpListAssign_t>(tableVar + "[]=nil"s, item); | ||
4627 | auto assign = assignment->action.to<Assign_t>(); | ||
4628 | assign->values.clear(); | ||
4629 | assign->values.push_back(item); | ||
4630 | transformAssignment(assignment, temp); | ||
4631 | } | ||
4632 | break; | ||
4633 | } | 4558 | } |
4634 | default: YUEE("AST node mismatch", item); break; | 4559 | forceAddToScope(indexVar); |
4635 | } | 4560 | temp.push_back(indent() + "local "s + indexVar + " = 1"s + nll(item)); |
4636 | } | 4561 | _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar |
4637 | switch (usage) { | 4562 | << "\n\tif "sv << indexVar << "=="sv << keyVar |
4638 | case ExpUsage::Common: | 4563 | << "\n\t\t"sv << tableVar << "[]="sv << valueVar |
4639 | break; | 4564 | << "\n\t\t"sv << indexVar << "+=1"sv |
4640 | case ExpUsage::Closure: { | 4565 | << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; |
4641 | out.push_back(join(temp)); | 4566 | auto forEach = toAst<ForEach_t>(clearBuf(), item); |
4642 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | 4567 | transformForEach(forEach, temp); |
4643 | popScope(); | ||
4644 | out.back().insert(0, anonFuncStart() + nll(x)); | ||
4645 | out.back().append(indent() + anonFuncEnd()); | ||
4646 | popAnonVarArg(); | ||
4647 | _enableReturn.pop(); | ||
4648 | break; | 4568 | break; |
4649 | } | 4569 | } |
4650 | case ExpUsage::Assignment: { | 4570 | case id<variable_pair_t>(): { |
4651 | auto assign = x->new_ptr<Assign_t>(); | 4571 | auto variablePair = static_cast<variable_pair_t*>(item); |
4652 | assign->values.push_back(toAst<Exp_t>(tableVar, x)); | 4572 | auto nameStr = _parser.toString(variablePair->name); |
4653 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4573 | auto assignment = toAst<ExpListAssign_t>(tableVar + '.' + nameStr + '=' + nameStr, item); |
4654 | assignment->expList.set(assignList); | ||
4655 | assignment->action.set(assign); | ||
4656 | transformAssignment(assignment, temp); | 4574 | transformAssignment(assignment, temp); |
4657 | popScope(); | ||
4658 | out.push_back(join(temp)); | ||
4659 | out.back() = indent() + "do"s + nll(x) + | ||
4660 | out.back() + indent() + "end"s + nlr(x); | ||
4661 | break; | 4575 | break; |
4662 | } | 4576 | } |
4663 | case ExpUsage::Return: | 4577 | case id<normal_pair_t>(): { |
4664 | out.push_back(join(temp)); | 4578 | auto normalPair = static_cast<normal_pair_t*>(item); |
4665 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | 4579 | auto assignment = toAst<ExpListAssign_t>(tableVar + "=nil"s, item); |
4580 | auto chainValue = singleValueFrom(ast_to<Exp_t>(assignment->expList->exprs.front()))->item.to<ChainValue_t>(); | ||
4581 | auto key = normalPair->key.get(); | ||
4582 | switch (key->getId()) { | ||
4583 | case id<KeyName_t>(): { | ||
4584 | auto keyName = static_cast<KeyName_t*>(key); | ||
4585 | ast_ptr<false, ast_node> chainItem; | ||
4586 | if (auto name = keyName->name.as<Name_t>()) { | ||
4587 | auto dotItem = x->new_ptr<DotChainItem_t>(); | ||
4588 | dotItem->name.set(name); | ||
4589 | chainItem = dotItem.get(); | ||
4590 | } else { | ||
4591 | auto selfName = keyName->name.to<SelfName_t>(); | ||
4592 | auto callable = x->new_ptr<Callable_t>(); | ||
4593 | callable->item.set(selfName); | ||
4594 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
4595 | chainValue->items.push_back(callable); | ||
4596 | auto value = x->new_ptr<Value_t>(); | ||
4597 | value->item.set(chainValue); | ||
4598 | auto exp = newExp(value, key); | ||
4599 | chainItem = exp.get(); | ||
4600 | } | ||
4601 | chainValue->items.push_back(chainItem); | ||
4602 | break; | ||
4603 | } | ||
4604 | case id<Exp_t>(): | ||
4605 | chainValue->items.push_back(key); | ||
4606 | break; | ||
4607 | case id<DoubleString_t>(): | ||
4608 | case id<SingleString_t>(): | ||
4609 | case id<LuaString_t>(): { | ||
4610 | auto strNode = x->new_ptr<String_t>(); | ||
4611 | strNode->str.set(key); | ||
4612 | chainValue->items.push_back(strNode); | ||
4613 | break; | ||
4614 | } | ||
4615 | default: YUEE("AST node mismatch", key); break; | ||
4616 | } | ||
4617 | auto assign = assignment->action.to<Assign_t>(); | ||
4618 | assign->values.clear(); | ||
4619 | assign->values.push_back(normalPair->value); | ||
4620 | transformAssignment(assignment, temp); | ||
4666 | break; | 4621 | break; |
4667 | default: | 4622 | } |
4623 | case id<Exp_t>(): { | ||
4624 | bool lastVarArg = false; | ||
4625 | BLOCK_START | ||
4626 | BREAK_IF(item != table->values.back()); | ||
4627 | auto value = singleValueFrom(item); | ||
4628 | BREAK_IF(!value); | ||
4629 | auto chainValue = value->item.as<ChainValue_t>(); | ||
4630 | BREAK_IF(!chainValue); | ||
4631 | BREAK_IF(chainValue->items.size() != 1); | ||
4632 | BREAK_IF((!chainValue->getByPath<Callable_t,VarArg_t>())); | ||
4633 | auto indexVar = getUnusedName("_index_"); | ||
4634 | _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv; | ||
4635 | transformFor(toAst<For_t>(clearBuf(), item), temp); | ||
4636 | lastVarArg = true; | ||
4637 | BLOCK_END | ||
4638 | if (!lastVarArg) { | ||
4639 | auto assignment = toAst<ExpListAssign_t>(tableVar + "[]=nil"s, item); | ||
4640 | auto assign = assignment->action.to<Assign_t>(); | ||
4641 | assign->values.clear(); | ||
4642 | assign->values.push_back(item); | ||
4643 | transformAssignment(assignment, temp); | ||
4644 | } | ||
4668 | break; | 4645 | break; |
4646 | } | ||
4647 | default: YUEE("AST node mismatch", item); break; | ||
4669 | } | 4648 | } |
4670 | } else { | 4649 | } |
4671 | transformTable(table, table->values.objects(), out); | 4650 | switch (usage) { |
4651 | case ExpUsage::Common: | ||
4652 | break; | ||
4653 | case ExpUsage::Closure: { | ||
4654 | out.push_back(join(temp)); | ||
4655 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | ||
4656 | popScope(); | ||
4657 | out.back().insert(0, anonFuncStart() + nll(x)); | ||
4658 | out.back().append(indent() + anonFuncEnd()); | ||
4659 | popAnonVarArg(); | ||
4660 | _enableReturn.pop(); | ||
4661 | break; | ||
4662 | } | ||
4663 | case ExpUsage::Assignment: { | ||
4664 | auto assign = x->new_ptr<Assign_t>(); | ||
4665 | assign->values.push_back(toAst<Exp_t>(tableVar, x)); | ||
4666 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
4667 | assignment->expList.set(assignList); | ||
4668 | assignment->action.set(assign); | ||
4669 | transformAssignment(assignment, temp); | ||
4670 | popScope(); | ||
4671 | out.push_back(join(temp)); | ||
4672 | out.back() = indent() + "do"s + nll(x) + | ||
4673 | out.back() + indent() + "end"s + nlr(x); | ||
4674 | break; | ||
4675 | } | ||
4676 | case ExpUsage::Return: | ||
4677 | out.push_back(join(temp)); | ||
4678 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | ||
4679 | break; | ||
4680 | default: | ||
4681 | break; | ||
4672 | } | 4682 | } |
4673 | } | 4683 | } |
4674 | 4684 | ||