diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 6 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 7 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 248 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 3 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 1 |
5 files changed, 232 insertions, 33 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index c4f133b..da99d07 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -870,6 +870,12 @@ std::string Exp_t::to_string(void* ud) const { | |||
| 870 | } | 870 | } |
| 871 | return join(temp, " "sv); | 871 | return join(temp, " "sv); |
| 872 | } | 872 | } |
| 873 | std::string ReversedIndex_t::to_string(void* ud) const { | ||
| 874 | if (modifier) { | ||
| 875 | return "[# - "s + modifier->to_string(ud) + ']'; | ||
| 876 | } | ||
| 877 | return "[#]"s; | ||
| 878 | } | ||
| 873 | std::string Callable_t::to_string(void* ud) const { | 879 | std::string Callable_t::to_string(void* ud) const { |
| 874 | return item->to_string(ud); | 880 | return item->to_string(ud); |
| 875 | } | 881 | } |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 6bdc31b..d396d82 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -643,9 +643,14 @@ AST_END(TableAppendingOp) | |||
| 643 | AST_LEAF(PlainItem) | 643 | AST_LEAF(PlainItem) |
| 644 | AST_END(PlainItem) | 644 | AST_END(PlainItem) |
| 645 | 645 | ||
| 646 | AST_NODE(ReversedIndex) | ||
| 647 | ast_ptr<false, Exp_t> modifier; | ||
| 648 | AST_MEMBER(ReversedIndex, &modifier) | ||
| 649 | AST_END(ReversedIndex) | ||
| 650 | |||
| 646 | AST_NODE(ChainValue) | 651 | AST_NODE(ChainValue) |
| 647 | ast_ptr<true, Seperator_t> sep; | 652 | ast_ptr<true, Seperator_t> sep; |
| 648 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, | 653 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, ReversedIndex_t, |
| 649 | /*non-syntax-rule*/ PlainItem_t> items; | 654 | /*non-syntax-rule*/ PlainItem_t> items; |
| 650 | AST_MEMBER(ChainValue, &sep, &items) | 655 | AST_MEMBER(ChainValue, &sep, &items) |
| 651 | AST_END(ChainValue) | 656 | AST_END(ChainValue) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 4bac51b..cbf976f 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const std::string_view version = "0.28.7"sv; | 81 | const std::string_view version = "0.29.0"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -1281,6 +1281,8 @@ private: | |||
| 1281 | Common, | 1281 | Common, |
| 1282 | EndWithColon, | 1282 | EndWithColon, |
| 1283 | EndWithEOP, | 1283 | EndWithEOP, |
| 1284 | EndWithSlice, | ||
| 1285 | HasRIndex, | ||
| 1284 | HasEOP, | 1286 | HasEOP, |
| 1285 | HasKeyword, | 1287 | HasKeyword, |
| 1286 | HasUnicode, | 1288 | HasUnicode, |
| @@ -1299,6 +1301,9 @@ private: | |||
| 1299 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { | 1301 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { |
| 1300 | return ChainType::EndWithEOP; | 1302 | return ChainType::EndWithEOP; |
| 1301 | } | 1303 | } |
| 1304 | if (ast_is<Slice_t>(chainValue->items.back())) { | ||
| 1305 | return ChainType::EndWithSlice; | ||
| 1306 | } | ||
| 1302 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | 1307 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { |
| 1303 | if (dot->name.is<Metatable_t>()) { | 1308 | if (dot->name.is<Metatable_t>()) { |
| 1304 | return ChainType::Metatable; | 1309 | return ChainType::Metatable; |
| @@ -1324,6 +1329,8 @@ private: | |||
| 1324 | } | 1329 | } |
| 1325 | } else if (ast_is<ExistentialOp_t>(item)) { | 1330 | } else if (ast_is<ExistentialOp_t>(item)) { |
| 1326 | return ChainType::HasEOP; | 1331 | return ChainType::HasEOP; |
| 1332 | } else if (ast_is<ReversedIndex_t>(item)) { | ||
| 1333 | return ChainType::HasRIndex; | ||
| 1327 | } | 1334 | } |
| 1328 | } | 1335 | } |
| 1329 | return type; | 1336 | return type; |
| @@ -2471,12 +2478,14 @@ private: | |||
| 2471 | switch (type) { | 2478 | switch (type) { |
| 2472 | case ChainType::HasEOP: | 2479 | case ChainType::HasEOP: |
| 2473 | case ChainType::EndWithColon: | 2480 | case ChainType::EndWithColon: |
| 2481 | case ChainType::EndWithSlice: | ||
| 2474 | case ChainType::MetaFieldInvocation: { | 2482 | case ChainType::MetaFieldInvocation: { |
| 2475 | std::string preDefine = getPreDefineLine(assignment); | 2483 | std::string preDefine = getPreDefineLine(assignment); |
| 2476 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); | 2484 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); |
| 2477 | out.back().insert(0, preDefine); | 2485 | out.back().insert(0, preDefine); |
| 2478 | return false; | 2486 | return false; |
| 2479 | } | 2487 | } |
| 2488 | case ChainType::HasRIndex: | ||
| 2480 | case ChainType::HasKeyword: | 2489 | case ChainType::HasKeyword: |
| 2481 | case ChainType::HasUnicode: | 2490 | case ChainType::HasUnicode: |
| 2482 | case ChainType::Macro: | 2491 | case ChainType::Macro: |
| @@ -2832,17 +2841,19 @@ private: | |||
| 2832 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 2841 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); |
| 2833 | std::list<DestructItem> pairs; | 2842 | std::list<DestructItem> pairs; |
| 2834 | int index = 0; | 2843 | int index = 0; |
| 2844 | int count = 0; | ||
| 2845 | bool hasSpread = false; | ||
| 2835 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); | 2846 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); |
| 2836 | for (auto pair : *tableItems) { | 2847 | for (auto pair : *tableItems) { |
| 2837 | switch (pair->get_id()) { | 2848 | switch (pair->get_id()) { |
| 2838 | case id<Exp_t>(): | 2849 | case id<Exp_t>(): |
| 2839 | case id<NormalDef_t>(): { | 2850 | case id<NormalDef_t>(): { |
| 2851 | ++index; | ||
| 2840 | Exp_t* defVal = nullptr; | 2852 | Exp_t* defVal = nullptr; |
| 2841 | if (auto nd = ast_cast<NormalDef_t>(pair)) { | 2853 | if (auto nd = ast_cast<NormalDef_t>(pair)) { |
| 2842 | pair = nd->item.get(); | 2854 | pair = nd->item.get(); |
| 2843 | defVal = nd->defVal.get(); | 2855 | defVal = nd->defVal.get(); |
| 2844 | } | 2856 | } |
| 2845 | ++index; | ||
| 2846 | bool assignable = false; | 2857 | bool assignable = false; |
| 2847 | try { | 2858 | try { |
| 2848 | assignable = isAssignable(static_cast<Exp_t*>(pair)); | 2859 | assignable = isAssignable(static_cast<Exp_t*>(pair)); |
| @@ -2853,13 +2864,19 @@ private: | |||
| 2853 | if (optional) break; | 2864 | if (optional) break; |
| 2854 | throw CompileError("can't destructure value"sv, pair); | 2865 | throw CompileError("can't destructure value"sv, pair); |
| 2855 | } | 2866 | } |
| 2867 | ast_ptr<true, ast_node> indexItem; | ||
| 2868 | if (hasSpread) { | ||
| 2869 | int rIndex = count - index; | ||
| 2870 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); | ||
| 2871 | } else { | ||
| 2872 | indexItem.set(toAst<Exp_t>(std::to_string(index), pair)); | ||
| 2873 | } | ||
| 2856 | if (optional && varDefOnly && !assignable) { | 2874 | if (optional && varDefOnly && !assignable) { |
| 2857 | if (defVal) { | 2875 | if (defVal) { |
| 2858 | throw CompileError("default value is not supported here"sv, defVal); | 2876 | throw CompileError("default value is not supported here"sv, defVal); |
| 2859 | } | 2877 | } |
| 2860 | auto exp = static_cast<Exp_t*>(pair); | 2878 | auto exp = static_cast<Exp_t*>(pair); |
| 2861 | auto chain = exp->new_ptr<ChainValue_t>(); | 2879 | auto chain = exp->new_ptr<ChainValue_t>(); |
| 2862 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
| 2863 | chain->items.push_back(indexItem); | 2880 | chain->items.push_back(indexItem); |
| 2864 | pairs.push_back({exp, Empty, chain, nullptr}); | 2881 | pairs.push_back({exp, Empty, chain, nullptr}); |
| 2865 | break; | 2882 | break; |
| @@ -2874,7 +2891,6 @@ private: | |||
| 2874 | throw CompileError("default value is not supported here"sv, defVal); | 2891 | throw CompileError("default value is not supported here"sv, defVal); |
| 2875 | } | 2892 | } |
| 2876 | } | 2893 | } |
| 2877 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); | ||
| 2878 | for (auto& p : subPairs) { | 2894 | for (auto& p : subPairs) { |
| 2879 | if (sep) p.structure->items.push_front(sep); | 2895 | if (sep) p.structure->items.push_front(sep); |
| 2880 | p.structure->items.push_front(indexItem); | 2896 | p.structure->items.push_front(indexItem); |
| @@ -2885,7 +2901,6 @@ private: | |||
| 2885 | auto varName = singleVariableFrom(exp, AccessType::None); | 2901 | auto varName = singleVariableFrom(exp, AccessType::None); |
| 2886 | if (varName == "_"sv) break; | 2902 | if (varName == "_"sv) break; |
| 2887 | auto chain = exp->new_ptr<ChainValue_t>(); | 2903 | auto chain = exp->new_ptr<ChainValue_t>(); |
| 2888 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
| 2889 | chain->items.push_back(indexItem); | 2904 | chain->items.push_back(indexItem); |
| 2890 | pairs.push_back({exp, | 2905 | pairs.push_back({exp, |
| 2891 | varName, | 2906 | varName, |
| @@ -3010,7 +3025,13 @@ private: | |||
| 3010 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 3025 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
| 3011 | ++index; | 3026 | ++index; |
| 3012 | auto subPairs = destructFromExp(tb, varDefOnly, optional); | 3027 | auto subPairs = destructFromExp(tb, varDefOnly, optional); |
| 3013 | auto indexItem = toAst<Exp_t>(std::to_string(index), tb); | 3028 | ast_ptr<true, ast_node> indexItem; |
| 3029 | if (hasSpread) { | ||
| 3030 | int rIndex = count - index; | ||
| 3031 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); | ||
| 3032 | } else { | ||
| 3033 | indexItem.set(toAst<Exp_t>(std::to_string(index), tb)); | ||
| 3034 | } | ||
| 3014 | for (auto& p : subPairs) { | 3035 | for (auto& p : subPairs) { |
| 3015 | if (sep) p.structure->items.push_front(sep); | 3036 | if (sep) p.structure->items.push_front(sep); |
| 3016 | p.structure->items.push_front(indexItem); | 3037 | p.structure->items.push_front(indexItem); |
| @@ -3067,6 +3088,42 @@ private: | |||
| 3067 | subMetaDestruct->values.push_back(newPairDef); | 3088 | subMetaDestruct->values.push_back(newPairDef); |
| 3068 | break; | 3089 | break; |
| 3069 | } | 3090 | } |
| 3091 | case id<SpreadListExp_t>(): | ||
| 3092 | case id<SpreadExp_t>(): { | ||
| 3093 | ++index; | ||
| 3094 | if (hasSpread) { | ||
| 3095 | throw CompileError("duplicated spread expression"sv, pair); | ||
| 3096 | } | ||
| 3097 | hasSpread = true; | ||
| 3098 | for (auto item : *tableItems) { | ||
| 3099 | if (ast_is< | ||
| 3100 | SpreadListExp_t, SpreadExp_t, | ||
| 3101 | TableBlockIndent_t, | ||
| 3102 | Exp_t, NormalDef_t>(item)) { | ||
| 3103 | count++; | ||
| 3104 | } | ||
| 3105 | } | ||
| 3106 | Exp_t* exp = nullptr; | ||
| 3107 | if (auto se = ast_cast<SpreadExp_t>(pair)) { | ||
| 3108 | exp = se->exp.get(); | ||
| 3109 | } else { | ||
| 3110 | exp = ast_to<SpreadListExp_t>(pair)->exp.get(); | ||
| 3111 | } | ||
| 3112 | auto varName = singleVariableFrom(exp, AccessType::None); | ||
| 3113 | if (varName == "_"sv) break; | ||
| 3114 | int start = index; | ||
| 3115 | int stop = index - count - 1; | ||
| 3116 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
| 3117 | auto slice = toAst<Slice_t>( | ||
| 3118 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); | ||
| 3119 | chain->items.push_back(slice); | ||
| 3120 | auto nil = toAst<Exp_t>("nil"sv, slice); | ||
| 3121 | pairs.push_back({exp, | ||
| 3122 | varName, | ||
| 3123 | chain, | ||
| 3124 | nil.get()}); | ||
| 3125 | break; | ||
| 3126 | } | ||
| 3070 | default: YUEE("AST node mismatch", pair); break; | 3127 | default: YUEE("AST node mismatch", pair); break; |
| 3071 | } | 3128 | } |
| 3072 | } | 3129 | } |
| @@ -5706,6 +5763,45 @@ private: | |||
| 5706 | } | 5763 | } |
| 5707 | } | 5764 | } |
| 5708 | 5765 | ||
| 5766 | bool transformChainEndWithSlice(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
| 5767 | auto x = chainList.front(); | ||
| 5768 | if (ast_is<Slice_t>(chainList.back())) { | ||
| 5769 | auto comp = x->new_ptr<Comprehension_t>(); | ||
| 5770 | { | ||
| 5771 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
| 5772 | for (auto item : chainList) { | ||
| 5773 | chainValue->items.push_back(item); | ||
| 5774 | } | ||
| 5775 | auto itemVar = getUnusedName("_item_"sv); | ||
| 5776 | auto expCode = YueFormat{}.toString(chainValue); | ||
| 5777 | auto compCode = '[' + itemVar + " for "s + itemVar + " in *"s + expCode + ']'; | ||
| 5778 | comp.set(toAst<Comprehension_t>(compCode, x)); | ||
| 5779 | } | ||
| 5780 | switch (usage) { | ||
| 5781 | case ExpUsage::Assignment: { | ||
| 5782 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 5783 | simpleValue->value.set(comp); | ||
| 5784 | auto exp = newExp(simpleValue, x); | ||
| 5785 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 5786 | assignment->expList.set(assignList); | ||
| 5787 | auto assign = x->new_ptr<Assign_t>(); | ||
| 5788 | assign->values.push_back(exp); | ||
| 5789 | assignment->action.set(assign); | ||
| 5790 | transformAssignment(assignment, out); | ||
| 5791 | break; | ||
| 5792 | } | ||
| 5793 | case ExpUsage::Return: | ||
| 5794 | transformComprehension(comp, out, ExpUsage::Return); | ||
| 5795 | break; | ||
| 5796 | default: | ||
| 5797 | transformComprehension(comp, out, ExpUsage::Closure); | ||
| 5798 | break; | ||
| 5799 | } | ||
| 5800 | return true; | ||
| 5801 | } | ||
| 5802 | return false; | ||
| 5803 | } | ||
| 5804 | |||
| 5709 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | 5805 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
| 5710 | auto x = chainList.front(); | 5806 | auto x = chainList.front(); |
| 5711 | if (ast_is<ExistentialOp_t>(chainList.back())) { | 5807 | if (ast_is<ExistentialOp_t>(chainList.back())) { |
| @@ -6369,6 +6465,93 @@ private: | |||
| 6369 | } | 6465 | } |
| 6370 | return; | 6466 | return; |
| 6371 | } | 6467 | } |
| 6468 | break; | ||
| 6469 | } | ||
| 6470 | case id<ReversedIndex_t>(): { | ||
| 6471 | auto rIndex = static_cast<ReversedIndex_t*>(*it); | ||
| 6472 | auto current = it; | ||
| 6473 | auto prevChain = x->new_ptr<ChainValue_t>(); | ||
| 6474 | for (auto i = chainList.begin(); i != current; ++i) { | ||
| 6475 | prevChain->items.push_back(*i); | ||
| 6476 | } | ||
| 6477 | auto var = singleVariableFrom(prevChain, AccessType::None); | ||
| 6478 | if (!var.empty() && isLocal(var)) { | ||
| 6479 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); | ||
| 6480 | if (rIndex->modifier) { | ||
| 6481 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
| 6482 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
| 6483 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
| 6484 | indexNode->opValues.push_back(opValue); | ||
| 6485 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
| 6486 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
| 6487 | } | ||
| 6488 | prevChain->items.push_back(indexNode); | ||
| 6489 | auto next = current; | ||
| 6490 | ++next; | ||
| 6491 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6492 | prevChain->items.push_back(*i); | ||
| 6493 | } | ||
| 6494 | if (usage == ExpUsage::Assignment) { | ||
| 6495 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6496 | assignment->expList.set(assignList); | ||
| 6497 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6498 | assign->values.push_back(newExp(prevChain, x)); | ||
| 6499 | assignment->action.set(assign); | ||
| 6500 | transformAssignment(assignment, out); | ||
| 6501 | return; | ||
| 6502 | } | ||
| 6503 | transformChainValue(prevChain, out, usage, assignList); | ||
| 6504 | return; | ||
| 6505 | } else { | ||
| 6506 | auto itemVar = getUnusedName("_item_"sv); | ||
| 6507 | auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x); | ||
| 6508 | auto stmt1 = x->new_ptr<Statement_t>(); | ||
| 6509 | stmt1->content.set(asmt); | ||
| 6510 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
| 6511 | newChain->items.push_back(toAst<Callable_t>(itemVar, x)); | ||
| 6512 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); | ||
| 6513 | if (rIndex->modifier) { | ||
| 6514 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
| 6515 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
| 6516 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
| 6517 | indexNode->opValues.push_back(opValue); | ||
| 6518 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
| 6519 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
| 6520 | } | ||
| 6521 | newChain->items.push_back(indexNode); | ||
| 6522 | auto next = current; | ||
| 6523 | ++next; | ||
| 6524 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6525 | newChain->items.push_back(*i); | ||
| 6526 | } | ||
| 6527 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 6528 | expList->exprs.push_back(newExp(newChain, x)); | ||
| 6529 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
| 6530 | expListAssign->expList.set(expList); | ||
| 6531 | auto stmt2 = x->new_ptr<Statement_t>(); | ||
| 6532 | stmt2->content.set(expListAssign); | ||
| 6533 | auto block = x->new_ptr<Block_t>(); | ||
| 6534 | block->statements.push_back(stmt1); | ||
| 6535 | block->statements.push_back(stmt2); | ||
| 6536 | auto body = x->new_ptr<Body_t>(); | ||
| 6537 | body->content.set(block); | ||
| 6538 | auto doNode = x->new_ptr<Do_t>(); | ||
| 6539 | doNode->body.set(body); | ||
| 6540 | if (usage == ExpUsage::Assignment) { | ||
| 6541 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6542 | assignment->expList.set(assignList); | ||
| 6543 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6544 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 6545 | sVal->value.set(doNode); | ||
| 6546 | assign->values.push_back(newExp(sVal, x)); | ||
| 6547 | assignment->action.set(assign); | ||
| 6548 | transformAssignment(assignment, out); | ||
| 6549 | return; | ||
| 6550 | } | ||
| 6551 | transformDo(doNode, out, usage); | ||
| 6552 | return; | ||
| 6553 | } | ||
| 6554 | break; | ||
| 6372 | } | 6555 | } |
| 6373 | } | 6556 | } |
| 6374 | } | 6557 | } |
| @@ -6887,6 +7070,9 @@ private: | |||
| 6887 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 7070 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
| 6888 | return; | 7071 | return; |
| 6889 | } | 7072 | } |
| 7073 | if (transformChainEndWithSlice(chainList, out, usage, assignList)) { | ||
| 7074 | return; | ||
| 7075 | } | ||
| 6890 | transformChainList(chainList, out, usage, assignList); | 7076 | transformChainList(chainList, out, usage, assignList); |
| 6891 | } | 7077 | } |
| 6892 | 7078 | ||
| @@ -8107,7 +8293,7 @@ private: | |||
| 8107 | if (stopValue.empty()) { | 8293 | if (stopValue.empty()) { |
| 8108 | _buf << "#"sv << listVar; | 8294 | _buf << "#"sv << listVar; |
| 8109 | } else { | 8295 | } else { |
| 8110 | _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " or "sv << maxVar; | 8296 | _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar; |
| 8111 | } | 8297 | } |
| 8112 | if (!stepValue.empty()) { | 8298 | if (!stepValue.empty()) { |
| 8113 | _buf << ", "sv << stepValue; | 8299 | _buf << ", "sv << stepValue; |
| @@ -10059,24 +10245,24 @@ private: | |||
| 10059 | str_list rets; | 10245 | str_list rets; |
| 10060 | pushScope(); | 10246 | pushScope(); |
| 10061 | auto okVar = getUnusedName("_ok_"sv); | 10247 | auto okVar = getUnusedName("_ok_"sv); |
| 10062 | for (size_t i = 0; i < assignList->exprs.size(); i++) { | 10248 | for (size_t i = 0; i < assignList->exprs.size(); i++) { |
| 10063 | auto retVar = getUnusedName("_ret_"sv); | 10249 | auto retVar = getUnusedName("_ret_"sv); |
| 10064 | rets.emplace_back(retVar); | 10250 | rets.emplace_back(retVar); |
| 10065 | addToScope(retVar); | 10251 | addToScope(retVar); |
| 10066 | } | 10252 | } |
| 10067 | popScope(); | 10253 | popScope(); |
| 10068 | auto varList = join(rets, ","sv); | 10254 | auto varList = join(rets, ","sv); |
| 10069 | auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); | 10255 | auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); |
| 10070 | auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); | 10256 | auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); |
| 10071 | auto sVal = simpleSingleValueFrom(exp); | 10257 | auto sVal = simpleSingleValueFrom(exp); |
| 10072 | auto newTry = sVal->value.to<Try_t>(); | 10258 | auto newTry = sVal->value.to<Try_t>(); |
| 10073 | newTry->func.set(tryNode->func); | 10259 | newTry->func.set(tryNode->func); |
| 10074 | newTry->catchBlock.set(tryNode->catchBlock); | 10260 | newTry->catchBlock.set(tryNode->catchBlock); |
| 10075 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10261 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10076 | assignment->expList.set(assignList); | 10262 | assignment->expList.set(assignList); |
| 10077 | auto assign = x->new_ptr<Assign_t>(); | 10263 | auto assign = x->new_ptr<Assign_t>(); |
| 10078 | assign->values.push_back(ifNode); | 10264 | assign->values.push_back(ifNode); |
| 10079 | assignment->action.set(assign); | 10265 | assignment->action.set(assign); |
| 10080 | transformAssignment(assignment, out); | 10266 | transformAssignment(assignment, out); |
| 10081 | return; | 10267 | return; |
| 10082 | } | 10268 | } |
| @@ -10084,12 +10270,12 @@ private: | |||
| 10084 | auto okVar = getUnusedName("_ok_"sv); | 10270 | auto okVar = getUnusedName("_ok_"sv); |
| 10085 | auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; | 10271 | auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; |
| 10086 | auto doNode = toAst<Do_t>(code, x); | 10272 | auto doNode = toAst<Do_t>(code, x); |
| 10087 | auto block = doNode->body->content.to<Block_t>(); | 10273 | auto block = doNode->body->content.to<Block_t>(); |
| 10088 | auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>(); | 10274 | auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>(); |
| 10089 | auto assign = asmt->action.to<Assign_t>(); | 10275 | auto assign = asmt->action.to<Assign_t>(); |
| 10090 | auto sVal = simpleSingleValueFrom(assign->values.back()); | 10276 | auto sVal = simpleSingleValueFrom(assign->values.back()); |
| 10091 | auto newTry = sVal->value.to<Try_t>(); | 10277 | auto newTry = sVal->value.to<Try_t>(); |
| 10092 | newTry->func.set(tryNode->func); | 10278 | newTry->func.set(tryNode->func); |
| 10093 | newTry->catchBlock.set(tryNode->catchBlock); | 10279 | newTry->catchBlock.set(tryNode->catchBlock); |
| 10094 | transformDo(doNode, out, usage); | 10280 | transformDo(doNode, out, usage); |
| 10095 | return; | 10281 | return; |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index e860d55..1011a49 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -709,7 +709,8 @@ YueParser::YueParser() { | |||
| 709 | chain_with_colon = +chain_item >> -colon_chain; | 709 | chain_with_colon = +chain_item >> -colon_chain; |
| 710 | chain_items = chain_with_colon | colon_chain; | 710 | chain_items = chain_with_colon | colon_chain; |
| 711 | 711 | ||
| 712 | index = '[' >> not_('[') >> space >> Exp >> space >> ']'; | 712 | index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']'; |
| 713 | ReversedIndex = '#' >> space >> -('-' >> space >> Exp); | ||
| 713 | chain_item = | 714 | chain_item = |
| 714 | Invoke >> -ExistentialOp | | 715 | Invoke >> -ExistentialOp | |
| 715 | DotChainItem >> -ExistentialOp | | 716 | DotChainItem >> -ExistentialOp | |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 0d9db19..1057626 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -365,6 +365,7 @@ private: | |||
| 365 | AST_RULE(ExpOpValue); | 365 | AST_RULE(ExpOpValue); |
| 366 | AST_RULE(Exp); | 366 | AST_RULE(Exp); |
| 367 | AST_RULE(Callable); | 367 | AST_RULE(Callable); |
| 368 | AST_RULE(ReversedIndex); | ||
| 368 | AST_RULE(ChainValue); | 369 | AST_RULE(ChainValue); |
| 369 | AST_RULE(SimpleTable); | 370 | AST_RULE(SimpleTable); |
| 370 | AST_RULE(SimpleValue); | 371 | AST_RULE(SimpleValue); |
