summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-04-22 18:00:20 +0800
committerLi Jin <dragon-fly@qq.com>2022-04-22 18:00:20 +0800
commit84b93d0e43e7248fd00df6957d55a954c48628d7 (patch)
treea8b9ff15c3de31f11b06e443c4d151dac67645b2 /src
parent53bd5a32e30493f4915e79bfb63b1eec846f1a7f (diff)
downloadyuescript-84b93d0e43e7248fd00df6957d55a954c48628d7.tar.gz
yuescript-84b93d0e43e7248fd00df6957d55a954c48628d7.tar.bz2
yuescript-84b93d0e43e7248fd00df6957d55a954c48628d7.zip
adding table spreading syntax.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/yuescript/yue_ast.h7
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp212
-rwxr-xr-xsrc/yuescript/yue_parser.cpp4
-rwxr-xr-xsrc/yuescript/yue_parser.h1
4 files changed, 209 insertions, 15 deletions
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index b5ceac1..ed6f7d2 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -605,10 +605,15 @@ AST_END(default_value)
605class default_pair_t; 605class default_pair_t;
606class meta_default_pair_t; 606class meta_default_pair_t;
607 607
608AST_NODE(SpreadExp)
609 ast_ptr<true, Exp_t> exp;
610 AST_MEMBER(SpreadExp, &exp)
611AST_END(SpreadExp)
612
608AST_NODE(TableLit) 613AST_NODE(TableLit)
609 ast_ptr<true, Seperator_t> sep; 614 ast_ptr<true, Seperator_t> sep;
610 ast_sel_list<false, 615 ast_sel_list<false,
611 variable_pair_t, normal_pair_t, Exp_t, default_pair_t, 616 variable_pair_t, normal_pair_t, SpreadExp_t, Exp_t, default_pair_t,
612 meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values; 617 meta_variable_pair_t, meta_normal_pair_t, meta_default_pair_t> values;
613 AST_MEMBER(TableLit, &sep, &values) 618 AST_MEMBER(TableLit, &sep, &values)
614AST_END(TableLit) 619AST_END(TableLit)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 17fbaf6..4fb14b6 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -60,7 +60,7 @@ using namespace parserlib;
60 60
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.10.12"sv; 63const std::string_view version = "0.10.14"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class YueCompilerImpl {
@@ -1353,6 +1353,16 @@ private:
1353 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); 1353 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment));
1354 return; 1354 return;
1355 } 1355 }
1356 case id<TableLit_t>(): {
1357 auto tableLit = static_cast<TableLit_t*>(value);
1358 if (hasSpreadExp(tableLit)) {
1359 auto expList = assignment->expList.get();
1360 std::string preDefine = getPredefine(assignment);
1361 transformTableLit(tableLit, out, true, ExpUsage::Assignment, expList);
1362 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment));
1363 return;
1364 }
1365 }
1356 } 1366 }
1357 auto exp = ast_cast<Exp_t>(value); 1367 auto exp = ast_cast<Exp_t>(value);
1358 BREAK_IF(!exp); 1368 BREAK_IF(!exp);
@@ -2665,7 +2675,7 @@ private:
2665 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;
2666 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;
2667 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;
2668 case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break; 2678 case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out, false, ExpUsage::Closure); break;
2669 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;
2670 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;
2671 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;
@@ -3274,6 +3284,13 @@ private:
3274 case id<If_t>(): 3284 case id<If_t>():
3275 transformIf(static_cast<If_t*>(value), out, ExpUsage::Return); 3285 transformIf(static_cast<If_t*>(value), out, ExpUsage::Return);
3276 return; 3286 return;
3287 case id<TableLit_t>(): {
3288 auto tableLit = static_cast<TableLit_t*>(value);
3289 if (hasSpreadExp(tableLit)) {
3290 transformTableLit(tableLit, out, true, ExpUsage::Return);
3291 return;
3292 }
3293 }
3277 } 3294 }
3278 } else if (auto chainValue = singleValue->item.as<ChainValue_t>()) { 3295 } else if (auto chainValue = singleValue->item.as<ChainValue_t>()) {
3279 if (specialChainValue(chainValue) != ChainType::Common) { 3296 if (specialChainValue(chainValue) != ChainType::Common) {
@@ -3834,6 +3851,12 @@ private:
3834 3851
3835 void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 3852 void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
3836 auto x = chainList.front(); 3853 auto x = chainList.front();
3854 if (chainList.size() > 1) {
3855 auto callable = ast_cast<Callable_t>(x);
3856 if (callable && callable->item.is<VarArg_t>()) {
3857 throw std::logic_error(_info.errorMessage("can not access variadic arguments directly"sv, x));
3858 }
3859 }
3837 str_list temp; 3860 str_list temp;
3838 switch (x->getId()) { 3861 switch (x->getId()) {
3839 case id<DotChainItem_t>(): 3862 case id<DotChainItem_t>():
@@ -4429,7 +4452,7 @@ private:
4429 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;
4430 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;
4431 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;
4432 case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(arg), temp); break; 4455 case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(arg), temp, false, ExpUsage::Closure); break;
4433 default: YUEE("AST node mismatch", arg); break; 4456 default: YUEE("AST node mismatch", arg); break;
4434 } 4457 }
4435 } 4458 }
@@ -4472,8 +4495,160 @@ private:
4472 out.push_back(_parser.toString(num)); 4495 out.push_back(_parser.toString(num));
4473 } 4496 }
4474 4497
4475 void transformTableLit(TableLit_t* table, str_list& out) { 4498 bool hasSpreadExp(TableLit_t* table) {
4476 transformTable(table, table->values.objects(), out); 4499 for (auto item : table->values.objects()) {
4500 if (ast_is<SpreadExp_t>(item)) return true;
4501 }
4502 return false;
4503 }
4504
4505 void transformTableLit(TableLit_t* table, str_list& out, bool spreading, ExpUsage usage, ExpList_t* assignList = nullptr) {
4506 if (spreading) {
4507 auto x = table;
4508 switch (usage) {
4509 case ExpUsage::Closure:
4510 _enableReturn.push(true);
4511 pushAnonVarArg();
4512 pushScope();
4513 break;
4514 case ExpUsage::Assignment:
4515 pushScope();
4516 break;
4517 default:
4518 break;
4519 }
4520 str_list temp;
4521 std::string tableVar = getUnusedName("_tab_"sv);
4522 forceAddToScope(tableVar);
4523 auto it = table->values.objects().begin();
4524 if (ast_is<SpreadExp_t>(*it)) {
4525 temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x));
4526 } else {
4527 auto initialTab = x->new_ptr<TableLit_t>();
4528 while (it != table->values.objects().end() && !ast_is<SpreadExp_t>(*it)) {
4529 initialTab->values.push_back(*it);
4530 ++it;
4531 }
4532 transformTableLit(initialTab, temp, false, ExpUsage::Closure);
4533 temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it);
4534 }
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 keyVar = getUnusedName("_key_"sv);
4541 std::string valueVar = getUnusedName("_value_"sv);
4542 auto targetStr = _parser.toString(spread->exp);
4543 _buf << "for "sv << keyVar << ',' << valueVar
4544 << " in pairs! do "sv
4545 << tableVar << '[' << keyVar << "]="sv << valueVar;
4546 auto forEach = toAst<ForEach_t>(clearBuf(), spread);
4547 auto chainValue = singleValueFrom(forEach->loopValue.to<ExpList_t>())->item.to<ChainValue_t>();
4548 ast_to<Invoke_t>(*(++chainValue->items.objects().begin()))->args.push_back(spread->exp);
4549 transformForEach(forEach, temp);
4550 break;
4551 }
4552 case id<variable_pair_t>(): {
4553 auto variablePair = static_cast<variable_pair_t*>(item);
4554 auto nameStr = _parser.toString(variablePair->name);
4555 auto assignment = toAst<ExpListAssign_t>(tableVar + '.' + nameStr + '=' + nameStr, item);
4556 transformAssignment(assignment, temp);
4557 break;
4558 }
4559 case id<normal_pair_t>(): {
4560 auto normalPair = static_cast<normal_pair_t*>(item);
4561 auto assignment = toAst<ExpListAssign_t>(tableVar + "=nil"s, item);
4562 auto chainValue = singleValueFrom(ast_to<Exp_t>(assignment->expList->exprs.front()))->item.to<ChainValue_t>();
4563 auto key = normalPair->key.get();
4564 switch (key->getId()) {
4565 case id<KeyName_t>(): {
4566 auto keyName = static_cast<KeyName_t*>(key);
4567 ast_ptr<false, ast_node> chainItem;
4568 if (auto name = keyName->name.as<Name_t>()) {
4569 auto dotItem = x->new_ptr<DotChainItem_t>();
4570 dotItem->name.set(name);
4571 chainItem = dotItem.get();
4572 } else {
4573 auto selfName = keyName->name.to<SelfName_t>();
4574 auto callable = x->new_ptr<Callable_t>();
4575 callable->item.set(selfName);
4576 auto chainValue = x->new_ptr<ChainValue_t>();
4577 chainValue->items.push_back(callable);
4578 auto value = x->new_ptr<Value_t>();
4579 value->item.set(chainValue);
4580 auto exp = newExp(value, key);
4581 chainItem = exp.get();
4582 }
4583 chainValue->items.push_back(chainItem);
4584 break;
4585 }
4586 case id<Exp_t>():
4587 chainValue->items.push_back(key);
4588 break;
4589 case id<DoubleString_t>():
4590 case id<SingleString_t>():
4591 case id<LuaString_t>(): {
4592 auto strNode = x->new_ptr<String_t>();
4593 strNode->str.set(key);
4594 chainValue->items.push_back(strNode);
4595 break;
4596 }
4597 default: YUEE("AST node mismatch", key); break;
4598 }
4599 auto assign = assignment->action.to<Assign_t>();
4600 assign->values.clear();
4601 assign->values.push_back(normalPair->value);
4602 transformAssignment(assignment, temp);
4603 break;
4604 }
4605 case id<Exp_t>(): {
4606 auto assignment = toAst<ExpListAssign_t>(tableVar + "[]=nil"s, item);
4607 auto assign = assignment->action.to<Assign_t>();
4608 assign->values.clear();
4609 assign->values.push_back(item);
4610 transformAssignment(assignment, temp);
4611 break;
4612 }
4613 default: YUEE("AST node mismatch", item); break;
4614 }
4615 }
4616 switch (usage) {
4617 case ExpUsage::Common:
4618 break;
4619 case ExpUsage::Closure: {
4620 out.push_back(join(temp));
4621 out.back().append(indent() + "return "s + tableVar + nlr(x));
4622 popScope();
4623 out.back().insert(0, anonFuncStart() + nll(x));
4624 out.back().append(indent() + anonFuncEnd());
4625 popAnonVarArg();
4626 _enableReturn.pop();
4627 break;
4628 }
4629 case ExpUsage::Assignment: {
4630 auto assign = x->new_ptr<Assign_t>();
4631 assign->values.push_back(toAst<Exp_t>(tableVar, x));
4632 auto assignment = x->new_ptr<ExpListAssign_t>();
4633 assignment->expList.set(assignList);
4634 assignment->action.set(assign);
4635 transformAssignment(assignment, temp);
4636 popScope();
4637 out.push_back(join(temp));
4638 out.back() = indent() + "do"s + nll(x) +
4639 out.back() + indent() + "end"s + nlr(x);
4640 break;
4641 }
4642 case ExpUsage::Return:
4643 out.push_back(join(temp));
4644 out.back().append(indent() + "return "s + tableVar + nlr(x));
4645 break;
4646 default:
4647 break;
4648 }
4649 } else {
4650 transformTable(table, table->values.objects(), out);
4651 }
4477 } 4652 }
4478 4653
4479 void transformCompCommon(Comprehension_t* comp, str_list& out) { 4654 void transformCompCommon(Comprehension_t* comp, str_list& out) {
@@ -5070,14 +5245,15 @@ private:
5070 out.push_back(name + " = "s + name); 5245 out.push_back(name + " = "s + name);
5071 } 5246 }
5072 5247
5073 void transform_normal_pair(normal_pair_t* pair, str_list& out) { 5248 void transform_normal_pair(normal_pair_t* pair, str_list& out, bool assignClass) {
5074 auto key = pair->key.get(); 5249 auto key = pair->key.get();
5075 str_list temp; 5250 str_list temp;
5076 switch (key->getId()) { 5251 switch (key->getId()) {
5077 case id<KeyName_t>(): { 5252 case id<KeyName_t>(): {
5078 transformKeyName(static_cast<KeyName_t*>(key), temp); 5253 auto keyName = static_cast<KeyName_t*>(key);
5079 if (LuaKeywords.find(temp.back()) != LuaKeywords.end()) { 5254 transformKeyName(keyName, temp);
5080 temp.back() = "[\""s + temp.back() + "\"]"s; 5255 if (keyName->name.is<SelfName_t>() && !assignClass) {
5256 temp.back() = '[' + temp.back() + ']';
5081 } 5257 }
5082 break; 5258 break;
5083 } 5259 }
@@ -5109,8 +5285,18 @@ private:
5109 void transformKeyName(KeyName_t* keyName, str_list& out) { 5285 void transformKeyName(KeyName_t* keyName, str_list& out) {
5110 auto name = keyName->name.get(); 5286 auto name = keyName->name.get();
5111 switch (name->getId()) { 5287 switch (name->getId()) {
5112 case id<SelfName_t>(): transformSelfName(static_cast<SelfName_t*>(name), out); break; 5288 case id<SelfName_t>():
5113 case id<Name_t>(): out.push_back(_parser.toString(name)); break; 5289 transformSelfName(static_cast<SelfName_t*>(name), out);
5290 break;
5291 case id<Name_t>(): {
5292 auto nameStr = _parser.toString(name);
5293 if (LuaKeywords.find(nameStr) != LuaKeywords.end()) {
5294 out.push_back("[\""s + nameStr + "\"]"s);
5295 } else {
5296 out.push_back(nameStr);
5297 }
5298 break;
5299 }
5114 default: YUEE("AST node mismatch", name); break; 5300 default: YUEE("AST node mismatch", name); break;
5115 } 5301 }
5116 } 5302 }
@@ -5531,7 +5717,7 @@ private:
5531 transform_variable_pair(static_cast<variable_pair_t*>(keyValue), temp); 5717 transform_variable_pair(static_cast<variable_pair_t*>(keyValue), temp);
5532 break; 5718 break;
5533 case id<normal_pair_t>(): 5719 case id<normal_pair_t>():
5534 transform_normal_pair(static_cast<normal_pair_t*>(keyValue), temp); 5720 transform_normal_pair(static_cast<normal_pair_t*>(keyValue), temp, true);
5535 break; 5721 break;
5536 default: YUEE("AST node mismatch", keyValue); break; 5722 default: YUEE("AST node mismatch", keyValue); break;
5537 } 5723 }
@@ -5876,7 +6062,7 @@ private:
5876 switch (pair->getId()) { 6062 switch (pair->getId()) {
5877 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(pair), temp, ExpUsage::Closure); break; 6063 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(pair), temp, ExpUsage::Closure); break;
5878 case id<variable_pair_t>(): transform_variable_pair(static_cast<variable_pair_t*>(pair), temp); break; 6064 case id<variable_pair_t>(): transform_variable_pair(static_cast<variable_pair_t*>(pair), temp); break;
5879 case id<normal_pair_t>(): transform_normal_pair(static_cast<normal_pair_t*>(pair), temp); break; 6065 case id<normal_pair_t>(): transform_normal_pair(static_cast<normal_pair_t*>(pair), temp, false); break;
5880 case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(pair), temp); break; 6066 case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(pair), temp); break;
5881 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(pair), temp); break; 6067 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(pair), temp); break;
5882 case id<meta_variable_pair_t>(): { 6068 case id<meta_variable_pair_t>(): {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index ab9b657..0c08d4f 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -469,7 +469,9 @@ YueParser::YueParser() {
469 and_(expr('[')) >> LuaString | 469 and_(expr('[')) >> LuaString |
470 and_(expr('{')) >> TableLit); 470 and_(expr('{')) >> TableLit);
471 471
472 TableValue = ((KeyValue | Exp) >> not_(sym('='))) | meta_default_pair | default_pair; 472 SpreadExp = sym("...") >> Exp;
473
474 TableValue = ((KeyValue | SpreadExp | Exp) >> not_(sym('='))) | meta_default_pair | default_pair;
473 475
474 table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); 476 table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(',');
475 477
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 6be8451..eeadaf6 100755
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -281,6 +281,7 @@ private:
281 AST_RULE(Invoke) 281 AST_RULE(Invoke)
282 AST_RULE(existential_op) 282 AST_RULE(existential_op)
283 AST_RULE(table_appending_op) 283 AST_RULE(table_appending_op)
284 AST_RULE(SpreadExp)
284 AST_RULE(TableLit) 285 AST_RULE(TableLit)
285 AST_RULE(TableBlock) 286 AST_RULE(TableBlock)
286 AST_RULE(TableBlockIndent) 287 AST_RULE(TableBlockIndent)