aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-02-14 15:35:54 +0800
committerLi Jin <dragon-fly@qq.com>2022-02-14 15:35:54 +0800
commitddb0b9deb720368a425d00bce0c0352469b55911 (patch)
tree8924f0a6e4d851c2f8545efba2d42c43581fd090
parent2c2cad4b4d3680bb30474b38ebed0f938e82636e (diff)
downloadyuescript-ddb0b9deb720368a425d00bce0c0352469b55911.tar.gz
yuescript-ddb0b9deb720368a425d00bce0c0352469b55911.tar.bz2
yuescript-ddb0b9deb720368a425d00bce0c0352469b55911.zip
fixing issue #77. change table appending syntax to: tb[] = 1
-rw-r--r--spec/inputs/syntax.yue17
-rw-r--r--spec/outputs/syntax.lua34
-rwxr-xr-xsrc/yuescript/yue_ast.h5
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp193
-rwxr-xr-xsrc/yuescript/yue_parser.cpp6
-rwxr-xr-xsrc/yuescript/yue_parser.h1
6 files changed, 147 insertions, 109 deletions
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue
index 67d3a27..e7f0a8d 100644
--- a/spec/inputs/syntax.yue
+++ b/spec/inputs/syntax.yue
@@ -188,16 +188,25 @@ a.b[1].c[2 + 3] += 1
188with tb 188with tb
189 .a.c += 1 189 .a.c += 1
190 190
191tb #= 10 191tb[] = 10
192a.b.c #= 1 192a.b.c[] = 1
193x #= if v 193x[] = if v
194 1 194 1
195else 195else
196 2 196 2
197with tb 197with tb
198 .b.c #= with vec 198 .b.c[] = with vec
199 .x = 1 199 .x = 1
200 .y = 2 200 .y = 2
201a
202 .b.c
203 .d\f!
204 .g[] = 1
205
206tb = {}
207tb[] = 1
208tb[] = 2
209tb[] = 3
201 210
202x = 0 211x = 0
203_ = (if ntype(v) == "fndef" then x += 1) for v in *values 212_ = (if ntype(v) == "fndef" then x += 1) for v in *values
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua
index 457f1e1..701361e 100644
--- a/spec/outputs/syntax.lua
+++ b/spec/outputs/syntax.lua
@@ -195,10 +195,14 @@ 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
197end 197end
198local _obj_2 = tb 198do
199_obj_2[#_obj_2 + 1] = 10 199 local _obj_2 = tb
200local _obj_3 = a.b.c 200 _obj_2[#_obj_2 + 1] = 10
201_obj_3[#_obj_3 + 1] = 1 201end
202do
203 local _obj_2 = a.b.c
204 _obj_2[#_obj_2 + 1] = 1
205end
202if v then 206if v then
203 x[#x + 1] = 1 207 x[#x + 1] = 1
204else 208else
@@ -206,14 +210,24 @@ else
206end 210end
207do 211do
208 local _with_0 = tb 212 local _with_0 = tb
209 local _obj_4 = _with_0.b.c
210 do 213 do
211 local _with_1 = vec 214 local _obj_2 = _with_0.b.c
212 _with_1.x = 1 215 do
213 _with_1.y = 2 216 local _with_1 = vec
214 _obj_4[#_obj_4 + 1] = _with_1 217 _with_1.x = 1
218 _with_1.y = 2
219 _obj_2[#_obj_2 + 1] = _with_1
220 end
215 end 221 end
216end 222end
223do
224 local _obj_2 = a.b.c.d:f().g
225 _obj_2[#_obj_2 + 1] = 1
226end
227local tb = { }
228tb[#tb + 1] = 1
229tb[#tb + 1] = 2
230tb[#tb + 1] = 3
217x = 0 231x = 0
218local _list_0 = values 232local _list_0 = values
219for _index_0 = 1, #_list_0 do 233for _index_0 = 1, #_list_0 do
@@ -231,7 +245,7 @@ hello = {
231 ["function"] = "okay", 245 ["function"] = "okay",
232 good = 230203 246 good = 230203
233} 247}
234local tb = { 248tb = {
235 ["do"] = b, 249 ["do"] = b,
236 (function() 250 (function()
237 return { 251 return {
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 7762c91..79e35a5 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -561,11 +561,14 @@ AST_END(Invoke)
561AST_LEAF(existential_op) 561AST_LEAF(existential_op)
562AST_END(existential_op) 562AST_END(existential_op)
563 563
564AST_LEAF(table_appending_op)
565AST_END(table_appending_op)
566
564class InvokeArgs_t; 567class InvokeArgs_t;
565 568
566AST_NODE(ChainValue) 569AST_NODE(ChainValue)
567 ast_ptr<true, Seperator_t> sep; 570 ast_ptr<true, Seperator_t> sep;
568 ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t> items; 571 ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t, table_appending_op_t> items;
569 AST_MEMBER(ChainValue, &sep, &items) 572 AST_MEMBER(ChainValue, &sep, &items)
570AST_END(ChainValue) 573AST_END(ChainValue)
571 574
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 6617ec5..6bc9fe8 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -60,7 +60,7 @@ using namespace parserlib;
60 60
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.9.9"sv; 63const std::string_view version = "0.9.10"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class YueCompilerImpl {
@@ -809,6 +809,7 @@ private:
809 switch (lastItem->getId()) { 809 switch (lastItem->getId()) {
810 case id<DotChainItem_t>(): 810 case id<DotChainItem_t>():
811 case id<Exp_t>(): 811 case id<Exp_t>():
812 case id<table_appending_op_t>():
812 return true; 813 return true;
813 } 814 }
814 } 815 }
@@ -1212,25 +1213,52 @@ private:
1212 BREAK_IF(!value); 1213 BREAK_IF(!value);
1213 auto chainValue = value->item.as<ChainValue_t>(); 1214 auto chainValue = value->item.as<ChainValue_t>();
1214 BREAK_IF(!chainValue); 1215 BREAK_IF(!chainValue);
1215 auto dot = ast_cast<DotChainItem_t>(chainValue->items.back()); 1216 str_list temp;
1216 BREAK_IF(!dot); 1217 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) {
1217 BREAK_IF(!dot->name.is<Metatable_t>()); 1218 BREAK_IF(!dot->name.is<Metatable_t>());
1218 str_list args; 1219 str_list args;
1219 chainValue->items.pop_back(); 1220 chainValue->items.pop_back();
1220 if (chainValue->items.empty()) { 1221 if (chainValue->items.empty()) {
1221 if (_withVars.empty()) { 1222 if (_withVars.empty()) {
1222 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); 1223 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x));
1224 } else {
1225 args.push_back(_withVars.top());
1226 }
1223 } else { 1227 } else {
1224 args.push_back(_withVars.top()); 1228 transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure);
1225 } 1229 }
1226 } else { 1230 if (vit != values.end()) transformAssignItem(*vit, args);
1227 transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure); 1231 else args.push_back("nil"s);
1228 } 1232 _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x);
1229 if (vit != values.end()) transformAssignItem(*vit, args); 1233 temp.push_back(clearBuf());
1230 else args.push_back("nil"s); 1234 } else if (ast_is<table_appending_op_t>(chainValue->items.back())) {
1231 _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); 1235 chainValue->items.pop_back();
1232 str_list temp; 1236 auto varName = singleVariableFrom(chainValue);
1233 temp.push_back(clearBuf()); 1237 bool isScoped = false;
1238 if (varName.empty() || !isLocal(varName)) {
1239 isScoped = true;
1240 temp.push_back(indent() + "do"s + nll(x));
1241 pushScope();
1242 auto objVar = getUnusedName("_obj_"sv);
1243 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1244 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
1245 auto assign = x->new_ptr<Assign_t>();
1246 assign->values.push_back(*it);
1247 newAssignment->action.set(assign);
1248 transformAssignment(newAssignment, temp);
1249 varName = objVar;
1250 }
1251 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1252 newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x));
1253 auto assign = x->new_ptr<Assign_t>();
1254 assign->values.push_back(*vit);
1255 newAssignment->action.set(assign);
1256 transformAssignment(newAssignment, temp);
1257 if (isScoped) {
1258 popScope();
1259 temp.push_back(indent() + "end"s + nlr(x));
1260 }
1261 } else break;
1234 auto newExpList = x->new_ptr<ExpList_t>(); 1262 auto newExpList = x->new_ptr<ExpList_t>();
1235 auto newAssign = x->new_ptr<Assign_t>(); 1263 auto newAssign = x->new_ptr<Assign_t>();
1236 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1264 auto newAssignment = x->new_ptr<ExpListAssign_t>();
@@ -1243,7 +1271,7 @@ private:
1243 if (value != *vit) newAssign->values.push_back(value); 1271 if (value != *vit) newAssign->values.push_back(value);
1244 } 1272 }
1245 if (newExpList->exprs.empty() && newAssign->values.empty()) { 1273 if (newExpList->exprs.empty() && newAssign->values.empty()) {
1246 out.push_back(temp.back()); 1274 out.push_back(join(temp));
1247 return; 1275 return;
1248 } 1276 }
1249 if (newExpList->exprs.size() < newAssign->values.size()) { 1277 if (newExpList->exprs.size() < newAssign->values.size()) {
@@ -2016,81 +2044,67 @@ private:
2016 if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); 2044 if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp));
2017 auto chain = leftValue->item.as<ChainValue_t>(); 2045 auto chain = leftValue->item.as<ChainValue_t>();
2018 if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, chain)); 2046 if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, chain));
2019 auto op = _parser.toString(update->op); 2047 BLOCK_START
2020 { 2048 {
2021 auto dot = ast_cast<DotChainItem_t>(chain->items.back()); 2049 auto dot = ast_cast<DotChainItem_t>(chain->items.back());
2022 if (dot && dot->name.is<Metatable_t>()) { 2050 if (dot && dot->name.is<Metatable_t>()) {
2023 throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); 2051 throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp));
2024 } 2052 }
2025 BLOCK_START 2053 BREAK_IF(chain->items.size() < 2);
2026 if (op == "#"sv) { 2054 if (chain->items.size() == 2) {
2027 auto varName = singleVariableFrom(chain); 2055 if (auto callable = ast_cast<Callable_t>(chain->items.front())) {
2028 BREAK_IF(!varName.empty() && isLocal(varName)); 2056 ast_node* var = callable->item.as<Variable_t>();
2029 auto objVar = getUnusedName("_obj_"sv); 2057 if (auto self = callable->item.as<SelfName_t>()) {
2030 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 2058 var = self->name.as<self_t>();
2031 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
2032 auto assign = x->new_ptr<Assign_t>();
2033 assign->values.push_back(leftExp);
2034 newAssignment->action.set(assign);
2035 transformAssignment(newAssignment, temp);
2036 chain->items.clear();
2037 chain->items.push_back(toAst<Callable_t>(objVar, x));
2038 } else {
2039 BREAK_IF(chain->items.size() < 2);
2040 if (chain->items.size() == 2) {
2041 if (auto callable = ast_cast<Callable_t>(chain->items.front())) {
2042 ast_node* var = callable->item.as<Variable_t>();
2043 if (auto self = callable->item.as<SelfName_t>()) {
2044 var = self->name.as<self_t>();
2045 }
2046 BREAK_IF(var && isLocal(_parser.toString(var)));
2047 } 2059 }
2060 BREAK_IF(var && isLocal(_parser.toString(var)));
2048 } 2061 }
2049 auto tmpChain = x->new_ptr<ChainValue_t>();
2050 ast_ptr<false, ast_node> ptr(chain->items.back());
2051 for (auto item : chain->items.objects()) {
2052 if (item != ptr) {
2053 tmpChain->items.push_back(item);
2054 }
2055 }
2056 auto value = x->new_ptr<Value_t>();
2057 value->item.set(tmpChain);
2058 auto exp = newExp(value, x);
2059 auto objVar = getUnusedName("_obj_"sv);
2060 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2061 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
2062 auto assign = x->new_ptr<Assign_t>();
2063 assign->values.push_back(exp);
2064 newAssignment->action.set(assign);
2065 transformAssignment(newAssignment, temp);
2066 chain->items.clear();
2067 chain->items.push_back(toAst<Callable_t>(objVar, x));
2068 chain->items.push_back(ptr);
2069 } 2062 }
2070 BLOCK_END
2071 auto tmpChain = x->new_ptr<ChainValue_t>(); 2063 auto tmpChain = x->new_ptr<ChainValue_t>();
2064 ast_ptr<false, ast_node> ptr(chain->items.back());
2072 for (auto item : chain->items.objects()) { 2065 for (auto item : chain->items.objects()) {
2073 bool itemAdded = false; 2066 if (item != ptr) {
2074 BLOCK_START 2067 tmpChain->items.push_back(item);
2075 auto exp = ast_cast<Exp_t>(item); 2068 }
2076 BREAK_IF(!exp);
2077 auto var = singleVariableFrom(exp);
2078 BREAK_IF(!var.empty());
2079 auto upVar = getUnusedName("_update_"sv);
2080 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2081 newAssignment->expList.set(toAst<ExpList_t>(upVar, x));
2082 auto assign = x->new_ptr<Assign_t>();
2083 assign->values.push_back(exp);
2084 newAssignment->action.set(assign);
2085 transformAssignment(newAssignment, temp);
2086 tmpChain->items.push_back(toAst<Exp_t>(upVar, x));
2087 itemAdded = true;
2088 BLOCK_END
2089 if (!itemAdded) tmpChain->items.push_back(item);
2090 } 2069 }
2070 auto value = x->new_ptr<Value_t>();
2071 value->item.set(tmpChain);
2072 auto exp = newExp(value, x);
2073 auto objVar = getUnusedName("_obj_"sv);
2074 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2075 newAssignment->expList.set(toAst<ExpList_t>(objVar, x));
2076 auto assign = x->new_ptr<Assign_t>();
2077 assign->values.push_back(exp);
2078 newAssignment->action.set(assign);
2079 transformAssignment(newAssignment, temp);
2091 chain->items.clear(); 2080 chain->items.clear();
2092 chain->items.dup(tmpChain->items); 2081 chain->items.push_back(toAst<Callable_t>(objVar, x));
2082 chain->items.push_back(ptr);
2093 } 2083 }
2084 BLOCK_END
2085 auto tmpChain = x->new_ptr<ChainValue_t>();
2086 for (auto item : chain->items.objects()) {
2087 bool itemAdded = false;
2088 BLOCK_START
2089 auto exp = ast_cast<Exp_t>(item);
2090 BREAK_IF(!exp);
2091 auto var = singleVariableFrom(exp);
2092 BREAK_IF(!var.empty());
2093 auto upVar = getUnusedName("_update_"sv);
2094 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2095 newAssignment->expList.set(toAst<ExpList_t>(upVar, x));
2096 auto assign = x->new_ptr<Assign_t>();
2097 assign->values.push_back(exp);
2098 newAssignment->action.set(assign);
2099 transformAssignment(newAssignment, temp);
2100 tmpChain->items.push_back(toAst<Exp_t>(upVar, x));
2101 itemAdded = true;
2102 BLOCK_END
2103 if (!itemAdded) tmpChain->items.push_back(item);
2104 }
2105 chain->items.clear();
2106 chain->items.dup(tmpChain->items);
2107 auto op = _parser.toString(update->op);
2094 if (op == "??"sv) { 2108 if (op == "??"sv) {
2095 auto defs = getPredefine(assignment); 2109 auto defs = getPredefine(assignment);
2096 auto rightExp = x->new_ptr<Exp_t>(); 2110 auto rightExp = x->new_ptr<Exp_t>();
@@ -2101,16 +2115,6 @@ private:
2101 if (!defs.empty()) temp.back().insert(0, defs + nll(x)); 2115 if (!defs.empty()) temp.back().insert(0, defs + nll(x));
2102 out.push_back(join(temp)); 2116 out.push_back(join(temp));
2103 return; 2117 return;
2104 } else if (op == "#"sv) {
2105 auto left = _parser.toString(chain->items.front());
2106 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2107 newAssignment->expList.set(toAst<ExpList_t>(left + "[#"s + left + "+1]"s, x));
2108 auto assign = x->new_ptr<Assign_t>();
2109 assign->values.push_back(update->value);
2110 newAssignment->action.set(assign);
2111 transformAssignment(newAssignment, temp);
2112 out.push_back(join(temp));
2113 return;
2114 } 2118 }
2115 auto defs = getPredefine(assignment); 2119 auto defs = getPredefine(assignment);
2116 transformValue(leftValue, temp); 2120 transformValue(leftValue, temp);
@@ -3970,6 +3974,9 @@ private:
3970 temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']'; 3974 temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']';
3971 break; 3975 break;
3972 case id<InvokeArgs_t>(): transformInvokeArgs(static_cast<InvokeArgs_t*>(item), temp); break; 3976 case id<InvokeArgs_t>(): transformInvokeArgs(static_cast<InvokeArgs_t*>(item), temp); break;
3977 case id<table_appending_op_t>():
3978 transform_table_appending_op(static_cast<table_appending_op_t*>(item), temp);
3979 break;
3973 default: YUEE("AST node mismatch", item); break; 3980 default: YUEE("AST node mismatch", item); break;
3974 } 3981 }
3975 } 3982 }
@@ -4391,6 +4398,10 @@ private:
4391 throw std::logic_error(_info.errorMessage("slice syntax not supported here"sv, slice)); 4398 throw std::logic_error(_info.errorMessage("slice syntax not supported here"sv, slice));
4392 } 4399 }
4393 4400
4401 void transform_table_appending_op(table_appending_op_t* op, str_list&) {
4402 throw std::logic_error(_info.errorMessage("table appending syntax not supported here"sv, op));
4403 }
4404
4394 void transformInvoke(Invoke_t* invoke, str_list& out) { 4405 void transformInvoke(Invoke_t* invoke, str_list& out) {
4395 str_list temp; 4406 str_list temp;
4396 for (auto arg : invoke->args.objects()) { 4407 for (auto arg : invoke->args.objects()) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 772ae08..3d12190 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -324,8 +324,7 @@ YueParser::YueParser() {
324 expr("|") | 324 expr("|") |
325 expr(">>") | 325 expr(">>") |
326 expr("<<") | 326 expr("<<") |
327 expr("??") | 327 expr("??");
328 expr("#");
329 328
330 Update = Space >> update_op >> expr("=") >> Exp; 329 Update = Space >> update_op >> expr("=") >> Exp;
331 330
@@ -382,7 +381,7 @@ YueParser::YueParser() {
382 return st->chainBlockStack.empty() || st->chainBlockStack.top(); 381 return st->chainBlockStack.empty() || st->chainBlockStack.top();
383 }) >> +SpaceBreak >> Advance >> ensure( 382 }) >> +SpaceBreak >> Advance >> ensure(
384 chain_line >> *(+SpaceBreak >> chain_line), PopIndent); 383 chain_line >> *(+SpaceBreak >> chain_line), PopIndent);
385 ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block); 384 ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op;
386 385
387 simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); 386 simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue);
388 Value = SimpleValue | simple_table | ChainValue | String; 387 Value = SimpleValue | simple_table | ChainValue | String;
@@ -427,6 +426,7 @@ YueParser::YueParser() {
427 Metamethod = Name >> expr('#'); 426 Metamethod = Name >> expr('#');
428 427
429 existential_op = expr('?') >> not_(expr('?')); 428 existential_op = expr('?') >> not_(expr('?'));
429 table_appending_op = expr("[]");
430 chain_call = (Callable | String) >> -existential_op >> ChainItems; 430 chain_call = (Callable | String) >> -existential_op >> ChainItems;
431 chain_item = and_(set(".\\")) >> ChainItems; 431 chain_item = and_(set(".\\")) >> ChainItems;
432 chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; 432 chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems;
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index e128e82..7dea126 100755
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -277,6 +277,7 @@ private:
277 AST_RULE(Slice) 277 AST_RULE(Slice)
278 AST_RULE(Invoke) 278 AST_RULE(Invoke)
279 AST_RULE(existential_op) 279 AST_RULE(existential_op)
280 AST_RULE(table_appending_op)
280 AST_RULE(TableLit) 281 AST_RULE(TableLit)
281 AST_RULE(TableBlock) 282 AST_RULE(TableBlock)
282 AST_RULE(TableBlockIndent) 283 AST_RULE(TableBlockIndent)