From d4af1fa275b1d27229fc995f4a45137380040933 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 8 Sep 2022 09:26:49 +0800 Subject: redesigned metatable syntax. add support for destructuring a field with string and expression --- doc/docs/doc/README.md | 53 ++-- spec/inputs/assign.yue | 4 +- spec/inputs/class.yue | 6 +- spec/inputs/destructure.yue | 31 ++- spec/inputs/existential.yue | 4 +- spec/inputs/import.yue | 6 +- spec/inputs/macro.yue | 2 +- spec/inputs/metatable.yue | 92 ++++--- spec/inputs/switch.yue | 4 +- spec/outputs/destructure.lua | 61 +++++ spec/outputs/metatable.lua | 33 +++ src/yuescript/yue_ast.h | 17 +- src/yuescript/yue_compiler.cpp | 556 ++++++++++++++++++++++++++--------------- src/yuescript/yue_parser.cpp | 32 ++- src/yuescript/yue_parser.h | 1 + 15 files changed, 605 insertions(+), 297 deletions(-) diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index 5f00860..5e81d4c 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md @@ -37,8 +37,8 @@ inventory = -- metatable manipulation apple = size: 15 - index#: {color: 0x00ffff} -p apple.color, apple.index# if apple.#? + : {color: 0x00ffff} +p apple.color, apple. if apple.<>? -- js-like export syntax export yuescript = "月之脚本" @@ -69,8 +69,8 @@ inventory = -- metatable manipulation apple = size: 15 - index#: {color: 0x00ffff} -p apple.color, apple.index# if apple.#? + : {color: 0x00ffff} +p apple.color, apple. if apple.<>? -- js-like export syntax export yuescript = "月之脚本" @@ -429,77 +429,78 @@ merge = {...a, ...b} ### Metatable -The **#** operator can be used as a shortcut for metatable manipulation. +The **<>** operator can be used as a shortcut for metatable manipulation. * **Metatable Creation** -Create normal table with key **#** or metamethod key that ends with **#**. +Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. ```moonscript mt = {} -add = (right)=> #: mt, value: @value + right.value +add = (right)=> <>: mt, value: @value + right.value mt.__add = add -a = #: mt, value: 1 +a = <>: mt, value: 1 -- set field with variable of the same name -b = :add#, value: 2 -c = add#: mt.__add, value: 3 +b = :, value: 2 +c = : mt.__add, value: 3 d = a + b + c print d.value -close _ = close#: -> print "out of scope" +close _ = : -> print "out of scope" ```
 mt = {}
-add = (right)=> #: mt, value: @value + right.value
+add = (right)=> <>: mt, value: @value + right.value
 mt.__add = add
 
-a = #: mt, value: 1
+a = <>: mt, value: 1
  -- set field with variable of the same name
-b = :add#, value: 2
-c = add#: mt.__add, value: 3
+b = :, value: 2
+c = : mt.__add, value: 3
 
 d = a + b + c
 print d.value
 
-close _ = close#: -> print "out of scope"
+close _ = : -> print "out of scope"
 
* **Metatable Accessing** -Accessing metatable with key **#** or metamethod key that ends with **#**. +Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. ```moonscript -- create with metatable containing field "value" -tb = ["value"]#: 123 -tb.index# = tb.# +tb = <"value">: 123 +tb. = tb.<> print tb.value -tb.# = __index: {item: "hello"} +tb.<> = __index: {item: "hello"} print tb.item ``` +
 -- create with metatable containing field "value"
-tb = ["value"]#: 123
-tb.index# = tb.#
+tb = <"value">: 123
+tb. = tb.<>
 print tb.value
-tb.# = __index: {item: "hello"}
+tb.<> = __index: {item: "hello"}
 print tb.item
 
* **Metatable Destructure** -Destruct metatable with metamethod key that ends with **#**. +Destruct metatable with metamethod key surrounded by **<>**. ```moonscript -{item, :new, :close#, index#: getter} = tb +{item, :new, :, : getter} = tb print item, new, close, getter ```
-{item, :new, :close#, index#: getter} = tb
+{item, :new, :, : getter} = tb
 print item, new, close, getter
 
diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue index d04bcb8..da44dff 100644 --- a/spec/inputs/assign.yue +++ b/spec/inputs/assign.yue @@ -34,7 +34,7 @@ x = (do (using nil) <- _ -a.# = do +a.<> = do print 123 {} @@ -63,7 +63,7 @@ do 123, tb do - a, b[], c, d.add# = if x + a, b[], c, d. = if x switch y when 1 f! diff --git a/spec/inputs/class.yue b/spec/inputs/class.yue index 9091d23..49537c2 100644 --- a/spec/inputs/class.yue +++ b/spec/inputs/class.yue @@ -237,9 +237,9 @@ class Example class Foo new: (x) => @x = x - mul#: (y) => @x * y - ["dsd-dsd"]#: 123 + : (y) => @x * y + <"dsd-dsd">: 123 :add - :add# + : nil diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 53f9ea3..ce593ec 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue @@ -160,17 +160,17 @@ do {key1: {key2: value1 = 123}, :key3 = "abc"} = tb - {#: mt = {__index: {abc: 123}}, #: {:call# = (-> {}), :add#}} = tb + {<>: mt = {__index: {abc: 123}}, <>: {: = (-> {}), :}} = tb - {x: {#: mtx = {}}, :y, z: zItem, :index# = -> nil} = tb + {x: {<>: mtx = {}}, :y, z: zItem, : = -> nil} = tb - {#: {func: a.b(-> 123).c = item?.defVal}} = tb + {<>: {func: a.b(-> 123).c = item?.defVal}} = tb do - {#: mt = {}, sub#: subFunc} = tb.x + {<>: mt = {}, : subFunc} = tb.x do - {x: {#: mt = {}, sub#: subFunc}} = tb + {x: {<>: mt = {}, : subFunc}} = tb do {a = 1, b = 2, c: {d.e = 3}} = tb @@ -189,5 +189,24 @@ do const {:x = 0.0, :y = 0.0} = point do - x1, x2, x3, a[], d, {b}, e, c.# = 1, 2, 3, f! + x1, x2, x3, a[], d, {b}, e, c.<> = 1, 2, 3, f! y1, :y2, :y3, y4 = f1!, f2! + +do + { + [["abc"]]: v1 = 111, + [1 + 1]: {v2 = 222, v3 = 333}, + @x: v4 = 444 + }, \ + 'x-y-z': v5, [func!]: {[func2!]: v6, v7} = tb, tb2 + +do + <[name]>: value_meta, [name]: value = tb + +do + {: = (-> "name"), :} = tb + + switch tb + when {: = "item", <"123">: meta_field} + print name, meta_field + diff --git a/spec/inputs/existential.yue b/spec/inputs/existential.yue index 101e1d8..e73b421 100644 --- a/spec/inputs/existential.yue +++ b/spec/inputs/existential.yue @@ -49,9 +49,9 @@ with? io.open "test.txt", "w" \write "hello" \close! -tb?.a#? 123 +tb?.? 123 -with? tb.#?.index# +with? tb.<>?. .a = 1 nil diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index 570b909..af5545d 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue @@ -64,8 +64,8 @@ do import "org.package.module" as function:func, if:ifVar do - import "m" as {a#: b} - import "m" as {e: f, a#: c} + import "m" as {: b} + import "m" as {e: f, : c} import "m" as {c: d} - import "m" as {g, {h#: i}} + import "m" as {g, {: i}} diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 3c89c1c..ac51d85 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue @@ -262,7 +262,7 @@ $chainC( Destroy! ) -macro tb = -> "{'abc', a:123, call#:=> 998}" +macro tb = -> "{'abc', a:123, :=> 998}" print $tb[1], $tb.a, ($tb)!, $tb! print "current line: #{ $LINE }" diff --git a/spec/inputs/metatable.yue b/spec/inputs/metatable.yue index 86991c2..61cc266 100644 --- a/spec/inputs/metatable.yue +++ b/spec/inputs/metatable.yue @@ -1,62 +1,86 @@ -a = close: true, close#: => print "out of scope" -b = add#: (left, right)-> right - left -c = key1: true, :add#, key2: true -w = [name]#:123, ["new"]#:(val)=> {val} -w.#["new"] w.#[name] +a = close: true, : => print "out of scope" +b = : (left, right)-> right - left +c = key1: true, :, key2: true +w = <[name]>:123, <"new">:(val)=> {val} +w.<>["new"] w.<>[name] -do close _ = close#: -> print "out of scope" +do close _ = : -> print "out of scope" -d, e = a.close, a.close# +d, e = a.close, a. -f = a\close# 1 -a.add# = (x, y)-> x + y +f = a\ 1 +a. = (x, y)-> x + y do - {:new, :close#, close#: closeA} = a + {:new, :, : closeA} = a print new, close, closeA do local * x, \ - {:new, :var, :close#, close#: closeA}, \ - :num, :add#, :sub# \ + {:new, :var, :, : closeA}, \ + :num, :, : \ = 123, a.b.c, func! -x.abc, a.b.# = 123, {} -func!.# = mt --, extra -a, b.c.#, d, e = 1, mt, "abc", nil +x.abc, a.b.<> = 123, {} +func!.<> = mt --, extra +a, b.c.<>, d, e = 1, mt, "abc", nil -is_same = a.#.__index == a.index# +is_same = a.<>.__index == a. -- -a.# = __index: tb -a.#.__index = tb -a.index# = tb +a.<> = __index: tb +a.<>.__index = tb +a. = tb -- -mt = a.# +mt = a.<> tb\func #list -tb\func#list -tb\func# list +tb\list +tb\ list -import "module" as :index#, newindex#:setFunc +import "module" as :, :setFunc with tb - print .add#, .x\index# "key" - a = .index#.add#\new# 123 - b = t#.close#.test - c = t #.close# .test + print ., .x\ "key" + a = ..\ 123 + b = t#..test + c = t #. .test -#:mt = a -a = #:mt -a = #:__index:mt +<>:mt = a +a = <>:mt +a = <>:__index:mt local index -#:__index:index = a -:index# = a +<>:__index:index = a +: = a -do #:{new:ctor, :update} = a -do {new:ctor, :update} = a.# +do <>:{new:ctor, :update} = a +do {new:ctor, :update} = a.<> + +tb = {} +do + f = tb\<"value#{x < y}">(123, ...) + f tb\<'value'> 123, ... + tb\<[[ + value + 1 + ]]>(123, ...) + return tb\<["value" .. tostring x > y]>(123, ...) + +do + f = tb\(123, ...) + f tb\(123, ...) + tb\(123, ...) + return tb\ 123, ... + +do + f = tb. 123, ... + f = tb.<"value#{x < y}">(123, ...) + f tb.<'value'> 123, ... + tb.<[[ value +1]]>(123, ...) + return tb.<["value" .. tostring x > y]>(123, ...) nil diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index 442d15f..cb1eb31 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue @@ -101,7 +101,7 @@ do print "Object A" when ClassB print "Object B" - when #: mt + when <>: mt print "A table with metatable" else print "item not accepted!" @@ -156,7 +156,7 @@ do do switch y - when {x: #: mt} + when {x: <>: mt} print mt nil diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index dfac42c..0da920e 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua @@ -428,3 +428,64 @@ do y2, y3 = _obj_0.y2, _obj_0.y3 end end +do + local v1, v2, v3, v4 + do + local _obj_0 = tb + local _tmp_0, _tmp_1 = 1 + 1, self.x + v1, v2, v3, v4 = _obj_0[ [["abc"]]], _obj_0[_tmp_0][1], _obj_0[_tmp_0][2], _obj_0[_tmp_1] + if v1 == nil then + v1 = 111 + end + if v2 == nil then + v2 = 222 + end + if v3 == nil then + v3 = 333 + end + if v4 == nil then + v4 = 444 + end + end + local v5, v6, v7 + do + local _obj_0 = tb2 + local _tmp_2, _tmp_3 = func(), func2() + v5, v6, v7 = _obj_0['x-y-z'], _obj_0[_tmp_2][_tmp_3], _obj_0[_tmp_2][1] + end +end +do + local _obj_0 = tb + local value = _obj_0[name] + local value_meta = getmetatable(_obj_0)[name] +end +do + local tostring, add + do + local _obj_0 = getmetatable(tb) + tostring, add = _obj_0.__tostring, _obj_0.__add + if tostring == nil then + tostring = (function() + return "name" + end) + end + end + local _exp_0 = tb + do + local _tab_0 = "table" == type(_exp_0) + if _tab_0 then + local name, meta_field + do + local _obj_0 = getmetatable(_exp_0) + name = _obj_0.__name + meta_field = _obj_0["123"] + if name == nil then + name = "item" + end + end + if meta_field ~= nil then + return print(name, meta_field) + end + end + end +end diff --git a/spec/outputs/metatable.lua b/spec/outputs/metatable.lua index 6f5ceed..937136f 100644 --- a/spec/outputs/metatable.lua +++ b/spec/outputs/metatable.lua @@ -111,4 +111,37 @@ do ctor, update = _obj_0.new, _obj_0.update end end +local tb = { } +do + do + local _obj_0 = getmetatable(tb) + f = _obj_0["value" .. tostring(x < y)](_obj_0, 123, ...) + end + f((function(...) + local _obj_0 = getmetatable(tb) + return _obj_0['value'](_obj_0, 123, ...) + end)(...)) + do + local _obj_0 = getmetatable(tb) + _obj_0[ [[ value + 1 + ]]](_obj_0, 123, ...) + end + local _obj_0 = getmetatable(tb) + return _obj_0["value" .. tostring(x > y)](_obj_0, 123, ...) +end +do + f = getmetatable(tb):__value(123, ...) + f(getmetatable(tb):__value(123, ...)) + getmetatable(tb):__value(123, ...) + return getmetatable(tb):__value(123, ...) +end +do + f = getmetatable(tb).__value(123, ...) + f = getmetatable(tb)["value" .. tostring(x < y)](123, ...) + f(getmetatable(tb)['value'](123, ...)) + getmetatable(tb)[ [[ value +1]]](123, ...) + return getmetatable(tb)["value" .. tostring(x > y)](123, ...) +end return nil diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 386fa28..d8f6c95 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -459,18 +459,16 @@ AST_NODE(variable_pair) AST_MEMBER(variable_pair, &name) AST_END(variable_pair, "variable_pair"sv) -class DoubleString_t; -class SingleString_t; -class LuaString_t; +class String_t; AST_NODE(normal_pair) - ast_sel key; + ast_sel key; ast_sel value; AST_MEMBER(normal_pair, &key, &value) AST_END(normal_pair, "normal_pair"sv) AST_NODE(default_pair) - ast_sel key; + ast_sel key; ast_ptr sep; ast_ptr value; ast_ptr defVal; @@ -483,13 +481,13 @@ AST_NODE(meta_variable_pair) AST_END(meta_variable_pair, "meta_variable_pair"sv) AST_NODE(meta_normal_pair) - ast_sel key; + ast_sel key; ast_sel value; AST_MEMBER(meta_normal_pair, &key, &value) AST_END(meta_normal_pair, "meta_normal_pair"sv) AST_NODE(meta_default_pair) - ast_sel key; + ast_sel key; ast_ptr sep; ast_ptr value; ast_ptr defVal; @@ -502,7 +500,6 @@ AST_NODE(simple_table) AST_MEMBER(simple_table, &sep, &pairs) AST_END(simple_table, "simple_table"sv) -class String_t; class const_value_t; class ClassDecl_t; class unary_value_t; @@ -560,8 +557,8 @@ AST_LEAF(Metatable) AST_END(Metatable, "metatable"sv) AST_NODE(Metamethod) - ast_ptr name; - AST_MEMBER(Metamethod, &name) + ast_sel item; + AST_MEMBER(Metamethod, &item) AST_END(Metamethod, "metamethod"sv) AST_NODE(DotChainItem) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 17979ab..73b4ae9 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -59,7 +59,7 @@ namespace yue { typedef std::list str_list; -const std::string_view version = "0.14.5"sv; +const std::string_view version = "0.15.1"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -296,7 +296,7 @@ private: struct DestructItem { ast_ptr target; std::string targetVar; - std::string structure; + ast_ptr structure; ast_ptr defVal; }; @@ -304,6 +304,7 @@ private: ast_ptr value; std::string valueVar; std::list items; + ast_ptr inlineAssignment; }; enum class ExpUsage { @@ -614,6 +615,24 @@ private: return nullptr; } + ast_ptr newExp(SimpleValue_t* simpleValue, ast_node* x) { + auto value = x->new_ptr(); + value->item.set(simpleValue); + return newExp(value, x); + } + + ast_ptr newExp(String_t* string, ast_node* x) { + auto value = x->new_ptr(); + value->item.set(string); + return newExp(value, x); + } + + ast_ptr newExp(ChainValue_t* chainValue, ast_node* x) { + auto value = x->new_ptr(); + value->item.set(chainValue); + return newExp(value, x); + } + ast_ptr newExp(Value_t* value, ast_node* x) { auto unary = x->new_ptr(); unary->expos.push_back(value); @@ -772,7 +791,8 @@ private: HasEOP, HasKeyword, Macro, - Metatable + Metatable, + MetaFieldInvocation }; ChainType specialChainValue(ChainValue_t* chainValue) const { @@ -795,6 +815,8 @@ private: if (auto colonChain = ast_cast(item)) { if (ast_is(colonChain->name)) { type = ChainType::HasKeyword; + } else if (auto meta = colonChain->name.as(); meta && !meta->item.is()) { + return ChainType::MetaFieldInvocation; } } else if (ast_is(item)) { return ChainType::HasEOP; @@ -1013,9 +1035,7 @@ private: case id(): { auto simpleValue = x->new_ptr(); simpleValue->value.set(val); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); expList->exprs.push_back(exp); break; } @@ -1025,9 +1045,7 @@ private: tabLit->values.dup(tableBlock->values); auto simpleValue = x->new_ptr(); simpleValue->value.set(tabLit); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); expList->exprs.push_back(exp); break; } @@ -1072,9 +1090,7 @@ private: statement->appendix.set(nullptr); auto simpleValue = x->new_ptr(); simpleValue->value.set(ifNode); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); auto expList = x->new_ptr(); expList->exprs.push_back(exp); auto expListAssign = x->new_ptr(); @@ -1091,9 +1107,7 @@ private: comp->value.set(stmt); auto simpleValue = x->new_ptr(); simpleValue->value.set(comp); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); auto expList = x->new_ptr(); expList->exprs.push_back(exp); auto expListAssign = x->new_ptr(); @@ -1483,9 +1497,7 @@ private: args.push_back(_withVars.top()); } } else { - auto value = tmpChain->new_ptr(); - value->item.set(tmpChain); - transformExp(newExp(value, tmpChain), args, ExpUsage::Closure); + transformExp(newExp(tmpChain, tmpChain), args, ExpUsage::Closure); } if (vit == values.end()) { throw std::logic_error(_info.errorMessage("right value missing"sv, values.front())); @@ -1514,9 +1526,7 @@ private: auto newAssignment = x->new_ptr(); newAssignment->expList.set(toAst(objVar, x)); auto assign = x->new_ptr(); - auto value = tmpChain->new_ptr(); - value->item.set(tmpChain); - assign->values.push_back(newExp(value, tmpChain)); + assign->values.push_back(newExp(tmpChain, tmpChain)); newAssignment->action.set(assign); transformAssignment(newAssignment, temp); varName = objVar; @@ -1685,7 +1695,8 @@ private: auto expList = assignment->expList.get(); switch (type) { case ChainType::HasEOP: - case ChainType::EndWithColon: { + case ChainType::EndWithColon: + case ChainType::MetaFieldInvocation: { std::string preDefine = getPreDefineLine(assignment); transformChainValue(chainValue, out, ExpUsage::Assignment, expList); out.back().insert(0, preDefine); @@ -1714,7 +1725,7 @@ private: for (auto& destruct : info.destructures) { std::list, ast_ptr>> leftPairs; bool extraScope = false; - if (destruct.items.size() == 1) { + if (!destruct.inlineAssignment && destruct.items.size() == 1) { auto& pair = destruct.items.front(); if (pair.targetVar.empty() && pair.defVal) { extraScope = true; @@ -1725,21 +1736,13 @@ private: pair.targetVar = objVar; } else if (auto val = singleValueFrom(destruct.value); val->item.is()) { auto chainValue = static_cast(val->item.get()); - int added = 0; - if (!pair.structure.empty()) { - auto appendChain = toAst("x"s + pair.structure, x); - appendChain->items.pop_front(); - for (auto item : appendChain->items.objects()) { - chainValue->items.push_back(item); - added++; - } + auto newChain = val->item->new_ptr(); + newChain->items.dup(chainValue->items); + if (pair.structure) { + newChain->items.dup(pair.structure->items); } - auto newAssignment = assignmentFrom(pair.target, destruct.value, x); + auto newAssignment = assignmentFrom(pair.target, newExp(newChain, val->item), x); transformAssignment(newAssignment, temp); - while (added > 0) { - chainValue->items.pop_back(); - added--; - } if (pair.defVal) { bool isNil = false; if (auto v1 = singleValueFrom(pair.defVal)) { @@ -1782,7 +1785,10 @@ private: auto newAssignment = assignmentFrom(toAst(objVar, x), destruct.value, x); transformAssignment(newAssignment, temp); } - auto valueExp = toAst(objVar + pair.structure, x); + auto chain = pair.target->new_ptr(); + chain->items.push_back(toAst(objVar, chain)); + chain->items.dup(pair.structure->items); + auto valueExp = newExp(chain, pair.target); auto newAssignment = assignmentFrom(pair.target, valueExp, x); transformAssignment(newAssignment, temp); if (!isLocalValue) { @@ -1791,7 +1797,8 @@ private: temp.push_back(clearBuf()); } } else { - str_list values, defs; + str_list defs; + std::list> values; std::list names; pushScope(); for (auto& item : destruct.items) { @@ -1813,8 +1820,9 @@ private: } popScope(); if (_parser.match(destruct.valueVar) && isLocal(destruct.valueVar)) { + auto callable = toAst(destruct.valueVar, destruct.value); for (auto& v : values) { - v.insert(0, destruct.valueVar); + v->items.push_front(callable); } if (extraScope) { if (!defs.empty()) { @@ -1842,17 +1850,22 @@ private: auto targetVar = toAst(valVar, destruct.value); auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value); transformAssignment(newAssignment, temp); + auto callable = singleValueFrom(targetVar)->item.to()->items.front(); for (auto& v : values) { - v.insert(0, valVar); + v->items.push_front(callable); } } + if (destruct.inlineAssignment) { + transformAssignment(destruct.inlineAssignment, temp); + } if (optionalDestruct) { while (!names.empty()) { auto name = names.front(); names.pop_front(); - auto value = values.front(); + auto value = values.front().get(); + auto valueList = value->new_ptr(); + valueList->exprs.push_back(newExp(value, value)); values.pop_front(); - auto valueList = toAst(value, x); auto newAssignment = x->new_ptr(); auto assignList = x->new_ptr(); assignList->exprs.push_back(name); @@ -1863,7 +1876,10 @@ private: transformAssignment(newAssignment, temp); } } else { - auto valueList = toAst(join(values, ","sv), x); + auto valueList = x->new_ptr(); + for (const auto& v : values) { + valueList->exprs.push_back(newExp(v, v)); + } auto newAssignment = x->new_ptr(); auto assignList = x->new_ptr(); for (auto name : names) { @@ -1923,7 +1939,7 @@ private: std::list destructFromExp(ast_node* node, bool optional) { const node_container* tableItems = nullptr; - auto sep = optional ? "?"s : Empty; + ast_ptr sep = optional ? node->new_ptr() : nullptr; switch (node->getId()) { case id(): { auto item = singleValueFrom(node)->item.get(); @@ -1965,17 +1981,20 @@ private: if (ast_is(item) || item->getByPath()) { auto subPairs = destructFromExp(pair, optional); for (auto& p : subPairs) { - pairs.push_back({p.target, p.targetVar, - '[' + std::to_string(index) + ']' + sep + p.structure, - p.defVal}); + if (sep) p.structure->items.push_front(sep); + p.structure->items.push_front( + toAst(std::to_string(index), p.target)); + pairs.push_back(p); } } else { auto exp = static_cast(pair); auto varName = singleVariableFrom(exp, false); if (varName == "_"sv) break; + auto chain = exp->new_ptr(); + chain->items.push_back(toAst(std::to_string(index), exp)); pairs.push_back({exp, varName, - '[' + std::to_string(index) + ']', + chain, nullptr}); } break; @@ -1983,38 +2002,55 @@ private: case id(): { auto vp = static_cast(pair); auto name = _parser.toString(vp->name); - pairs.push_back({toAst(name, vp).get(), name, '.' + name, nullptr}); + auto chain = toAst('.' + name, vp->name); + pairs.push_back({toAst(name, vp).get(), + name, + chain, + nullptr}); break; } case id(): { auto np = static_cast(pair); - std::string keyName; + ast_ptr keyIndex; if (np->key) { - auto key = np->key->getByPath(); - if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); - keyName = _parser.toString(key); - if (LuaKeywords.find(keyName) != LuaKeywords.end()) { - keyName = "[\""s + keyName + "\"]"s; - } else { - keyName = "."s + keyName; - } + if (auto key = np->key->getByPath()) { + auto keyNameStr = _parser.toString(key); + if (LuaKeywords.find(keyNameStr) != LuaKeywords.end()) { + keyIndex = toAst('"' + keyNameStr + '"', key).get(); + } else { + keyIndex = toAst('.' + keyNameStr, key).get(); + } + } else if (auto key = np->key->getByPath()) { + auto callable = np->new_ptr(); + callable->item.set(key); + auto chainValue = np->new_ptr(); + chainValue->items.push_back(callable); + keyIndex = newExp(chainValue, np).get(); + } else if (auto key = np->key.as()) { + keyIndex = key; + } else if (auto key = np->key.as()) { + keyIndex = newExp(key, np->key).get(); + } else throw std::logic_error(_info.errorMessage("unsupported key for destructuring"sv, np)); } if (auto exp = np->value.as()) { - if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); + if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't do destructure value"sv, exp)); auto item = singleValueFrom(exp)->item.get(); if (ast_is(item) || item->getByPath()) { auto subPairs = destructFromExp(exp, optional); for (auto& p : subPairs) { - pairs.push_back({p.target, - p.targetVar, - keyName + sep + p.structure, - p.defVal}); + if (keyIndex) { + if (sep) p.structure->items.push_front(sep); + p.structure->items.push_front(keyIndex); + } + pairs.push_back(p); } } else { + auto chain = exp->new_ptr(); + if (keyIndex) chain->items.push_back(keyIndex); auto varName = singleVariableFrom(exp, false); pairs.push_back({exp, varName, - keyName, + chain, nullptr}); } break; @@ -2022,10 +2058,11 @@ private: if (np->value.is()) { auto subPairs = destructFromExp(np->value, optional); for (auto& p : subPairs) { - pairs.push_back({p.target, - p.targetVar, - keyName + sep + p.structure, - p.defVal}); + if (keyIndex) { + if (sep) p.structure->items.push_front(sep); + p.structure->items.push_front(keyIndex); + } + pairs.push_back(p); } } break; @@ -2035,10 +2072,9 @@ private: ++index; auto subPairs = destructFromExp(tb, optional); for (auto& p : subPairs) { - pairs.push_back({p.target, - p.targetVar, - '[' + std::to_string(index) + ']' + sep + p.structure, - p.defVal}); + if (sep) p.structure->items.push_front(sep); + p.structure->items.push_front(toAst(std::to_string(index), tb)); + pairs.push_back(p); } break; } @@ -2057,34 +2093,45 @@ private: auto varName = singleVariableFrom(exp, false); pairs.push_back({exp, varName, - '[' + std::to_string(index) + ']', + toAst('[' + std::to_string(index) + ']', value), dp->defVal}); } break; } - std::string keyName, valueStr; + auto chain = dp->new_ptr(); + std::string valueStr; if (dp->key) { - auto key = dp->key->getByPath(); - if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, dp)); - keyName = _parser.toString(key); - if (!dp->value) valueStr = keyName; - if (LuaKeywords.find(keyName) != LuaKeywords.end()) { - keyName = "[\""s + keyName + "\"]"s; - } else { - keyName = "."s + keyName; - } + if (auto key = dp->key->getByPath()) { + auto keyName = _parser.toString(key); + if (!dp->value) valueStr = keyName; + if (LuaKeywords.find(keyName) != LuaKeywords.end()) { + chain->items.push_back(toAst('"' + keyName + '"', key)); + } else { + chain->items.push_back(toAst('.' + keyName, key)); + } + } else if (auto key = dp->key->getByPath()) { + auto callable = dp->new_ptr(); + callable->item.set(key); + auto chainValue = dp->new_ptr(); + chainValue->items.push_back(callable); + chain->items.push_back(newExp(chainValue, dp)); + } else if (auto key = dp->key.as()) { + chain->items.push_back(newExp(key, dp)); + } else if (auto key = dp->key.as()) { + chain->items.push_back(key); + } else throw std::logic_error(_info.errorMessage("unsupported key for destructuring"sv, dp)); } if (auto exp = dp->value.get()) { if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); auto varName = singleVariableFrom(exp, false); pairs.push_back({exp, varName, - keyName, + chain, dp->defVal}); } else { pairs.push_back({toAst(valueStr, dp).get(), valueStr, - keyName, + chain, dp->defVal}); } break; @@ -2093,6 +2140,9 @@ private: auto mp = static_cast(pair); auto newPair = pair->new_ptr(); if (mp->key) { + if (!ast_is(mp->key)) { + throw std::logic_error(_info.errorMessage("destructuring with metatable accessed by expression is not supported."sv, mp->key)); + } auto key = _parser.toString(mp->key); _buf << "__"sv << key; auto newKey = toAst(clearBuf(), mp->key); @@ -2145,14 +2195,16 @@ private: if (!subMetaDestruct->values.empty()) { auto simpleValue = subMetaDestruct->new_ptr(); simpleValue->value.set(subMetaDestruct); - auto value = subMetaDestruct->new_ptr(); - value->item.set(simpleValue); - auto subPairs = destructFromExp(newExp(value, subMetaDestruct), optional); + auto subPairs = destructFromExp(newExp(simpleValue, subMetaDestruct), optional); for (const auto& p : subPairs) { - pairs.push_back({p.target, - p.targetVar, - ".#"s + (p.structure.empty() ? Empty : sep + p.structure), - p.defVal}); + if (!p.structure->items.empty()) { + if (sep) p.structure->items.push_front(sep); + } + auto mt = p.structure->new_ptr(); + auto dot = mt->new_ptr(); + dot->name.set(mt); + p.structure->items.push_front(dot); + pairs.push_back(p); } } return pairs; @@ -2258,6 +2310,12 @@ private: case id(): newPair->key.set(mp->key); break; + case id(): { + auto value = mp->new_ptr(); + value->item.set(mp->key); + newPair->key.set(newExp(value, mp)); + break; + } default: YUEE("AST node mismatch", mp->key); break; } } @@ -2289,9 +2347,7 @@ private: } auto simpleValue = tab->new_ptr(); simpleValue->value.set(tab); - auto value = tab->new_ptr(); - value->item.set(simpleValue); - auto pairs = destructFromExp(newExp(value, expr), optional); + auto pairs = destructFromExp(newExp(simpleValue, expr), optional); if (pairs.empty()) { throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); } @@ -2299,15 +2355,13 @@ private: if (!varDefOnly) { if (*j == nil) { for (auto& item : destruct.items) { - item.structure.clear(); + item.structure = nullptr; } } else if (tab == subMetaDestruct.get()) { auto p = destruct.value.get(); auto chainValue = toAst("getmetatable()", p); static_cast(chainValue->items.back())->args.push_back(destruct.value); - auto value = p->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, p); + auto exp = newExp(chainValue, p); destruct.value.set(exp); destruct.valueVar.clear(); } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) { @@ -2318,9 +2372,7 @@ private: callable->item.set(parens); auto chainValue = p->new_ptr(); chainValue->items.push_back(callable); - auto value = p->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, p); + auto exp = newExp(chainValue, p); destruct.value.set(exp); destruct.valueVar.clear(); } @@ -2346,6 +2398,51 @@ private: newAssign->action.set(assign); newAssignment = newAssign; } + if (!varDefOnly) { + pushScope(); + for (auto& des : destructs) { + for (const auto& item : des.items) { + for (auto node : item.structure->items.objects()) { + if (auto exp = ast_cast(node)) { + if (auto value = simpleSingleValueFrom(node)) { + if (ast_is(value->value)) { + continue; + } + } + if (auto value = singleValueFrom(exp); !value || !value->item.is()) { + auto var = singleVariableFrom(exp, false); + if (var.empty()) { + if (!des.inlineAssignment) { + des.inlineAssignment = x->new_ptr(); + auto expList = x->new_ptr(); + des.inlineAssignment->expList.set(expList); + auto assign = x->new_ptr(); + des.inlineAssignment->action.set(assign); + } + auto assignList = des.inlineAssignment->expList.get(); + auto assign = des.inlineAssignment->action.to(); + auto tmpVar = getUnusedName("_tmp_"sv); + addToScope(tmpVar); + auto tmpExp = toAst(tmpVar, exp); + assignList->exprs.push_back(tmpExp); + auto vExp = exp->new_ptr(); + vExp->pipeExprs.dup(exp->pipeExprs); + vExp->opValues.dup(exp->opValues); + vExp->nilCoalesed.set(exp->nilCoalesed); + exp->pipeExprs.clear(); + exp->pipeExprs.dup(tmpExp->pipeExprs); + exp->opValues.clear(); + exp->opValues.dup(tmpExp->opValues); + exp->nilCoalesed = tmpExp->nilCoalesed; + assign->values.push_back(vExp); + } + } + } + } + } + } + popScope(); + } return {std::move(destructs), newAssignment}; } @@ -2385,9 +2482,7 @@ private: tmpChain->items.push_back(item); } } - auto value = x->new_ptr(); - value->item.set(tmpChain); - auto exp = newExp(value, x); + auto exp = newExp(tmpChain, x); auto objVar = getUnusedName("_obj_"sv); auto newAssignment = x->new_ptr(); newAssignment->expList.set(toAst(objVar, x)); @@ -2518,9 +2613,7 @@ private: ns.clear(); auto simpleValue = x->new_ptr(); simpleValue->value.set(newIf); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); auto expList = x->new_ptr(); expList->exprs.push_back(exp); auto expListAssign = x->new_ptr(); @@ -3129,9 +3222,7 @@ private: funLit->body.set(body); auto simpleValue = x->new_ptr(); simpleValue->value.set(funLit); - auto value = x->new_ptr(); - value->item.set(simpleValue); - arg = newExp(value, x); + arg = newExp(simpleValue, x); } if (isChainValueCall(backcall->value)) { auto last = backcall->value->items.back(); @@ -3164,9 +3255,7 @@ private: auto newStmt = x->new_ptr(); { auto chainValue = backcall->value.get(); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); auto expList = x->new_ptr(); expList->exprs.push_back(exp); auto expListAssign = x->new_ptr(); @@ -3329,9 +3418,7 @@ private: } else { auto simpleValue = x->new_ptr(); simpleValue->value.set(last->content); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); assign->values.push_back(exp); } newAssignment->action.set(assign); @@ -3857,9 +3944,7 @@ private: callable->item.set(parens); auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); auto assignment = x->new_ptr(); assignment->expList.set(assignList); auto assign = x->new_ptr(); @@ -3949,9 +4034,7 @@ private: if (!newObj.empty()) { objVar = newObj; } else { - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); auto assign = x->new_ptr(); assign->values.push_back(exp); auto expListAssign = x->new_ptr(); @@ -3981,9 +4064,7 @@ private: } objVar = getUnusedName("_obj_"sv); } - auto value = x->new_ptr(); - value->item.set(partOne); - auto exp = newExp(value, x); + auto exp = newExp(partOne, x); auto assign = x->new_ptr(); assign->values.push_back(exp); auto expListAssign = x->new_ptr(); @@ -4004,9 +4085,7 @@ private: transformChainValue(partTwo, temp, ExpUsage::Common); break; case ExpUsage::Assignment: { - auto value = x->new_ptr(); - value->item.set(partTwo); - auto exp = newExp(value, x); + auto exp = newExp(partTwo, x); auto assign = x->new_ptr(); assign->values.push_back(exp); auto assignment = x->new_ptr(); @@ -4017,9 +4096,7 @@ private: } case ExpUsage::Return: case ExpUsage::Closure: { - auto value = x->new_ptr(); - value->item.set(partTwo); - auto exp = newExp(value, x); + auto exp = newExp(partTwo, x); auto ret = x->new_ptr(); auto expListLow = x->new_ptr(); expListLow->exprs.push_back(exp); @@ -4095,9 +4172,7 @@ private: auto baseVar = getUnusedName("_base_"sv); auto fnVar = getUnusedName("_fn_"sv); { - auto value = x->new_ptr(); - value->item.set(baseChain); - auto exp = newExp(value, x); + auto exp = newExp(baseChain, x); auto assign = x->new_ptr(); assign->values.push_back(exp); auto assignment = x->new_ptr(); @@ -4183,26 +4258,124 @@ private: for (auto it = chainList.begin(); it != opIt; ++it) { chain->items.push_back(*it); } - auto value = x->new_ptr(); - value->item.set(chain); - auto exp = newExp(value, x); - - chain = toAst("getmetatable()"sv, x); - ast_to(chain->items.back())->args.push_back(exp); + { + auto exp = newExp(chain, x); + chain = toAst("getmetatable()"sv, x); + ast_to(chain->items.back())->args.push_back(exp); + } switch ((*opIt)->getId()) { case id(): { auto colon = static_cast(*opIt); auto meta = colon->name.to(); - auto newColon = toAst("\\__"s + _parser.toString(meta->name), x); - chain->items.push_back(newColon); + switch (meta->item->getId()) { + case id(): { + auto newColon = toAst("\\__"s + _parser.toString(meta->item), x); + chain->items.push_back(newColon); + break; + } + case id(): + case id(): { + str_list temp; + std::string* funcStart = nullptr; + if (usage == ExpUsage::Closure) { + _enableReturn.push(true); + pushAnonVarArg(); + funcStart = &temp.emplace_back(); + pushScope(); + } else if (usage != ExpUsage::Return) { + temp.push_back(indent() + "do"s + nll(x)); + pushScope(); + } + auto var = getUnusedName("_obj_"sv); + auto target = toAst(var, x); + { + auto assignment = assignmentFrom(target, newExp(chain, x), x); + transformAssignment(assignment, temp); + } + auto newChain = toAst(var, x); + if (auto str = meta->item.as()) { + newChain->items.push_back(newExp(str, x)); + } else { + newChain->items.push_back(meta->item); + } + auto newChainExp = newExp(newChain, x); + for (auto it = ++opIt; it != chainList.end(); ++it) { + newChain->items.push_back(*it); + } + auto last = newChain->items.back(); + if (ast_is(last)) { + if (auto invoke = ast_cast(last)) { + invoke->args.push_front(target); + } else { + ast_to(last)->args.push_front(target); + } + } + switch (usage) { + case ExpUsage::Closure: { + auto returnNode = x->new_ptr(); + auto values = x->new_ptr(); + values->exprs.push_back(newChainExp); + returnNode->valueList.set(values); + transformReturn(returnNode, temp); + popScope(); + *funcStart = anonFuncStart() + nll(x); + temp.push_back(indent() + anonFuncEnd()); + popAnonVarArg(); + _enableReturn.pop(); + break; + } + case ExpUsage::Return: { + auto returnNode = x->new_ptr(); + auto values = x->new_ptr(); + values->exprs.push_back(newChainExp); + returnNode->valueList.set(values); + transformReturn(returnNode, temp); + break; + } + case ExpUsage::Assignment: { + auto assignment = x->new_ptr(); + assignment->expList.set(assignList); + auto assign = x->new_ptr(); + assign->values.push_back(newChainExp); + assignment->action.set(assign); + transformAssignment(assignment, temp); + popScope(); + temp.push_back(indent() + "end"s + nlr(x)); + break; + } + case ExpUsage::Common: + transformExp(newChainExp, temp, usage); + popScope(); + temp.push_back(indent() + "end"s + nlr(x)); + break; + } + out.push_back(join(temp)); + return true; + } + default: YUEE("AST node mismatch", meta->item); break; + } break; } case id(): { auto dot = static_cast(*opIt); if (dot->name.is()) break; auto meta = dot->name.to(); - auto newDot = toAst(".__"s + _parser.toString(meta->name), x); - chain->items.push_back(newDot); + switch (meta->item->getId()) { + case id(): { + auto newDot = toAst(".__"s + _parser.toString(meta->item), x); + chain->items.push_back(newDot); + break; + } + case id(): + chain->items.push_back(meta->item); + break; + case id(): { + auto str = static_cast(meta->item.get()); + chain->items.push_back(newExp(str, x)); + break; + } + default: YUEE("AST node mismatch", meta->item); break; + } break; } } @@ -4276,9 +4449,7 @@ private: for (auto i = chainList.begin(); i != current; ++i) { chainValue->items.push_back(*i); } - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); callVar = singleVariableFrom(exp, true); if (callVar.empty()) { callVar = getUnusedName("_call_"s); @@ -4310,9 +4481,7 @@ private: for (auto i = next; i != chainList.end(); ++i) { chainValue->items.push_back(*i); } - auto value = x->new_ptr(); - value->item.set(chainValue); - nexp = newExp(value, x); + nexp = newExp(chainValue, x); auto expList = x->new_ptr(); expList->exprs.push_back(nexp); auto expListAssign = x->new_ptr(); @@ -4342,9 +4511,7 @@ private: funLit->body.set(body); auto simpleValue = x->new_ptr(); simpleValue->value.set(funLit); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = newExp(value, x); + auto exp = newExp(simpleValue, x); auto paren = x->new_ptr(); paren->expr.set(exp); auto callable = x->new_ptr(); @@ -4679,9 +4846,7 @@ private: for (; it != chainList.end(); ++it) { newChain->items.push_back(*it); } - auto value = x->new_ptr(); - value->item.set(newChain); - exp = newExp(value, x); + exp = newExp(newChain, x); } if (usage == ExpUsage::Common) { auto expList = x->new_ptr(); @@ -4961,9 +5126,7 @@ private: callable->item.set(selfName); auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, key); + auto exp = newExp(chainValue, key); chainItem = exp.get(); } chainValue->items.push_back(chainItem); @@ -5034,7 +5197,7 @@ private: case id(): { auto metaVarPair = static_cast(item); auto nameStr = _parser.toString(metaVarPair->name); - auto assignment = toAst(tableVar + '.' + nameStr + "#="s + nameStr, item); + auto assignment = toAst(tableVar + ".<"s + nameStr + ">="s + nameStr, item); transformAssignment(assignment, temp); break; } @@ -5051,8 +5214,10 @@ private: break; } case id(): { - auto dotItem = toAst(".#"sv, key); - chainValue->items.push_back(dotItem); + auto mt = key->new_ptr(); + auto dot = mt->new_ptr(); + dot->name.set(mt); + chainValue->items.push_back(dot); chainValue->items.push_back(key); break; } @@ -5158,6 +5323,11 @@ private: case id(): newPair->key.set(mp->key); break; + case id(): { + auto str = static_cast(mp->key.get()); + newPair->key.set(newExp(str, mp)); + break; + } default: YUEE("AST node mismatch", mp->key); break; } newPair->value.set(mp->value); @@ -5504,9 +5674,7 @@ private: for (auto& pair : destructPairs) { auto sValue = x->new_ptr(); sValue->value.set(pair.first); - auto value = x->new_ptr(); - value->item.set(sValue); - auto exp = newExp(value, x); + auto exp = newExp(sValue, x); auto expList = x->new_ptr(); expList->exprs.push_back(exp); auto assign = x->new_ptr(); @@ -5918,18 +6086,26 @@ private: transformExp(static_cast(key), temp, ExpUsage::Closure); temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']'; break; - case id(): - transformDoubleString(static_cast(key), temp); - temp.back() = '[' + temp.back() + ']'; - break; - case id(): - transformSingleString(static_cast(key), temp); - temp.back() = '[' + temp.back() + ']'; - break; - case id(): - transformLuaString(static_cast(key), temp); - temp.back() = "[ "s + temp.back() + ']'; + case id(): { + auto strNode = static_cast(key); + auto str = strNode->str.get(); + switch (str->getId()) { + case id(): + transformDoubleString(static_cast(str), temp); + temp.back() = '[' + temp.back() + ']'; + break; + case id(): + transformSingleString(static_cast(str), temp); + temp.back() = '[' + temp.back() + ']'; + break; + case id(): + transformLuaString(static_cast(str), temp); + temp.back() = "[ "s + temp.back() + ']'; + break; + default: YUEE("AST node mismatch", str); break; + } break; + } default: YUEE("AST node mismatch", key); break; } auto value = pair->value.get(); @@ -6308,6 +6484,8 @@ private: if (auto name = mtPair->key.as()) { auto nameStr = _parser.toString(name); normal_pair->key.set(toAst("__"s + nameStr, keyValue)); + } else if (auto str = mtPair->key.as()) { + normal_pair->key.set(newExp(str, str)); } else { normal_pair->key.set(mtPair->key); } @@ -6624,9 +6802,7 @@ private: callable->item.set(name); auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); expList->exprs.push_back(exp); } auto assignment = x->new_ptr(); @@ -6979,18 +7155,14 @@ private: auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); chainValue->items.push_back(dotChainItem); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); assign->values.push_back(exp); } auto callable = x->new_ptr(); callable->item.set(var); auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); expList->exprs.push_back(exp); break; } @@ -7004,18 +7176,14 @@ private: auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); chainValue->items.push_back(colonChain); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); assign->values.push_back(exp); } auto callable = x->new_ptr(); callable->item.set(var); auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); expList->exprs.push_back(exp); break; } @@ -7507,9 +7675,7 @@ private: callable->item.set(name); auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = newExp(value, x); + auto exp = newExp(chainValue, x); expList->exprs.push_back(exp); } auto assignment = x->new_ptr(); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index e5209ef..153babe 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -351,7 +351,7 @@ YueParser::YueParser() { unary_operator = expr('-') >> not_(set(">=") | space_one) | - expr('#') >> not_(':') | + expr('#') | expr('~') >> not_(expr('=') | space_one) | expr("not") >> not_(AlphaNum); unary_exp = *(Space >> unary_operator) >> expo_exp; @@ -435,8 +435,9 @@ YueParser::YueParser() { FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | (sym('!') >> not_(expr('='))); - Metatable = expr('#'); - Metamethod = Name >> expr('#'); + meta_index = Name | Index | String; + Metatable = expr('<') >> sym('>'); + Metamethod = expr('<') >> Space >> meta_index >> sym('>'); existential_op = expr('?') >> not_(expr('?')); table_appending_op = expr("[]"); @@ -453,8 +454,8 @@ YueParser::YueParser() { Index = symx('[') >> not_('[') >> Exp >> sym(']'); ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; - DotChainItem = symx('.') >> (Name >> not_('#') | Metatable | Metamethod); - ColonChainItem = (expr('\\') | expr("::")) >> ((LuaKeyword | Name) >> not_('#') | Metamethod); + DotChainItem = symx('.') >> (Name | Metatable | Metamethod); + ColonChainItem = (expr('\\') | expr("::")) >> (LuaKeyword | Name | Metamethod); invoke_chain = Invoke >> -existential_op >> -ChainItems; ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; @@ -542,26 +543,31 @@ YueParser::YueParser() { return true; })) >> not_(Space >> statement_appendix); - variable_pair = sym(':') >> Variable >> not_('#'); + variable_pair = sym(':') >> Variable; normal_pair = ( KeyName | sym('[') >> not_('[') >> Exp >> sym(']') | - Space >> DoubleString | - Space >> SingleString | - Space >> LuaString + Space >> String ) >> symx(':') >> not_(':') >> (Exp | TableBlock | +SpaceBreak >> Exp); - default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> exp_not_tab | exp_not_tab >> Seperator) >> sym('=') >> Exp; + default_pair = ( + sym(':') >> Variable >> Seperator | + KeyName >> symx(':') >> not_(':') >> Seperator >> exp_not_tab | + Space >> String >> symx(':') >> not_(':') >> Seperator >> exp_not_tab | + exp_not_tab >> Seperator) >> sym('=') >> Exp; - meta_variable_pair = sym(':') >> Variable >> expr('#'); + meta_variable_pair = sym(":<") >> Space >> Variable >> sym('>'); - meta_normal_pair = Space >> -(Name | symx('[') >> not_('[') >> Exp >> sym(']')) >> expr("#:") >> + meta_normal_pair = sym('<') >> Space >> -meta_index >> sym(">:") >> (Exp | TableBlock | +(SpaceBreak) >> Exp); - meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | Space >> -Name >> expr("#:") >> Seperator >> exp_not_tab) >> sym('=') >> Exp; + meta_default_pair = ( + sym(":<") >> Space >> Variable >> sym('>') >> Seperator | + sym('<') >> Space >> -meta_index >> sym(">:") >> Seperator >> exp_not_tab + ) >> sym('=') >> Exp; KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; KeyValueList = KeyValue >> *(sym(',') >> KeyValue); diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index dd577b4..f83f1b9 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -172,6 +172,7 @@ private: rule ChainItem; rule chain_line; rule chain_block; + rule meta_index; rule Index; rule invoke_chain; rule TableValue; -- cgit v1.2.3-55-g6feb