aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2024-10-31 16:29:10 +0800
committerLi Jin <dragon-fly@qq.com>2024-10-31 16:29:19 +0800
commit37c8f0a862a570af707809d530b3284c6ff9229c (patch)
tree78de6d4bdfacd30602823cf05b437dd506572247
parent3387abbfe072cbfe1ed1e7a3d71668603831591b (diff)
downloadyuescript-37c8f0a862a570af707809d530b3284c6ff9229c.tar.gz
yuescript-37c8f0a862a570af707809d530b3284c6ff9229c.tar.bz2
yuescript-37c8f0a862a570af707809d530b3284c6ff9229c.zip
Fixed issue #175 and #177.
-rw-r--r--spec/inputs/macro.yue15
-rw-r--r--spec/outputs/macro.lua15
-rw-r--r--src/yuescript/yue_compiler.cpp162
3 files changed, 137 insertions, 55 deletions
diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue
index d5197da..5dafd84 100644
--- a/spec/inputs/macro.yue
+++ b/spec/inputs/macro.yue
@@ -5,6 +5,21 @@ import "macro_export" as {
5 5
6import "macro_todo" as $ 6import "macro_todo" as $
7 7
8macro not_leak = -> "leak"
9do
10 macro x = -> 123
11 print $x
12 do
13 macro x = -> math.pi * 2
14 print $x
15 macro x = -> 456
16 print $x
17
18 import "macro_todo" as $todo: $not_leak
19 $not_leak "todo in a do block"
20
21$not_leak!!
22
8macro WindowFlag = $enum( 23macro WindowFlag = $enum(
9 NoNav 24 NoNav
10 NoDecoration 25 NoDecoration
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua
index 777f754..83c6a90 100644
--- a/spec/outputs/macro.lua
+++ b/spec/outputs/macro.lua
@@ -1,3 +1,16 @@
1do
2 print(123)
3 do
4 print(6.2831853071796)
5 end
6 print(456)
7 do
8-- TODO: "todo in a do block"
9 end
10end
11do
12 (leak)()
13end
1print("AlwaysAutoResize") 14print("AlwaysAutoResize")
2print({ 15print({
3 "NoNav", 16 "NoNav",
@@ -298,7 +311,7 @@ print((setmetatable({
298 return 998 311 return 998
299 end 312 end
300})) 313}))
301print("current line: " .. tostring(308)) 314print("current line: " .. tostring(323))
302do 315do
303-- TODO 316-- TODO
304end 317end
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 77a4967..240e3b5 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.25.6"sv; 78const std::string_view version = "0.26.0"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -432,6 +432,9 @@ private:
432 struct Scope { 432 struct Scope {
433 GlobalMode mode = GlobalMode::None; 433 GlobalMode mode = GlobalMode::None;
434 bool lastStatement = false; 434 bool lastStatement = false;
435#ifndef YUE_NO_MACRO
436 bool macroScope = false;
437#endif
435 std::unique_ptr<std::unordered_map<std::string, VarType>> vars; 438 std::unique_ptr<std::unordered_map<std::string, VarType>> vars;
436 std::unique_ptr<std::unordered_set<std::string>> allows; 439 std::unique_ptr<std::unordered_set<std::string>> allows;
437 std::unique_ptr<std::unordered_set<std::string>> globals; 440 std::unique_ptr<std::unordered_set<std::string>> globals;
@@ -472,12 +475,39 @@ private:
472 Closure 475 Closure
473 }; 476 };
474 477
478#ifndef YUE_NO_MACRO
479 void pushMacro(int moduleIndex) {
480 int len = static_cast<int>(lua_objlen(L, moduleIndex)); // len = #cur
481 if (currentScope().macroScope) {
482 lua_rawgeti(L, moduleIndex, len); // cur[len], tb
483 } else {
484 currentScope().macroScope = true;
485 lua_newtable(L); // tb
486 lua_pushvalue(L, -1); // tb tb
487 lua_rawseti(L, moduleIndex, len + 1); // cur[len + 1] = tb, tb
488 }
489 }
490
491 void popMacro() {
492 pushCurrentModule(); // cur
493 int len = static_cast<int>(lua_objlen(L, -1)); // len = #cur, cur
494 lua_pushnil(L); // cur nil
495 lua_rawseti(L, -2, len); // cur[len] = nil, cur
496 lua_pop(L, 1);
497 }
498#endif // YUE_NO_MACRO
499
475 void pushScope() { 500 void pushScope() {
476 _scopes.emplace_back(); 501 _scopes.emplace_back();
477 _scopes.back().vars = std::make_unique<std::unordered_map<std::string, VarType>>(); 502 _scopes.back().vars = std::make_unique<std::unordered_map<std::string, VarType>>();
478 } 503 }
479 504
480 void popScope() { 505 void popScope() {
506#ifndef YUE_NO_MACRO
507 if (_scopes.back().macroScope) {
508 popMacro();
509 }
510#endif // YUE_NO_MACRO
481 _scopes.pop_back(); 511 _scopes.pop_back();
482 } 512 }
483 513
@@ -4092,7 +4122,11 @@ private:
4092 } 4122 }
4093 YueConfig config; 4123 YueConfig config;
4094 config.lintGlobalVariable = true; 4124 config.lintGlobalVariable = true;
4095 auto result = YueCompiler{L, _luaOpen, true}.compile(codes, config); 4125#ifndef YUE_NO_MACRO
4126 auto result = YueCompiler{L, _luaOpen, false}.compile(codes, config);
4127#else
4128 auto result = YueCompiler{}.compile(codes, config);
4129#endif // YUE_NO_MACRO
4096 if (result.error) { 4130 if (result.error) {
4097 YUEE("failed to compile dues to Yue formatter", x); 4131 YUEE("failed to compile dues to Yue formatter", x);
4098 } 4132 }
@@ -5058,9 +5092,9 @@ private:
5058 void pushCurrentModule() { 5092 void pushCurrentModule() {
5059 if (_useModule) { 5093 if (_useModule) {
5060 lua_pushliteral(L, YUE_MODULES); // YUE_MODULES 5094 lua_pushliteral(L, YUE_MODULES); // YUE_MODULES
5061 lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], tb 5095 lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], mods
5062 int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb 5096 int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #mods, mods
5063 lua_rawgeti(L, -1, idx); // tb[idx], tb cur 5097 lua_rawgeti(L, -1, idx); // mods[idx], mods cur
5064 lua_remove(L, -2); // cur 5098 lua_remove(L, -2); // cur
5065 return; 5099 return;
5066 } 5100 }
@@ -5085,18 +5119,20 @@ private:
5085 _stateOwner = true; 5119 _stateOwner = true;
5086 } 5120 }
5087 lua_pushliteral(L, YUE_MODULES); // YUE_MODULES 5121 lua_pushliteral(L, YUE_MODULES); // YUE_MODULES
5088 lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], tb 5122 lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], mods
5089 if (lua_isnil(L, -1) != 0) { // tb == nil 5123 if (lua_isnil(L, -1) != 0) { // mods == nil
5090 lua_pop(L, 1); 5124 lua_pop(L, 1);
5091 lua_newtable(L); // tb 5125 lua_newtable(L); // mods
5092 lua_pushliteral(L, YUE_MODULES); // tb YUE_MODULES 5126 lua_pushliteral(L, YUE_MODULES); // mods YUE_MODULES
5093 lua_pushvalue(L, -2); // tb YUE_MODULE tb 5127 lua_pushvalue(L, -2); // mods YUE_MODULE mods
5094 lua_rawset(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES] = tb, tb 5128 lua_rawset(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES] = mods, mods
5095 } // tb 5129 } // tb
5096 int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb 5130 int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #mods, mods
5097 lua_newtable(L); // tb cur 5131 lua_newtable(L); // mods cur
5098 lua_pushvalue(L, -1); // tb cur cur 5132 lua_newtable(L); // mods cur scope
5099 lua_rawseti(L, -3, idx + 1); // tb[idx + 1] = cur, tb cur 5133 lua_rawseti(L, -2, 1); // cur[1] = scope, mods cur
5134 lua_pushvalue(L, -1); // mods cur cur
5135 lua_rawseti(L, -3, idx + 1); // mods[idx + 1] = cur, mods cur
5100 lua_remove(L, -2); // cur 5136 lua_remove(L, -2); // cur
5101 } 5137 }
5102 5138
@@ -5158,9 +5194,6 @@ private:
5158 } 5194 }
5159 5195
5160 void transformMacro(Macro_t* macro, str_list& out, bool exporting) { 5196 void transformMacro(Macro_t* macro, str_list& out, bool exporting) {
5161 if (_scopes.size() > 1) {
5162 throw CompileError("can not define macro outside the root block"sv, macro);
5163 }
5164 auto macroName = _parser.toString(macro->name); 5197 auto macroName = _parser.toString(macro->name);
5165 if (auto macroFunc = macro->decl.as<MacroFunc_t>()) { 5198 if (auto macroFunc = macro->decl.as<MacroFunc_t>()) {
5166 auto chainValue = macroFunc->new_ptr<ChainValue_t>(); 5199 auto chainValue = macroFunc->new_ptr<ChainValue_t>();
@@ -5184,9 +5217,12 @@ private:
5184 lua_rawset(L, -3); // cur macro module 5217 lua_rawset(L, -3); // cur macro module
5185 lua_pop(L, 1); 5218 lua_pop(L, 1);
5186 } // cur macro 5219 } // cur macro
5187 lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro name 5220 int moduleIndex = lua_gettop(L) - 1;
5188 lua_insert(L, -2); // cur name macro 5221 pushMacro(moduleIndex); // cur macro scope
5189 lua_rawset(L, -3); // cur[name] = macro, cur 5222 lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro scope name
5223 lua_insert(L, -3); // cur name macro scope
5224 lua_insert(L, -3); // cur scope name macro
5225 lua_rawset(L, -3); // scope[name] = macro, cur scope
5190 out.push_back(Empty); 5226 out.push_back(Empty);
5191 return; 5227 return;
5192 } 5228 }
@@ -5249,9 +5285,12 @@ private:
5249 lua_rawset(L, -3); // cur macro module 5285 lua_rawset(L, -3); // cur macro module
5250 lua_pop(L, 1); 5286 lua_pop(L, 1);
5251 } // cur macro 5287 } // cur macro
5252 lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro name 5288 int moduleIndex = lua_gettop(L) - 1;
5253 lua_insert(L, -2); // cur name macro 5289 pushMacro(moduleIndex); // cur macro scope
5254 lua_rawset(L, -3); // cur[name] = macro, cur 5290 lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro scope name
5291 lua_insert(L, -3); // cur name macro scope
5292 lua_insert(L, -3); // cur scope name macro
5293 lua_rawset(L, -3); // scope[name] = macro, cur scope
5255 out.push_back(Empty); 5294 out.push_back(Empty);
5256 } 5295 }
5257#else 5296#else
@@ -6373,8 +6412,18 @@ private:
6373 } 6412 }
6374 } 6413 }
6375 } 6414 }
6376 lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName 6415 int len = lua_objlen(L, -1);
6377 lua_rawget(L, -2); // cur[macroName], cur macroFunc 6416 lua_pushnil(L); // cur nil
6417 for (int i = len; i >= 1; i--) {
6418 lua_pop(L, 1); // cur
6419 lua_rawgeti(L, -1, i); // cur[i], cur scope
6420 lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur scope macroName
6421 lua_rawget(L, -2); // scope[macroName], cur scope macroFunc
6422 lua_remove(L, -2); // cur macroFunc
6423 if (!lua_isnil(L, -1)) {
6424 break;
6425 }
6426 }
6378 if (!lua_isfunction(L, -1)) { 6427 if (!lua_isfunction(L, -1)) {
6379 auto code = expandBuiltinMacro(macroName, x); 6428 auto code = expandBuiltinMacro(macroName, x);
6380 if (!code.empty()) return code; 6429 if (!code.empty()) return code;
@@ -7763,13 +7812,13 @@ private:
7763 bool extraScope = false; 7812 bool extraScope = false;
7764 bool needScope = !currentScope().lastStatement; 7813 bool needScope = !currentScope().lastStatement;
7765 std::list<std::pair<ast_node*, ast_ptr<false, ast_node>>> destructPairs; 7814 std::list<std::pair<ast_node*, ast_ptr<false, ast_node>>> destructPairs;
7766 for (auto _item : nameList->items.objects()) { 7815 for (auto item_ : nameList->items.objects()) {
7767 auto item = static_cast<NameOrDestructure_t*>(_item)->item.get(); 7816 auto item = static_cast<NameOrDestructure_t*>(item_)->item.get();
7768 switch (item->get_id()) { 7817 switch (item->get_id()) {
7769 case id<Variable_t>(): 7818 case id<Variable_t>():
7770 transformVariable(static_cast<Variable_t*>(item), vars); 7819 transformVariable(static_cast<Variable_t*>(item), vars);
7771 varAfter.push_back(vars.back()); 7820 varAfter.push_back(vars.back());
7772 if (_item == nameList->items.objects().front()) { 7821 if (getLuaTarget(x) >= 505 && item_ == nameList->items.objects().front()) {
7773 varConstAfter = vars.back(); 7822 varConstAfter = vars.back();
7774 } 7823 }
7775 break; 7824 break;
@@ -10027,39 +10076,44 @@ private:
10027 pushCurrentModule(); // cur 10076 pushCurrentModule(); // cur
10028 int top = lua_gettop(L) - 1; // Lua state may be setup by pushCurrentModule() 10077 int top = lua_gettop(L) - 1; // Lua state may be setup by pushCurrentModule()
10029 DEFER(lua_settop(L, top)); 10078 DEFER(lua_settop(L, top));
10030 pushYue("find_modulepath"sv); // cur find_modulepath 10079 pushMacro(lua_gettop(L)); // cur scope
10031 lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur find_modulepath moduleName 10080 pushYue("find_modulepath"sv); // cur scope find_modulepath
10032 if (lua_pcall(L, 1, 2, 0) != 0) { 10081 lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur scope find_modulepath moduleName
10082 if (lua_pcall(L, 1, 2, 0) != 0) { // find_modulepath(moduleName), cur scope result searchItems
10033 std::string err = lua_tostring(L, -1); 10083 std::string err = lua_tostring(L, -1);
10034 throw CompileError("failed to resolve module path\n"s + err, x); 10084 throw CompileError("failed to resolve module path\n"s + err, x);
10035 } 10085 }
10036 if (lua_isnil(L, -2) != 0) { 10086 if (lua_isnil(L, -2) != 0) { // result != nil
10037 str_list files; 10087 str_list files;
10038 if (lua_istable(L, -1) != 0) { 10088 if (lua_istable(L, -1) != 0) { // searchItems is table,
10039 int size = static_cast<int>(lua_objlen(L, -1)); 10089 int size = static_cast<int>(lua_objlen(L, -1));
10040 for (int i = 0; i < size; i++) { 10090 for (int i = 0; i < size; i++) {
10041 lua_rawgeti(L, -1, i + 1); 10091 lua_rawgeti(L, -1, i + 1); // cur scope result searchItems item
10042 files.push_back("no file \""s + lua_tostring(L, -1) + "\""s); 10092 files.push_back("no file \""s + lua_tostring(L, -1) + "\""s);
10043 lua_pop(L, 1); 10093 lua_pop(L, 1); // cur scope result searchItems
10044 } 10094 }
10045 } 10095 }
10046 throw CompileError("module '"s + moduleName + "\' not found:\n\t"s + join(files, "\n\t"sv), x); 10096 throw CompileError("module '"s + moduleName + "\' not found:\n\t"s + join(files, "\n\t"sv), x);
10047 } 10097 }
10048 lua_pop(L, 1); 10098 lua_pop(L, 1); // cur scope result
10049 std::string moduleFullName = lua_tostring(L, -1); 10099 std::string moduleFullName = lua_tostring(L, -1);
10050 lua_pop(L, 1); // cur 10100 lua_pop(L, 1); // cur scope
10051 if (!isModuleLoaded(moduleFullName)) { 10101 if (!isModuleLoaded(moduleFullName)) {
10052 pushYue("read_file"sv); // cur read_file 10102 pushYue("read_file"sv); // cur scope read_file
10053 lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur load_text moduleFullName 10103 lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur scope load_text moduleFullName
10054 if (lua_pcall(L, 1, 1, 0) != 0) { 10104 if (lua_pcall(L, 1, 1, 0) != 0) {
10055 std::string err = lua_tostring(L, -1); 10105 std::string err = lua_tostring(L, -1);
10056 throw CompileError("failed to read module file\n"s + err, x); 10106 throw CompileError("failed to read module file\n"s + err, x);
10057 } // cur text 10107 } // cur scope text
10058 if (lua_isnil(L, -1) != 0) { 10108 if (lua_isnil(L, -1) != 0) {
10059 throw CompileError("failed to get module text"sv, x); 10109 throw CompileError("failed to get module text"sv, x);
10060 } // cur text 10110 } // cur scope text
10061 std::string text = lua_tostring(L, -1); 10111 std::string text = lua_tostring(L, -1);
10062 auto compiler = YueCompilerImpl(L, _luaOpen, false); 10112#ifndef YUE_NO_MACRO
10113 auto compiler = YueCompiler{L, _luaOpen, false};
10114#else
10115 auto compiler = YueCompiler{};
10116#endif // YUE_NO_MACRO
10063 YueConfig config; 10117 YueConfig config;
10064 config.lineOffset = 0; 10118 config.lineOffset = 0;
10065 config.lintGlobalVariable = false; 10119 config.lintGlobalVariable = false;
@@ -10071,28 +10125,28 @@ private:
10071 if (result.error) { 10125 if (result.error) {
10072 throw CompileError("failed to compile module '"s + moduleName + "\': "s + result.error.value().msg, x); 10126 throw CompileError("failed to compile module '"s + moduleName + "\': "s + result.error.value().msg, x);
10073 } 10127 }
10074 lua_pop(L, 1); // cur 10128 lua_pop(L, 1); // cur scope
10075 } 10129 }
10076 pushModuleTable(moduleFullName); // cur mod 10130 pushModuleTable(moduleFullName); // cur scope mod
10077 if (importAllMacro) { 10131 if (importAllMacro) {
10078 lua_pushnil(L); // cur mod startKey 10132 lua_pushnil(L); // cur scope mod startKey
10079 while (lua_next(L, -2) != 0) { // cur mod key value 10133 while (lua_next(L, -2) != 0) { // cur scope mod key value
10080 const char* key = lua_tostring(L, -2); 10134 const char* key = lua_tostring(L, -2);
10081 auto it = std::find_if(macroPairs.begin(), macroPairs.end(), [&](const auto& item) { 10135 auto it = std::find_if(macroPairs.begin(), macroPairs.end(), [&](const auto& item) {
10082 return key == item.first; 10136 return key == item.first;
10083 }); 10137 });
10084 if (it == macroPairs.end()) { 10138 if (it == macroPairs.end()) {
10085 lua_pushvalue(L, -2); // cur mod key value key 10139 lua_pushvalue(L, -2); // cur scope mod key value key
10086 lua_insert(L, -2); // cur mod key key value 10140 lua_insert(L, -2); // cur scope mod key key value
10087 lua_rawset(L, -5); // cur[key] = value, cur mod key 10141 lua_rawset(L, -5); // scope[key] = value, cur scope mod key
10088 } else { 10142 } else {
10089 lua_pop(L, 1); // cur mod key 10143 lua_pop(L, 1); // cur scope mod key
10090 } 10144 }
10091 } 10145 } // cur scope mod
10092 } 10146 }
10093 for (const auto& pair : macroPairs) { 10147 for (const auto& pair : macroPairs) {
10094 lua_getfield(L, -1, pair.first.c_str()); // mod[first], cur mod val 10148 lua_getfield(L, -1, pair.first.c_str()); // mod[first], cur scope mod val
10095 lua_setfield(L, -3, pair.second.c_str()); // cur[second] = val, cur mod 10149 lua_setfield(L, -3, pair.second.c_str()); // scope[second] = val, cur scope mod
10096 } 10150 }
10097 } 10151 }
10098#else // YUE_NO_MACRO 10152#else // YUE_NO_MACRO