diff options
author | Li Jin <dragon-fly@qq.com> | 2022-02-11 10:37:35 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-02-11 10:37:35 +0800 |
commit | 09fc831f540ce3966aeff679164f37e7d40457c9 (patch) | |
tree | ea56f0fa897af3089e1289bdfa7676a62198dc13 | |
parent | a66ec0d18eba6b38fad25cc88c82f7532d689670 (diff) | |
download | yuescript-09fc831f540ce3966aeff679164f37e7d40457c9.tar.gz yuescript-09fc831f540ce3966aeff679164f37e7d40457c9.tar.bz2 yuescript-09fc831f540ce3966aeff679164f37e7d40457c9.zip |
add Lua table appending idiom: tb #= 123
-rw-r--r-- | spec/inputs/syntax.yue | 13 | ||||
-rw-r--r-- | spec/outputs/syntax.lua | 18 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 66 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.cpp | 3 |
4 files changed, 77 insertions, 23 deletions
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index cb947e1..67d3a27 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
@@ -184,10 +184,21 @@ a["hello#{tostring ff}"] += 10 | |||
184 | a[four].x += 10 | 184 | a[four].x += 10 |
185 | 185 | ||
186 | a.b += 1 | 186 | a.b += 1 |
187 | a.b[1].c[2+3] += 1 | 187 | a.b[1].c[2 + 3] += 1 |
188 | with tb | 188 | with tb |
189 | .a.c += 1 | 189 | .a.c += 1 |
190 | 190 | ||
191 | tb #= 10 | ||
192 | a.b.c #= 1 | ||
193 | x #= if v | ||
194 | 1 | ||
195 | else | ||
196 | 2 | ||
197 | with tb | ||
198 | .b.c #= with vec | ||
199 | .x = 1 | ||
200 | .y = 2 | ||
201 | |||
191 | x = 0 | 202 | x = 0 |
192 | _ = (if ntype(v) == "fndef" then x += 1) for v in *values | 203 | _ = (if ntype(v) == "fndef" then x += 1) for v in *values |
193 | 204 | ||
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index ed8ed39..4596a29 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua | |||
@@ -195,6 +195,24 @@ do | |||
195 | local _obj_2 = _with_0.a | 195 | local _obj_2 = _with_0.a |
196 | _obj_2.c = _obj_2.c + 1 | 196 | _obj_2.c = _obj_2.c + 1 |
197 | end | 197 | end |
198 | tb[#tb + 1] = 10 | ||
199 | local _obj_2 = a.b.c | ||
200 | _obj_2[#_obj_2 + 1] = 1 | ||
201 | if v then | ||
202 | x[#x + 1] = 1 | ||
203 | else | ||
204 | x[#x + 1] = 2 | ||
205 | end | ||
206 | do | ||
207 | local _with_0 = tb | ||
208 | local _obj_3 = _with_0.b.c | ||
209 | do | ||
210 | local _with_1 = vec | ||
211 | _with_1.x = 1 | ||
212 | _with_1.y = 2 | ||
213 | _obj_3[#_obj_3 + 1] = _with_1 | ||
214 | end | ||
215 | end | ||
198 | x = 0 | 216 | x = 0 |
199 | local _list_0 = values | 217 | local _list_0 = values |
200 | for _index_0 = 1, #_list_0 do | 218 | for _index_0 = 1, #_list_0 do |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index db225f6..33d4dcb 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -60,7 +60,7 @@ using namespace parserlib; | |||
60 | 60 | ||
61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
62 | 62 | ||
63 | const std::string_view version = "0.9.8"sv; | 63 | const std::string_view version = "0.9.9"sv; |
64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
65 | 65 | ||
66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
@@ -2014,7 +2014,10 @@ private: | |||
2014 | auto leftExp = static_cast<Exp_t*>(expList->exprs.objects().front()); | 2014 | auto leftExp = static_cast<Exp_t*>(expList->exprs.objects().front()); |
2015 | auto leftValue = singleValueFrom(leftExp); | 2015 | auto leftValue = singleValueFrom(leftExp); |
2016 | if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); | 2016 | if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); |
2017 | if (auto chain = leftValue->item.as<ChainValue_t>()) { | 2017 | auto chain = leftValue->item.as<ChainValue_t>(); |
2018 | if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, chain)); | ||
2019 | auto op = _parser.toString(update->op); | ||
2020 | { | ||
2018 | auto dot = ast_cast<DotChainItem_t>(chain->items.back()); | 2021 | auto dot = ast_cast<DotChainItem_t>(chain->items.back()); |
2019 | if (dot && dot->name.is<Metatable_t>()) { | 2022 | if (dot && dot->name.is<Metatable_t>()) { |
2020 | throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); | 2023 | throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); |
@@ -2030,26 +2033,38 @@ private: | |||
2030 | BREAK_IF(var); | 2033 | BREAK_IF(var); |
2031 | } | 2034 | } |
2032 | } | 2035 | } |
2033 | auto tmpChain = x->new_ptr<ChainValue_t>(); | 2036 | if (op == "#"sv) { |
2034 | ast_ptr<false, ast_node> ptr(chain->items.back()); | 2037 | auto objVar = getUnusedName("_obj_"sv); |
2035 | for (auto item : chain->items.objects()) { | 2038 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
2036 | if (item != ptr) { | 2039 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); |
2037 | tmpChain->items.push_back(item); | 2040 | auto assign = x->new_ptr<Assign_t>(); |
2041 | assign->values.push_back(leftExp); | ||
2042 | newAssignment->action.set(assign); | ||
2043 | transformAssignment(newAssignment, temp); | ||
2044 | chain->items.clear(); | ||
2045 | chain->items.push_back(toAst<Callable_t>(objVar, x)); | ||
2046 | } else { | ||
2047 | auto tmpChain = x->new_ptr<ChainValue_t>(); | ||
2048 | ast_ptr<false, ast_node> ptr(chain->items.back()); | ||
2049 | for (auto item : chain->items.objects()) { | ||
2050 | if (item != ptr) { | ||
2051 | tmpChain->items.push_back(item); | ||
2052 | } | ||
2038 | } | 2053 | } |
2054 | auto value = x->new_ptr<Value_t>(); | ||
2055 | value->item.set(tmpChain); | ||
2056 | auto exp = newExp(value, x); | ||
2057 | auto objVar = getUnusedName("_obj_"sv); | ||
2058 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2059 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | ||
2060 | auto assign = x->new_ptr<Assign_t>(); | ||
2061 | assign->values.push_back(exp); | ||
2062 | newAssignment->action.set(assign); | ||
2063 | transformAssignment(newAssignment, temp); | ||
2064 | chain->items.clear(); | ||
2065 | chain->items.push_back(toAst<Callable_t>(objVar, x)); | ||
2066 | chain->items.push_back(ptr); | ||
2039 | } | 2067 | } |
2040 | auto value = x->new_ptr<Value_t>(); | ||
2041 | value->item.set(tmpChain); | ||
2042 | auto exp = newExp(value, x); | ||
2043 | auto objVar = getUnusedName("_obj_"sv); | ||
2044 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2045 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | ||
2046 | auto assign = x->new_ptr<Assign_t>(); | ||
2047 | assign->values.push_back(exp); | ||
2048 | newAssignment->action.set(assign); | ||
2049 | transformAssignment(newAssignment, temp); | ||
2050 | chain->items.clear(); | ||
2051 | chain->items.push_back(toAst<Callable_t>(objVar, x)); | ||
2052 | chain->items.push_back(ptr); | ||
2053 | BLOCK_END | 2068 | BLOCK_END |
2054 | auto tmpChain = x->new_ptr<ChainValue_t>(); | 2069 | auto tmpChain = x->new_ptr<ChainValue_t>(); |
2055 | for (auto item : chain->items.objects()) { | 2070 | for (auto item : chain->items.objects()) { |
@@ -2074,7 +2089,6 @@ private: | |||
2074 | chain->items.clear(); | 2089 | chain->items.clear(); |
2075 | chain->items.dup(tmpChain->items); | 2090 | chain->items.dup(tmpChain->items); |
2076 | } | 2091 | } |
2077 | auto op = _parser.toString(update->op); | ||
2078 | if (op == "??"sv) { | 2092 | if (op == "??"sv) { |
2079 | auto defs = getPredefine(assignment); | 2093 | auto defs = getPredefine(assignment); |
2080 | auto rightExp = x->new_ptr<Exp_t>(); | 2094 | auto rightExp = x->new_ptr<Exp_t>(); |
@@ -2085,6 +2099,16 @@ private: | |||
2085 | if (!defs.empty()) temp.back().insert(0, defs + nll(x)); | 2099 | if (!defs.empty()) temp.back().insert(0, defs + nll(x)); |
2086 | out.push_back(join(temp)); | 2100 | out.push_back(join(temp)); |
2087 | return; | 2101 | return; |
2102 | } else if (op == "#"sv) { | ||
2103 | auto left = _parser.toString(chain->items.front()); | ||
2104 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2105 | newAssignment->expList.set(toAst<ExpList_t>(left + "[#"s + left + "+1]"s, x)); | ||
2106 | auto assign = x->new_ptr<Assign_t>(); | ||
2107 | assign->values.push_back(update->value); | ||
2108 | newAssignment->action.set(assign); | ||
2109 | transformAssignment(newAssignment, temp); | ||
2110 | out.push_back(join(temp)); | ||
2111 | return; | ||
2088 | } | 2112 | } |
2089 | auto defs = getPredefine(assignment); | 2113 | auto defs = getPredefine(assignment); |
2090 | transformValue(leftValue, temp); | 2114 | transformValue(leftValue, temp); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index e171f3f..772ae08 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -324,7 +324,8 @@ YueParser::YueParser() { | |||
324 | expr("|") | | 324 | expr("|") | |
325 | expr(">>") | | 325 | expr(">>") | |
326 | expr("<<") | | 326 | expr("<<") | |
327 | expr("??"); | 327 | expr("??") | |
328 | expr("#"); | ||
328 | 329 | ||
329 | Update = Space >> update_op >> expr("=") >> Exp; | 330 | Update = Space >> update_op >> expr("=") >> Exp; |
330 | 331 | ||