diff options
-rw-r--r-- | spec/inputs/macro.moon | 33 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 85 | ||||
-rw-r--r-- | src/MoonP/moon_parser.cpp | 6 | ||||
-rw-r--r-- | src/MoonP/stacktraceplus.h | 17 |
4 files changed, 100 insertions, 41 deletions
diff --git a/spec/inputs/macro.moon b/spec/inputs/macro.moon index 9083449..47e5a26 100644 --- a/spec/inputs/macro.moon +++ b/spec/inputs/macro.moon | |||
@@ -102,5 +102,38 @@ do | |||
102 | a += $get_inner_hygienic! | 102 | a += $get_inner_hygienic! |
103 | print a | 103 | print a |
104 | 104 | ||
105 | macro lua lua = (codes)-> "#{codes}" | ||
106 | |||
107 | x = 0 | ||
108 | |||
109 | $lua [[ | ||
110 | local function f(a) | ||
111 | return a + 1 | ||
112 | end | ||
113 | x = x + f(3) | ||
114 | ]] | ||
115 | |||
116 | print x | ||
117 | |||
118 | macro lua def = (fname, ...)-> | ||
119 | args = {...} | ||
120 | last = table.remove args | ||
121 | $showMacro "def", "local function #{fname}(#{table.concat args, ', '}) | ||
122 | #{last} | ||
123 | end" | ||
124 | |||
125 | sel = (a, b, c)-> if a then b else c | ||
126 | |||
127 | $def sel, a, b, c, [[ | ||
128 | if a then | ||
129 | return b | ||
130 | else | ||
131 | return c | ||
132 | end | ||
133 | ]] | ||
134 | |||
135 | $def dummy,[[ | ||
136 | ]] | ||
137 | |||
105 | nil | 138 | nil |
106 | 139 | ||
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 00b897d..c176c01 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -43,7 +43,7 @@ inline std::string s(std::string_view sv) { | |||
43 | } | 43 | } |
44 | 44 | ||
45 | const char* moonScriptVersion() { | 45 | const char* moonScriptVersion() { |
46 | return "0.5.0-r0.3.3"; | 46 | return "0.5.0-r0.3.4"; |
47 | } | 47 | } |
48 | 48 | ||
49 | // name of table stored in lua registry | 49 | // name of table stored in lua registry |
@@ -58,11 +58,11 @@ public: | |||
58 | L(sharedState), | 58 | L(sharedState), |
59 | _luaOpen(luaOpen), | 59 | _luaOpen(luaOpen), |
60 | _moduleName(moduleName) { | 60 | _moduleName(moduleName) { |
61 | int top = -1; | ||
62 | BLOCK_START | 61 | BLOCK_START |
63 | BREAK_IF(!sameModule); | 62 | BREAK_IF(!sameModule); |
64 | BREAK_IF(!L); | 63 | BREAK_IF(!L); |
65 | top = lua_gettop(L); | 64 | int top = lua_gettop(L); |
65 | DEFER(lua_settop(L, top)); | ||
66 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | 66 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE |
67 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE], tb | 67 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE], tb |
68 | BREAK_IF(lua_istable(L, -1) == 0); | 68 | BREAK_IF(lua_istable(L, -1) == 0); |
@@ -71,7 +71,6 @@ public: | |||
71 | _useModule = true; | 71 | _useModule = true; |
72 | _sameModule = true; | 72 | _sameModule = true; |
73 | BLOCK_END | 73 | BLOCK_END |
74 | if (top != -1) lua_settop(L, top); | ||
75 | } | 74 | } |
76 | 75 | ||
77 | ~MoonCompilerImpl() { | 76 | ~MoonCompilerImpl() { |
@@ -2095,15 +2094,14 @@ private: | |||
2095 | 2094 | ||
2096 | bool isModuleLoaded(std::string_view name) { | 2095 | bool isModuleLoaded(std::string_view name) { |
2097 | int top = lua_gettop(L); | 2096 | int top = lua_gettop(L); |
2097 | DEFER(lua_settop(L, top)); | ||
2098 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | 2098 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE |
2099 | lua_rawget(L, LUA_REGISTRYINDEX); // modules | 2099 | lua_rawget(L, LUA_REGISTRYINDEX); // modules |
2100 | lua_pushlstring(L, &name.front(), name.size()); | 2100 | lua_pushlstring(L, &name.front(), name.size()); |
2101 | lua_rawget(L, -2); // modules module | 2101 | lua_rawget(L, -2); // modules module |
2102 | if (lua_isnil(L, -1) != 0) { | 2102 | if (lua_isnil(L, -1) != 0) { |
2103 | lua_settop(L, top); | ||
2104 | return false; | 2103 | return false; |
2105 | } | 2104 | } |
2106 | lua_settop(L, top); | ||
2107 | return true; | 2105 | return true; |
2108 | } | 2106 | } |
2109 | 2107 | ||
@@ -2153,7 +2151,7 @@ private: | |||
2153 | for (auto def_ : argsDef->definitions.objects()) { | 2151 | for (auto def_ : argsDef->definitions.objects()) { |
2154 | auto def = static_cast<FnArgDef_t*>(def_); | 2152 | auto def = static_cast<FnArgDef_t*>(def_); |
2155 | if (def->name.is<SelfName_t>()) { | 2153 | if (def->name.is<SelfName_t>()) { |
2156 | throw std::logic_error(_info.errorMessage("self name is not supported here"sv, def->name)); | 2154 | throw std::logic_error(_info.errorMessage("self name is not supported for macro function argument"sv, def->name)); |
2157 | } else { | 2155 | } else { |
2158 | std::string defVal; | 2156 | std::string defVal; |
2159 | if (def->defaultValue) { | 2157 | if (def->defaultValue) { |
@@ -2177,18 +2175,17 @@ private: | |||
2177 | auto chunkName = clearBuf(); | 2175 | auto chunkName = clearBuf(); |
2178 | pushCurrentModule(); // cur | 2176 | pushCurrentModule(); // cur |
2179 | int top = lua_gettop(L) - 1; | 2177 | int top = lua_gettop(L) - 1; |
2178 | DEFER(lua_settop(L, top)); | ||
2180 | pushMoonp("loadstring"sv); // cur loadstring | 2179 | pushMoonp("loadstring"sv); // cur loadstring |
2181 | lua_pushlstring(L, macroCodes.c_str(), macroCodes.size()); // cur loadstring codes | 2180 | lua_pushlstring(L, macroCodes.c_str(), macroCodes.size()); // cur loadstring codes |
2182 | lua_pushlstring(L, chunkName.c_str(), chunkName.size()); // cur loadstring codes chunk | 2181 | lua_pushlstring(L, chunkName.c_str(), chunkName.size()); // cur loadstring codes chunk |
2183 | pushOptions(macro->m_begin.m_line - 1); // cur loadstring codes chunk options | 2182 | pushOptions(macro->m_begin.m_line - 1); // cur loadstring codes chunk options |
2184 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), cur f err | 2183 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), cur f err |
2185 | std::string err = lua_tostring(L, -1); | 2184 | std::string err = lua_tostring(L, -1); |
2186 | lua_settop(L, top); | ||
2187 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes\n"sv) + err, macro->macroLit)); | 2185 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes\n"sv) + err, macro->macroLit)); |
2188 | } // cur f err | 2186 | } // cur f err |
2189 | if (lua_isnil(L, -2) != 0) { // f == nil, cur f err | 2187 | if (lua_isnil(L, -2) != 0) { // f == nil, cur f err |
2190 | std::string err = lua_tostring(L, -1); | 2188 | std::string err = lua_tostring(L, -1); |
2191 | lua_settop(L, top); | ||
2192 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes, at (macro "sv) + macroName + s("): "sv) + err, macro->macroLit)); | 2189 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes, at (macro "sv) + macroName + s("): "sv) + err, macro->macroLit)); |
2193 | } | 2190 | } |
2194 | lua_pop(L, 1); // cur f | 2191 | lua_pop(L, 1); // cur f |
@@ -2196,12 +2193,10 @@ private: | |||
2196 | lua_insert(L, -2); // cur pcall f | 2193 | lua_insert(L, -2); // cur pcall f |
2197 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), cur success macro | 2194 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), cur success macro |
2198 | std::string err = lua_tostring(L, -1); | 2195 | std::string err = lua_tostring(L, -1); |
2199 | lua_settop(L, top); | ||
2200 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, macro->macroLit)); | 2196 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, macro->macroLit)); |
2201 | } // cur success res | 2197 | } // cur success res |
2202 | if (lua_toboolean(L, -2) == 0) { | 2198 | if (lua_toboolean(L, -2) == 0) { |
2203 | std::string err = lua_tostring(L, -1); | 2199 | std::string err = lua_tostring(L, -1); |
2204 | lua_settop(L, top); | ||
2205 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, macro->macroLit)); | 2200 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, macro->macroLit)); |
2206 | } // cur true macro | 2201 | } // cur true macro |
2207 | lua_remove(L, -2); // cur macro | 2202 | lua_remove(L, -2); // cur macro |
@@ -2215,7 +2210,6 @@ private: | |||
2215 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro name | 2210 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro name |
2216 | lua_insert(L, -2); // cur name macro | 2211 | lua_insert(L, -2); // cur name macro |
2217 | lua_rawset(L, -3); // cur[name] = macro, cur | 2212 | lua_rawset(L, -3); // cur[name] = macro, cur |
2218 | lua_settop(L, top); | ||
2219 | out.push_back(Empty); | 2213 | out.push_back(Empty); |
2220 | } | 2214 | } |
2221 | 2215 | ||
@@ -2935,10 +2929,10 @@ private: | |||
2935 | } | 2929 | } |
2936 | pushCurrentModule(); // cur | 2930 | pushCurrentModule(); // cur |
2937 | int top = lua_gettop(L) - 1; | 2931 | int top = lua_gettop(L) - 1; |
2932 | DEFER(lua_settop(L, top)); | ||
2938 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName | 2933 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName |
2939 | lua_rawget(L, -2); // cur[macroName], cur macro | 2934 | lua_rawget(L, -2); // cur[macroName], cur macro |
2940 | if (lua_istable(L, -1) == 0) { | 2935 | if (lua_istable(L, -1) == 0) { |
2941 | lua_settop(L, top); | ||
2942 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 2936 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); |
2943 | } | 2937 | } |
2944 | lua_rawgeti(L, -1, 1); // cur macro func | 2938 | lua_rawgeti(L, -1, 1); // cur macro func |
@@ -2968,9 +2962,23 @@ private: | |||
2968 | str = codes; | 2962 | str = codes; |
2969 | BLOCK_END | 2963 | BLOCK_END |
2970 | if (str.empty()) { | 2964 | if (str.empty()) { |
2971 | str = _parser.toString(exp->value); | 2965 | bool multiLineStr = false; |
2972 | for (auto opVal : exp->opValues.objects()) { | 2966 | BLOCK_START |
2973 | str += _parser.toString(opVal); | 2967 | auto value = singleValueFrom(exp); |
2968 | BREAK_IF(!value); | ||
2969 | auto lstr = value->getByPath<String_t, LuaString_t>(); | ||
2970 | BREAK_IF(!lstr); | ||
2971 | str = _parser.toString(lstr->content); | ||
2972 | multiLineStr = true; | ||
2973 | BLOCK_END | ||
2974 | if (!multiLineStr) { | ||
2975 | // convert sub nodes to strings in case exp is assembled | ||
2976 | // in transform stage, the toString() function won't be able | ||
2977 | // to convert its whole content | ||
2978 | str = _parser.toString(exp->value); | ||
2979 | for (auto opVal : exp->opValues.objects()) { | ||
2980 | str += _parser.toString(opVal); | ||
2981 | } | ||
2974 | } | 2982 | } |
2975 | } | 2983 | } |
2976 | } else str = _parser.toString(arg); | 2984 | } else str = _parser.toString(arg); |
@@ -2981,39 +2989,48 @@ private: | |||
2981 | bool success = lua_pcall(L, static_cast<int>(args->size()) + 1, 2, 0) == 0; | 2989 | bool success = lua_pcall(L, static_cast<int>(args->size()) + 1, 2, 0) == 0; |
2982 | if (!success) { // cur macro err | 2990 | if (!success) { // cur macro err |
2983 | std::string err = lua_tostring(L, -1); | 2991 | std::string err = lua_tostring(L, -1); |
2984 | lua_settop(L, top); | ||
2985 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); | 2992 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); |
2986 | } // cur macro success res | 2993 | } // cur macro success res |
2987 | if (lua_toboolean(L, -2) == 0) { | 2994 | if (lua_toboolean(L, -2) == 0) { |
2988 | std::string err = lua_tostring(L, -1); | 2995 | std::string err = lua_tostring(L, -1); |
2989 | lua_settop(L, top); | ||
2990 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); | 2996 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); |
2991 | } | 2997 | } |
2992 | lua_remove(L, -2); // cur macro res | 2998 | lua_remove(L, -2); // cur macro res |
2993 | if (lua_isstring(L, -1) == 0) { | 2999 | if (lua_isstring(L, -1) == 0) { |
2994 | lua_settop(L, top); | ||
2995 | throw std::logic_error(_info.errorMessage(s("macro function must return string with expanded codes"sv), x)); | 3000 | throw std::logic_error(_info.errorMessage(s("macro function must return string with expanded codes"sv), x)); |
2996 | } // cur macro codes | 3001 | } // cur macro codes |
2997 | lua_rawgeti(L, -2, 2); // cur macro codes type | 3002 | lua_rawgeti(L, -2, 2); // cur macro codes type |
2998 | std::string type = lua_tostring(L, -1); | 3003 | std::string type = lua_tostring(L, -1); |
2999 | std::string codes = lua_tostring(L, -2); | 3004 | std::string codes = lua_tostring(L, -2); |
3000 | lua_settop(L, top); | ||
3001 | return {type, codes}; | 3005 | return {type, codes}; |
3002 | } | 3006 | } |
3003 | 3007 | ||
3004 | std::pair<ast_ptr<false,ast_node>, std::unique_ptr<input>> expandMacro(ChainValue_t* chainValue, ExpUsage usage) { | 3008 | std::tuple<ast_ptr<false,ast_node>, std::unique_ptr<input>, std::string> expandMacro(ChainValue_t* chainValue, ExpUsage usage) { |
3005 | auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>(); | 3009 | auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>(); |
3006 | const auto& chainList = chainValue->items.objects(); | 3010 | const auto& chainList = chainValue->items.objects(); |
3007 | std::string type, codes; | 3011 | std::string type, codes; |
3008 | std::tie(type, codes) = expandMacroStr(chainValue); | 3012 | std::tie(type, codes) = expandMacroStr(chainValue); |
3009 | std::string targetType(usage != ExpUsage::Common || chainList.size() > 2 ? "expr"sv : "block"sv); | 3013 | std::string targetType(usage != ExpUsage::Common || chainList.size() > 2 ? "expr"sv : "block"sv); |
3014 | if (type == "lua"sv) { | ||
3015 | if (targetType != "block"sv) { | ||
3016 | throw std::logic_error(_info.errorMessage("lua macro can only be placed where block macro is allowed"sv, x)); | ||
3017 | } | ||
3018 | auto macroChunk = s("=(macro "sv) + _parser.toString(x->name) + ')'; | ||
3019 | int top = lua_gettop(L); | ||
3020 | DEFER(lua_settop(L, top)); | ||
3021 | if (luaL_loadbuffer(L, codes.c_str(), codes.size(), macroChunk.c_str()) != 0) { | ||
3022 | std::string err = lua_tostring(L, -1); | ||
3023 | throw std::logic_error(_info.errorMessage(err, x)); | ||
3024 | } | ||
3025 | return {nullptr, nullptr, std::move(codes)}; | ||
3026 | } | ||
3010 | if (type != targetType) { | 3027 | if (type != targetType) { |
3011 | throw std::logic_error(_info.errorMessage(s("macro type mismatch, "sv) + targetType + s(" expected, got "sv) + type, x)); | 3028 | throw std::logic_error(_info.errorMessage(s("macro type mismatch, "sv) + targetType + s(" expected, got "sv) + type, x)); |
3012 | } | 3029 | } |
3013 | ParseInfo info; | 3030 | ParseInfo info; |
3014 | if (usage == ExpUsage::Common) { | 3031 | if (usage == ExpUsage::Common) { |
3015 | if (codes.empty()) { | 3032 | if (codes.empty()) { |
3016 | return {x->new_ptr<Block_t>().get(),std::move(info.codes)}; | 3033 | return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty}; |
3017 | } | 3034 | } |
3018 | if (type == "expr"sv) { | 3035 | if (type == "expr"sv) { |
3019 | info = _parser.parse<Exp_t>(codes); | 3036 | info = _parser.parse<Exp_t>(codes); |
@@ -3070,14 +3087,27 @@ private: | |||
3070 | info.node.set(exp); | 3087 | info.node.set(exp); |
3071 | } | 3088 | } |
3072 | } | 3089 | } |
3073 | return {info.node,std::move(info.codes)}; | 3090 | return {info.node, std::move(info.codes), Empty}; |
3074 | } | 3091 | } |
3075 | 3092 | ||
3076 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 3093 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
3077 | if (isMacroChain(chainValue)) { | 3094 | if (isMacroChain(chainValue)) { |
3078 | ast_ptr<false,ast_node> node; | 3095 | ast_ptr<false,ast_node> node; |
3079 | std::unique_ptr<input> codes; | 3096 | std::unique_ptr<input> codes; |
3080 | std::tie(node, codes) = expandMacro(chainValue, usage); | 3097 | std::string luaCodes; |
3098 | std::tie(node, codes, luaCodes) = expandMacro(chainValue, usage); | ||
3099 | Utils::replace(luaCodes, "\r\n"sv, "\n"sv); | ||
3100 | Utils::trim(luaCodes); | ||
3101 | if (!node && !codes) { | ||
3102 | if (!luaCodes.empty()) { | ||
3103 | if (_config.reserveLineNumber) { | ||
3104 | luaCodes.insert(0, nll(chainValue).substr(1)); | ||
3105 | } | ||
3106 | luaCodes.append(nlr(chainValue)); | ||
3107 | } | ||
3108 | out.push_back(luaCodes); | ||
3109 | return; | ||
3110 | } | ||
3081 | if (usage == ExpUsage::Common) { | 3111 | if (usage == ExpUsage::Common) { |
3082 | transformBlock(node.to<Block_t>(), out, usage, assignList); | 3112 | transformBlock(node.to<Block_t>(), out, usage, assignList); |
3083 | } else { | 3113 | } else { |
@@ -4700,15 +4730,14 @@ private: | |||
4700 | Utils::trim(moduleName); | 4730 | Utils::trim(moduleName); |
4701 | pushCurrentModule(); // cur | 4731 | pushCurrentModule(); // cur |
4702 | int top = lua_gettop(L) - 1; | 4732 | int top = lua_gettop(L) - 1; |
4733 | DEFER(lua_settop(L, top)); | ||
4703 | pushMoonp("find_modulepath"sv); // cur find_modulepath | 4734 | pushMoonp("find_modulepath"sv); // cur find_modulepath |
4704 | lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur find_modulepath moduleName | 4735 | lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur find_modulepath moduleName |
4705 | if (lua_pcall(L, 1, 1, 0) != 0) { | 4736 | if (lua_pcall(L, 1, 1, 0) != 0) { |
4706 | std::string err = lua_tostring(L, -1); | 4737 | std::string err = lua_tostring(L, -1); |
4707 | lua_settop(L, top); | ||
4708 | throw std::logic_error(_info.errorMessage(s("fail to resolve module path\n"sv) + err, x)); | 4738 | throw std::logic_error(_info.errorMessage(s("fail to resolve module path\n"sv) + err, x)); |
4709 | } | 4739 | } |
4710 | if (lua_isnil(L, -1) != 0) { | 4740 | if (lua_isnil(L, -1) != 0) { |
4711 | lua_settop(L, top); | ||
4712 | throw std::logic_error(_info.errorMessage(s("fail to find module '"sv) + moduleName + '\'', x)); | 4741 | throw std::logic_error(_info.errorMessage(s("fail to find module '"sv) + moduleName + '\'', x)); |
4713 | } | 4742 | } |
4714 | std::string moduleFullName = lua_tostring(L, -1); | 4743 | std::string moduleFullName = lua_tostring(L, -1); |
@@ -4718,11 +4747,9 @@ private: | |||
4718 | lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur load_text moduleFullName | 4747 | lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur load_text moduleFullName |
4719 | if (lua_pcall(L, 1, 1, 0) != 0) { | 4748 | if (lua_pcall(L, 1, 1, 0) != 0) { |
4720 | std::string err = lua_tostring(L, -1); | 4749 | std::string err = lua_tostring(L, -1); |
4721 | lua_settop(L, top); | ||
4722 | throw std::logic_error(_info.errorMessage(s("fail to read module file\n"sv) + err, x)); | 4750 | throw std::logic_error(_info.errorMessage(s("fail to read module file\n"sv) + err, x)); |
4723 | } // cur text | 4751 | } // cur text |
4724 | if (lua_isnil(L, -1) != 0) { | 4752 | if (lua_isnil(L, -1) != 0) { |
4725 | lua_settop(L, top); | ||
4726 | throw std::logic_error(_info.errorMessage("fail to get module text"sv, x)); | 4753 | throw std::logic_error(_info.errorMessage("fail to get module text"sv, x)); |
4727 | } // cur text | 4754 | } // cur text |
4728 | std::string text = lua_tostring(L, -1); | 4755 | std::string text = lua_tostring(L, -1); |
@@ -4736,7 +4763,6 @@ private: | |||
4736 | GlobalVars globals; | 4763 | GlobalVars globals; |
4737 | std::tie(codes, err, globals) = compiler.compile(text, config); | 4764 | std::tie(codes, err, globals) = compiler.compile(text, config); |
4738 | if (codes.empty() && !err.empty()) { | 4765 | if (codes.empty() && !err.empty()) { |
4739 | lua_settop(L, top); | ||
4740 | throw std::logic_error(_info.errorMessage(s("fail to compile module '"sv) + moduleName + s("\': "sv) + err, x)); | 4766 | throw std::logic_error(_info.errorMessage(s("fail to compile module '"sv) + moduleName + s("\': "sv) + err, x)); |
4741 | } | 4767 | } |
4742 | lua_pop(L, 1); // cur | 4768 | lua_pop(L, 1); // cur |
@@ -4746,7 +4772,6 @@ private: | |||
4746 | lua_getfield(L, -1, pair.first.c_str()); | 4772 | lua_getfield(L, -1, pair.first.c_str()); |
4747 | lua_setfield(L, -3, pair.second.c_str()); | 4773 | lua_setfield(L, -3, pair.second.c_str()); |
4748 | } | 4774 | } |
4749 | lua_settop(L, top); | ||
4750 | } | 4775 | } |
4751 | if (newTab->values.empty()) { | 4776 | if (newTab->values.empty()) { |
4752 | out.push_back(Empty); | 4777 | out.push_back(Empty); |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index f0269d7..c8a3a23 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -472,7 +472,7 @@ MoonParser::MoonParser() { | |||
472 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; | 472 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; |
473 | 473 | ||
474 | MacroName = expr('$') >> Name; | 474 | MacroName = expr('$') >> Name; |
475 | macro_type = expr("expr") | expr("block"); | 475 | macro_type = expr("expr") | expr("block") | expr("lua"); |
476 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); | 476 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); |
477 | MacroLit = -macro_args_def >> Space >> expr("->") >> Body; | 477 | MacroLit = -macro_args_def >> Space >> expr("->") >> Body; |
478 | Macro = key("macro") >> Space >> macro_type >> Space >> Name >> sym('=') >> MacroLit; | 478 | Macro = key("macro") >> Space >> macro_type >> Space >> Name >> sym('=') >> MacroLit; |
@@ -608,8 +608,8 @@ namespace Utils { | |||
608 | 608 | ||
609 | void trim(std::string& str) { | 609 | void trim(std::string& str) { |
610 | if (str.empty()) return; | 610 | if (str.empty()) return; |
611 | str.erase(0, str.find_first_not_of(" \t")); | 611 | str.erase(0, str.find_first_not_of(" \t\n")); |
612 | str.erase(str.find_last_not_of(" \t") + 1); | 612 | str.erase(str.find_last_not_of(" \t\n") + 1); |
613 | } | 613 | } |
614 | } | 614 | } |
615 | 615 | ||
diff --git a/src/MoonP/stacktraceplus.h b/src/MoonP/stacktraceplus.h index fcd887a..ea53885 100644 --- a/src/MoonP/stacktraceplus.h +++ b/src/MoonP/stacktraceplus.h | |||
@@ -334,16 +334,17 @@ local function getMoonLineNumber(fname, line) | |||
334 | end | 334 | end |
335 | end | 335 | end |
336 | if source then | 336 | if source then |
337 | local i, target = 1, tonumber(line) | 337 | local current, target = 1, tonumber(line) |
338 | local findLine = line | ||
338 | for lineCode in source:gmatch("([^\n]*)\n") do | 339 | for lineCode in source:gmatch("([^\n]*)\n") do |
339 | if i == target then | 340 | local num = lineCode:match("--%s*(%d+)%s*$") |
340 | local num = lineCode:match("--%s*(%d*)%s*$") | 341 | if num then |
341 | if num then | 342 | findLine = num |
342 | return fname, num | 343 | end |
343 | end | 344 | if current == target then |
344 | break | 345 | return fname, findLine or line |
345 | end | 346 | end |
346 | i = i + 1 | 347 | current = current + 1 |
347 | end | 348 | end |
348 | end | 349 | end |
349 | return fname, line | 350 | return fname, line |