aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/inputs/macro.moon33
-rw-r--r--src/MoonP/moon_compiler.cpp85
-rw-r--r--src/MoonP/moon_parser.cpp6
-rw-r--r--src/MoonP/stacktraceplus.h17
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
105macro lua lua = (codes)-> "#{codes}"
106
107x = 0
108
109$lua [[
110local function f(a)
111 return a + 1
112end
113x = x + f(3)
114]]
115
116print x
117
118macro lua def = (fname, ...)->
119 args = {...}
120 last = table.remove args
121 $showMacro "def", "local function #{fname}(#{table.concat args, ', '})
122 #{last}
123end"
124
125sel = (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
105nil 138nil
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
45const char* moonScriptVersion() { 45const 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