diff options
-rw-r--r-- | spec/inputs/tables.yue | 19 | ||||
-rw-r--r-- | spec/outputs/tables.lua | 127 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 326 |
3 files changed, 289 insertions, 183 deletions
diff --git a/spec/inputs/tables.yue b/spec/inputs/tables.yue index 649c1dc..3a245a7 100644 --- a/spec/inputs/tables.yue +++ b/spec/inputs/tables.yue | |||
@@ -262,5 +262,24 @@ tbMixB = { | |||
262 | 1, 2, 3 | 262 | 1, 2, 3 |
263 | } | 263 | } |
264 | 264 | ||
265 | const template = { | ||
266 | foo: "Hello" | ||
267 | bar: "World" | ||
268 | baz: "!" | ||
269 | } | ||
270 | |||
271 | const specialized = { | ||
272 | ...template | ||
273 | bar: "Bob" | ||
274 | } | ||
275 | |||
276 | specializedB = { | ||
277 | function: -> | ||
278 | ...template | ||
279 | end: -> | ||
280 | if: true | ||
281 | else: false | ||
282 | } | ||
283 | |||
265 | nil | 284 | nil |
266 | 285 | ||
diff --git a/spec/outputs/tables.lua b/spec/outputs/tables.lua index b820122..165706d 100644 --- a/spec/outputs/tables.lua +++ b/spec/outputs/tables.lua | |||
@@ -351,10 +351,14 @@ local menus = { | |||
351 | local tb | 351 | local tb |
352 | do | 352 | do |
353 | local _tab_0 = { } | 353 | local _tab_0 = { } |
354 | local _list_0 = other | 354 | local _idx_0 = 1 |
355 | for _index_0 = 1, #_list_0 do | 355 | for _key_0, _value_0 in pairs(other) do |
356 | local _value_0 = _list_0[_index_0] | 356 | if _idx_0 == _key_0 then |
357 | _tab_0[#_tab_0 + 1] = _value_0 | 357 | _tab_0[#_tab_0 + 1] = _value_0 |
358 | _idx_0 = _idx_0 + 1 | ||
359 | else | ||
360 | _tab_0[_key_0] = _value_0 | ||
361 | end | ||
358 | end | 362 | end |
359 | tb = _tab_0 | 363 | tb = _tab_0 |
360 | end | 364 | end |
@@ -372,9 +376,14 @@ do | |||
372 | _with_0:func() | 376 | _with_0:func() |
373 | _obj_0 = _with_0 | 377 | _obj_0 = _with_0 |
374 | end | 378 | end |
375 | for _index_0 = 1, #_obj_0 do | 379 | local _idx_0 = 1 |
376 | local _value_0 = _obj_0[_index_0] | 380 | for _key_0, _value_0 in pairs(_obj_0) do |
377 | _tab_0[#_tab_0 + 1] = _value_0 | 381 | if _idx_0 == _key_0 then |
382 | _tab_0[#_tab_0 + 1] = _value_0 | ||
383 | _idx_0 = _idx_0 + 1 | ||
384 | else | ||
385 | _tab_0[_key_0] = _value_0 | ||
386 | end | ||
378 | end | 387 | end |
379 | _tab_0[#_tab_0 + 1] = "a" | 388 | _tab_0[#_tab_0 + 1] = "a" |
380 | _tab_0[#_tab_0 + 1] = "b" | 389 | _tab_0[#_tab_0 + 1] = "b" |
@@ -386,9 +395,14 @@ do | |||
386 | _obj_1 = _obj_2() | 395 | _obj_1 = _obj_2() |
387 | end | 396 | end |
388 | end | 397 | end |
389 | for _index_0 = 1, #_obj_1 do | 398 | local _idx_1 = 1 |
390 | local _value_0 = _obj_1[_index_0] | 399 | for _key_0, _value_0 in pairs(_obj_1) do |
391 | _tab_0[#_tab_0 + 1] = _value_0 | 400 | if _idx_1 == _key_0 then |
401 | _tab_0[#_tab_0 + 1] = _value_0 | ||
402 | _idx_1 = _idx_1 + 1 | ||
403 | else | ||
404 | _tab_0[_key_0] = _value_0 | ||
405 | end | ||
392 | end | 406 | end |
393 | _tab_0.key = "value" | 407 | _tab_0.key = "value" |
394 | for _index_0 = 1, select('#', ...) do | 408 | for _index_0 = 1, select('#', ...) do |
@@ -409,9 +423,14 @@ do | |||
409 | end | 423 | end |
410 | _obj_0 = _accum_0 | 424 | _obj_0 = _accum_0 |
411 | end | 425 | end |
412 | for _index_0 = 1, #_obj_0 do | 426 | local _idx_0 = 1 |
413 | local _value_0 = _obj_0[_index_0] | 427 | for _key_0, _value_0 in pairs(_obj_0) do |
414 | _tab_0[#_tab_0 + 1] = _value_0 | 428 | if _idx_0 == _key_0 then |
429 | _tab_0[#_tab_0 + 1] = _value_0 | ||
430 | _idx_0 = _idx_0 + 1 | ||
431 | else | ||
432 | _tab_0[_key_0] = _value_0 | ||
433 | end | ||
415 | end | 434 | end |
416 | _tab_0[#_tab_0 + 1] = 11 | 435 | _tab_0[#_tab_0 + 1] = 11 |
417 | tbMixA = _tab_0 | 436 | tbMixA = _tab_0 |
@@ -420,34 +439,92 @@ local tbMixB | |||
420 | do | 439 | do |
421 | local _tab_0 = { } | 440 | local _tab_0 = { } |
422 | local _obj_0 = ... | 441 | local _obj_0 = ... |
423 | for _index_0 = 1, #_obj_0 do | 442 | local _idx_0 = 1 |
424 | local _value_0 = _obj_0[_index_0] | 443 | for _key_0, _value_0 in pairs(_obj_0) do |
425 | _tab_0[#_tab_0 + 1] = _value_0 | 444 | if _idx_0 == _key_0 then |
445 | _tab_0[#_tab_0 + 1] = _value_0 | ||
446 | _idx_0 = _idx_0 + 1 | ||
447 | else | ||
448 | _tab_0[_key_0] = _value_0 | ||
449 | end | ||
426 | end | 450 | end |
427 | local _obj_1 = { | 451 | local _obj_1 = { |
428 | ... | 452 | ... |
429 | } | 453 | } |
430 | for _index_0 = 1, #_obj_1 do | 454 | local _idx_1 = 1 |
431 | local _value_0 = _obj_1[_index_0] | 455 | for _key_0, _value_0 in pairs(_obj_1) do |
432 | _tab_0[#_tab_0 + 1] = _value_0 | 456 | if _idx_1 == _key_0 then |
457 | _tab_0[#_tab_0 + 1] = _value_0 | ||
458 | _idx_1 = _idx_1 + 1 | ||
459 | else | ||
460 | _tab_0[_key_0] = _value_0 | ||
461 | end | ||
433 | end | 462 | end |
434 | local _obj_2 | 463 | local _obj_2 |
435 | do | 464 | do |
436 | local _tab_1 = { } | 465 | local _tab_1 = { } |
437 | local _obj_3 = ... | 466 | local _obj_3 = ... |
438 | for _index_0 = 1, #_obj_3 do | 467 | local _idx_2 = 1 |
439 | local _value_0 = _obj_3[_index_0] | 468 | for _key_0, _value_0 in pairs(_obj_3) do |
440 | _tab_1[#_tab_1 + 1] = _value_0 | 469 | if _idx_2 == _key_0 then |
470 | _tab_1[#_tab_1 + 1] = _value_0 | ||
471 | _idx_2 = _idx_2 + 1 | ||
472 | else | ||
473 | _tab_1[_key_0] = _value_0 | ||
474 | end | ||
441 | end | 475 | end |
442 | _obj_2 = _tab_1 | 476 | _obj_2 = _tab_1 |
443 | end | 477 | end |
444 | for _index_0 = 1, #_obj_2 do | 478 | local _idx_2 = 1 |
445 | local _value_0 = _obj_2[_index_0] | 479 | for _key_0, _value_0 in pairs(_obj_2) do |
446 | _tab_0[#_tab_0 + 1] = _value_0 | 480 | if _idx_2 == _key_0 then |
481 | _tab_0[#_tab_0 + 1] = _value_0 | ||
482 | _idx_2 = _idx_2 + 1 | ||
483 | else | ||
484 | _tab_0[_key_0] = _value_0 | ||
485 | end | ||
447 | end | 486 | end |
448 | _tab_0[#_tab_0 + 1] = 1 | 487 | _tab_0[#_tab_0 + 1] = 1 |
449 | _tab_0[#_tab_0 + 1] = 2 | 488 | _tab_0[#_tab_0 + 1] = 2 |
450 | _tab_0[#_tab_0 + 1] = 3 | 489 | _tab_0[#_tab_0 + 1] = 3 |
451 | tbMixB = _tab_0 | 490 | tbMixB = _tab_0 |
452 | end | 491 | end |
492 | local template <const> = { | ||
493 | foo = "Hello", | ||
494 | bar = "World", | ||
495 | baz = "!" | ||
496 | } | ||
497 | local specialized <const> = (function() | ||
498 | local _tab_0 = { } | ||
499 | local _idx_0 = 1 | ||
500 | for _key_0, _value_0 in pairs(template) do | ||
501 | if _idx_0 == _key_0 then | ||
502 | _tab_0[#_tab_0 + 1] = _value_0 | ||
503 | _idx_0 = _idx_0 + 1 | ||
504 | else | ||
505 | _tab_0[_key_0] = _value_0 | ||
506 | end | ||
507 | end | ||
508 | _tab_0.bar = "Bob" | ||
509 | return _tab_0 | ||
510 | end)() | ||
511 | local specializedB | ||
512 | do | ||
513 | local _tab_0 = { | ||
514 | ["function"] = function() end | ||
515 | } | ||
516 | local _idx_0 = 1 | ||
517 | for _key_0, _value_0 in pairs(template) do | ||
518 | if _idx_0 == _key_0 then | ||
519 | _tab_0[#_tab_0 + 1] = _value_0 | ||
520 | _idx_0 = _idx_0 + 1 | ||
521 | else | ||
522 | _tab_0[_key_0] = _value_0 | ||
523 | end | ||
524 | end | ||
525 | _tab_0["end"] = function() end | ||
526 | _tab_0["if"] = true | ||
527 | _tab_0["else"] = false | ||
528 | specializedB = _tab_0 | ||
529 | end | ||
453 | return nil | 530 | return nil |
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 | ||