diff options
| author | Li Jin <dragon-fly@qq.com> | 2020-10-21 23:44:50 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2020-10-21 23:44:50 +0800 |
| commit | b6725202f4a8cac5f829dac9a72a81f3ff73e787 (patch) | |
| tree | c173accb869b60cba14babc7685284864bc80426 /src/MoonP/moon_compiler.cpp | |
| parent | 0777356cbe599b3f88bdfa476e3ffa64bb3a3a8c (diff) | |
| download | yuescript-b6725202f4a8cac5f829dac9a72a81f3ff73e787.tar.gz yuescript-b6725202f4a8cac5f829dac9a72a81f3ff73e787.tar.bz2 yuescript-b6725202f4a8cac5f829dac9a72a81f3ff73e787.zip | |
extend macro feature to support compiling Moonscript to other Lua dialect like teal.
add examples for how to write MoonPlus codes that compile to teal.
fix C++ macro to build without MoonPlus macro feature or built-in Lua.
add support for passing arguments from command line to compiler that can be accessed or altered by "require('moonp').options".
Diffstat (limited to 'src/MoonP/moon_compiler.cpp')
| -rw-r--r-- | src/MoonP/moon_compiler.cpp | 198 |
1 files changed, 160 insertions, 38 deletions
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index debc43a..f24441f 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
| @@ -53,7 +53,7 @@ inline std::string s(std::string_view sv) { | |||
| 53 | return std::string(sv); | 53 | return std::string(sv); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | const std::string_view version = "0.4.18"sv; | 56 | const std::string_view version = "0.4.19"sv; |
| 57 | const std::string_view extension = "mp"sv; | 57 | const std::string_view extension = "mp"sv; |
| 58 | 58 | ||
| 59 | class MoonCompilerImpl { | 59 | class MoonCompilerImpl { |
| @@ -89,10 +89,17 @@ public: | |||
| 89 | } | 89 | } |
| 90 | #endif // MOONP_NO_MACRO | 90 | #endif // MOONP_NO_MACRO |
| 91 | 91 | ||
| 92 | std::tuple<std::string,std::string,GlobalVars> compile(std::string_view codes, const MoonConfig& config) { | 92 | CompileInfo compile(std::string_view codes, const MoonConfig& config) { |
| 93 | _config = config; | 93 | _config = config; |
| 94 | #ifndef MOONP_NO_MACRO | ||
| 95 | if (L) passOptions(); | ||
| 96 | #endif // MOONP_NO_MACRO | ||
| 94 | _info = _parser.parse<File_t>(codes); | 97 | _info = _parser.parse<File_t>(codes); |
| 95 | GlobalVars globals; | 98 | std::unique_ptr<GlobalVars> globals; |
| 99 | std::unique_ptr<Options> options; | ||
| 100 | if (!config.options.empty()) { | ||
| 101 | options = std::make_unique<Options>(config.options); | ||
| 102 | } | ||
| 96 | DEFER(clear()); | 103 | DEFER(clear()); |
| 97 | if (_info.node) { | 104 | if (_info.node) { |
| 98 | try { | 105 | try { |
| @@ -104,19 +111,39 @@ public: | |||
| 104 | nullptr, true); | 111 | nullptr, true); |
| 105 | popScope(); | 112 | popScope(); |
| 106 | if (config.lintGlobalVariable) { | 113 | if (config.lintGlobalVariable) { |
| 107 | globals = std::make_unique<std::list<GlobalVar>>(); | 114 | globals = std::make_unique<GlobalVars>(); |
| 108 | for (const auto& var : _globals) { | 115 | for (const auto& var : _globals) { |
| 109 | int line,col; | 116 | int line,col; |
| 110 | std::tie(line,col) = var.second; | 117 | std::tie(line,col) = var.second; |
| 111 | globals->push_back({var.first, line, col}); | 118 | globals->push_back({var.first, line, col}); |
| 112 | } | 119 | } |
| 113 | } | 120 | } |
| 114 | return {std::move(out.back()), Empty, std::move(globals)}; | 121 | #ifndef MOONP_NO_MACRO |
| 122 | if (L) { | ||
| 123 | int top = lua_gettop(L); | ||
| 124 | DEFER(lua_settop(L, top)); | ||
| 125 | if (!options) { | ||
| 126 | options = std::make_unique<Options>(); | ||
| 127 | } | ||
| 128 | pushMoonp("options"sv); | ||
| 129 | lua_pushnil(L); // options startKey | ||
| 130 | while (lua_next(L, -2) != 0) { // options key value | ||
| 131 | size_t len = 0; | ||
| 132 | auto pstr = lua_tolstring(L, -2, &len); | ||
| 133 | std::string key{pstr, len}; | ||
| 134 | pstr = lua_tolstring(L, -1, &len); | ||
| 135 | std::string value{pstr, len}; | ||
| 136 | (*options)[key] = value; | ||
| 137 | lua_pop(L, 1); // options key | ||
| 138 | } | ||
| 139 | } | ||
| 140 | #endif // MOONP_NO_MACRO | ||
| 141 | return {std::move(out.back()), Empty, std::move(globals), std::move(options)}; | ||
| 115 | } catch (const std::logic_error& error) { | 142 | } catch (const std::logic_error& error) { |
| 116 | return {Empty, error.what(), std::move(globals)}; | 143 | return {Empty, error.what(), std::move(globals), std::move(options)}; |
| 117 | } | 144 | } |
| 118 | } else { | 145 | } else { |
| 119 | return {Empty, std::move(_info.error), std::move(globals)}; | 146 | return {Empty, std::move(_info.error), std::move(globals), std::move(options)}; |
| 120 | } | 147 | } |
| 121 | } | 148 | } |
| 122 | 149 | ||
| @@ -2150,6 +2177,17 @@ private: | |||
| 2150 | } | 2177 | } |
| 2151 | 2178 | ||
| 2152 | #ifndef MOONP_NO_MACRO | 2179 | #ifndef MOONP_NO_MACRO |
| 2180 | void passOptions() { | ||
| 2181 | if (!_config.options.empty()) { | ||
| 2182 | pushMoonp("options"sv); // options | ||
| 2183 | for (const auto& option : _config.options) { | ||
| 2184 | lua_pushlstring(L, option.second.c_str(), option.second.size()); | ||
| 2185 | lua_setfield(L, -2, option.first.c_str()); | ||
| 2186 | } | ||
| 2187 | lua_pop(L, 1); | ||
| 2188 | } | ||
| 2189 | } | ||
| 2190 | |||
| 2153 | void pushCurrentModule() { | 2191 | void pushCurrentModule() { |
| 2154 | if (_useModule) { | 2192 | if (_useModule) { |
| 2155 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | 2193 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE |
| @@ -2165,6 +2203,7 @@ private: | |||
| 2165 | if (_luaOpen) { | 2203 | if (_luaOpen) { |
| 2166 | _luaOpen(static_cast<void*>(L)); | 2204 | _luaOpen(static_cast<void*>(L)); |
| 2167 | } | 2205 | } |
| 2206 | passOptions(); | ||
| 2168 | _stateOwner = true; | 2207 | _stateOwner = true; |
| 2169 | } | 2208 | } |
| 2170 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | 2209 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE |
| @@ -2314,7 +2353,7 @@ private: | |||
| 2314 | out.push_back(Empty); | 2353 | out.push_back(Empty); |
| 2315 | } | 2354 | } |
| 2316 | #else | 2355 | #else |
| 2317 | void transformMacro(Macro_t* macro, str_list& out, bool exporting) { | 2356 | void transformMacro(Macro_t* macro, str_list&, bool) { |
| 2318 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macro)); | 2357 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macro)); |
| 2319 | } | 2358 | } |
| 2320 | #endif // MOONP_NO_MACRO | 2359 | #endif // MOONP_NO_MACRO |
| @@ -3023,16 +3062,67 @@ private: | |||
| 3023 | } | 3062 | } |
| 3024 | 3063 | ||
| 3025 | #ifndef MOONP_NO_MACRO | 3064 | #ifndef MOONP_NO_MACRO |
| 3026 | std::pair<std::string,std::string> expandMacroStr(ChainValue_t* chainValue) { | 3065 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { |
| 3027 | const auto& chainList = chainValue->items.objects(); | 3066 | const auto& chainList = chainValue->items.objects(); |
| 3028 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); | 3067 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); |
| 3029 | auto macroName = _parser.toString(x->name); | 3068 | auto macroName = x->name ? _parser.toString(x->name) : Empty; |
| 3030 | if (!_useModule) { | 3069 | if (!macroName.empty() && !_useModule) { |
| 3031 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 3070 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); |
| 3032 | } | 3071 | } |
| 3033 | pushCurrentModule(); // cur | 3072 | pushCurrentModule(); // cur |
| 3034 | int top = lua_gettop(L) - 1; | 3073 | int top = lua_gettop(L) - 1; |
| 3035 | DEFER(lua_settop(L, top)); | 3074 | DEFER(lua_settop(L, top)); |
| 3075 | if (macroName.empty()) { | ||
| 3076 | lua_pop(L, 1); // empty | ||
| 3077 | auto item = *(++chainList.begin()); | ||
| 3078 | const node_container* args = nullptr; | ||
| 3079 | if (auto invoke = ast_cast<Invoke_t>(item)) { | ||
| 3080 | args = &invoke->args.objects(); | ||
| 3081 | } else { | ||
| 3082 | args = &ast_to<InvokeArgs_t>(item)->args.objects(); | ||
| 3083 | } | ||
| 3084 | if (args->size() != 1) { | ||
| 3085 | throw std::logic_error(_info.errorMessage("in-place macro must be followed by a compile time function"sv, x)); | ||
| 3086 | } | ||
| 3087 | auto fcodes = _parser.toString(args->back()); | ||
| 3088 | Utils::trim(fcodes); | ||
| 3089 | pushMoonp("loadstring"sv); // loadstring | ||
| 3090 | lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes | ||
| 3091 | lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk | ||
| 3092 | pushOptions(args->back()->m_begin.m_line - 1); // loadstring codes chunk options | ||
| 3093 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err | ||
| 3094 | std::string err = lua_tostring(L, -1); | ||
| 3095 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes\n"sv) + err, x)); | ||
| 3096 | } // f err | ||
| 3097 | if (lua_isnil(L, -2) != 0) { // f == nil, f err | ||
| 3098 | std::string err = lua_tostring(L, -1); | ||
| 3099 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes, at (macro in-place): "sv) + err, x)); | ||
| 3100 | } | ||
| 3101 | lua_pop(L, 1); // f | ||
| 3102 | pushMoonp("pcall"sv); // f pcall | ||
| 3103 | lua_insert(L, -2); // pcall f | ||
| 3104 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc | ||
| 3105 | std::string err = lua_tostring(L, -1); | ||
| 3106 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, x)); | ||
| 3107 | } // success res | ||
| 3108 | if (lua_toboolean(L, -2) == 0) { | ||
| 3109 | std::string err = lua_tostring(L, -1); | ||
| 3110 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, x)); | ||
| 3111 | } // true macroFunc | ||
| 3112 | lua_remove(L, -2); // macroFunc | ||
| 3113 | pushMoonp("pcall"sv); // macroFunc pcall | ||
| 3114 | lua_insert(L, -2); // pcall macroFunc | ||
| 3115 | bool success = lua_pcall(L, 1, 2, 0) == 0; | ||
| 3116 | if (!success) { // err | ||
| 3117 | std::string err = lua_tostring(L, -1); | ||
| 3118 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); | ||
| 3119 | } // success err | ||
| 3120 | if (lua_toboolean(L, -2) == 0) { | ||
| 3121 | std::string err = lua_tostring(L, -1); | ||
| 3122 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); | ||
| 3123 | } | ||
| 3124 | return {s("block"sv), Empty, {}}; | ||
| 3125 | } | ||
| 3036 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName | 3126 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName |
| 3037 | lua_rawget(L, -2); // cur[macroName], cur macro | 3127 | lua_rawget(L, -2); // cur[macroName], cur macro |
| 3038 | if (lua_istable(L, -1) == 0) { | 3128 | if (lua_istable(L, -1) == 0) { |
| @@ -3060,9 +3150,7 @@ private: | |||
| 3060 | BREAK_IF(!chainValue); | 3150 | BREAK_IF(!chainValue); |
| 3061 | BREAK_IF(!isMacroChain(chainValue)); | 3151 | BREAK_IF(!isMacroChain(chainValue)); |
| 3062 | BREAK_IF(chainValue->items.size() != 2); | 3152 | BREAK_IF(chainValue->items.size() != 2); |
| 3063 | std::string type, codes; | 3153 | str = std::get<1>(expandMacroStr(chainValue)); |
| 3064 | std::tie(type, codes) = expandMacroStr(chainValue); | ||
| 3065 | str = codes; | ||
| 3066 | BLOCK_END | 3154 | BLOCK_END |
| 3067 | if (str.empty()) { | 3155 | if (str.empty()) { |
| 3068 | // exp is reassembled due to backcall expressions | 3156 | // exp is reassembled due to backcall expressions |
| @@ -3092,30 +3180,55 @@ private: | |||
| 3092 | Utils::replace(str, "\r\n"sv, "\n"sv); | 3180 | Utils::replace(str, "\r\n"sv, "\n"sv); |
| 3093 | lua_pushlstring(L, str.c_str(), str.size()); | 3181 | lua_pushlstring(L, str.c_str(), str.size()); |
| 3094 | } // cur macro pcall func args... | 3182 | } // cur macro pcall func args... |
| 3095 | bool success = lua_pcall(L, static_cast<int>(args->size()) + 1, 2, 0) == 0; | 3183 | bool success = lua_pcall(L, static_cast<int>(args->size()) + 1, 3, 0) == 0; |
| 3096 | if (!success) { // cur macro err | 3184 | if (!success) { // cur macro err |
| 3097 | std::string err = lua_tostring(L, -1); | 3185 | std::string err = lua_tostring(L, -1); |
| 3098 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); | 3186 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); |
| 3099 | } // cur macro success res | 3187 | } // cur macro success res option |
| 3100 | if (lua_toboolean(L, -2) == 0) { | 3188 | if (lua_toboolean(L, -3) == 0) { |
| 3101 | std::string err = lua_tostring(L, -1); | 3189 | std::string err = lua_tostring(L, -2); |
| 3102 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); | 3190 | throw std::logic_error(_info.errorMessage(s("fail to expand macro: "sv) + err, x)); |
| 3103 | } | 3191 | } |
| 3104 | lua_remove(L, -2); // cur macro res | 3192 | lua_remove(L, -3); // cur macro res option |
| 3105 | if (lua_isstring(L, -1) == 0) { | 3193 | if (lua_isstring(L, -2) == 0) { |
| 3106 | throw std::logic_error(_info.errorMessage(s("macro function must return string with expanded codes"sv), x)); | 3194 | throw std::logic_error(_info.errorMessage(s("macro function must return string with expanded codes"sv), x)); |
| 3107 | } // cur macro codes | 3195 | } // cur macro codes option |
| 3108 | lua_rawgeti(L, -2, 2); // cur macro codes type | 3196 | lua_rawgeti(L, -3, 2); // cur macro codes option type |
| 3109 | std::string type = lua_tostring(L, -1); | 3197 | std::string type = lua_tostring(L, -1); |
| 3198 | lua_pop(L, 1); // cur macro codes option | ||
| 3199 | str_list localVars; | ||
| 3200 | if (lua_isnil(L, -1) == 0) { | ||
| 3201 | if (lua_istable(L, -1) == 0) { | ||
| 3202 | throw std::logic_error(_info.errorMessage(s("macro function must return expanded codes followed by a config table"sv), x)); | ||
| 3203 | } | ||
| 3204 | if (type == "expr"sv || type == "block"sv) { | ||
| 3205 | throw std::logic_error(_info.errorMessage(s("expr or block macro is not accepting config table"sv), x)); | ||
| 3206 | } | ||
| 3207 | for (int i = 0; i < static_cast<int>(lua_objlen(L, -1)); i++) { | ||
| 3208 | lua_rawgeti(L, -1, i + 1); // cur macro codes option item | ||
| 3209 | size_t len = 0; | ||
| 3210 | if (lua_isstring(L, -1) == 0) { | ||
| 3211 | throw std::logic_error(_info.errorMessage(s("macro config table must contains strings"sv), x)); | ||
| 3212 | } | ||
| 3213 | auto name = lua_tolstring(L, -1, &len); | ||
| 3214 | if (_parser.match<Variable_t>({name, len})) { | ||
| 3215 | localVars.push_back(std::string(name, len)); | ||
| 3216 | } else { | ||
| 3217 | throw std::logic_error(_info.errorMessage(s("macro config table must contains names for local variables, got \""sv) + std::string(name, len) + '"', x)); | ||
| 3218 | } | ||
| 3219 | lua_pop(L, 1); | ||
| 3220 | } | ||
| 3221 | } // cur macro codes option | ||
| 3110 | std::string codes = lua_tostring(L, -2); | 3222 | std::string codes = lua_tostring(L, -2); |
| 3111 | return {type, codes}; | 3223 | return {type, codes, std::move(localVars)}; |
| 3112 | } | 3224 | } |
| 3113 | 3225 | ||
| 3114 | std::tuple<ast_ptr<false,ast_node>, std::unique_ptr<input>, std::string> expandMacro(ChainValue_t* chainValue, ExpUsage usage, bool allowBlockMacroReturn) { | 3226 | std::tuple<ast_ptr<false,ast_node>, std::unique_ptr<input>, std::string, str_list> expandMacro(ChainValue_t* chainValue, ExpUsage usage, bool allowBlockMacroReturn) { |
| 3115 | auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>(); | 3227 | auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>(); |
| 3116 | const auto& chainList = chainValue->items.objects(); | 3228 | const auto& chainList = chainValue->items.objects(); |
| 3117 | std::string type, codes; | 3229 | std::string type, codes; |
| 3118 | std::tie(type, codes) = expandMacroStr(chainValue); | 3230 | str_list localVars; |
| 3231 | std::tie(type, codes, localVars) = expandMacroStr(chainValue); | ||
| 3119 | std::string targetType(usage != ExpUsage::Common || chainList.size() > 2 ? "expr"sv : "block"sv); | 3232 | std::string targetType(usage != ExpUsage::Common || chainList.size() > 2 ? "expr"sv : "block"sv); |
| 3120 | if (type == "lua"sv) { | 3233 | if (type == "lua"sv) { |
| 3121 | if (!allowBlockMacroReturn && targetType != "block"sv) { | 3234 | if (!allowBlockMacroReturn && targetType != "block"sv) { |
| @@ -3128,19 +3241,19 @@ private: | |||
| 3128 | std::string err = lua_tostring(L, -1); | 3241 | std::string err = lua_tostring(L, -1); |
| 3129 | throw std::logic_error(_info.errorMessage(err, x)); | 3242 | throw std::logic_error(_info.errorMessage(err, x)); |
| 3130 | } | 3243 | } |
| 3131 | return {nullptr, nullptr, std::move(codes)}; | 3244 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; |
| 3132 | } else if (type == "text"sv) { | 3245 | } else if (type == "text"sv) { |
| 3133 | if (!allowBlockMacroReturn && targetType != "block"sv) { | 3246 | if (!allowBlockMacroReturn && targetType != "block"sv) { |
| 3134 | throw std::logic_error(_info.errorMessage("text macro can only be placed where block macro is allowed"sv, x)); | 3247 | throw std::logic_error(_info.errorMessage("text macro can only be placed where block macro is allowed"sv, x)); |
| 3135 | } | 3248 | } |
| 3136 | return {nullptr, nullptr, std::move(codes)}; | 3249 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; |
| 3137 | } else if (!allowBlockMacroReturn && type != targetType) { | 3250 | } else if (!allowBlockMacroReturn && type != targetType) { |
| 3138 | throw std::logic_error(_info.errorMessage(s("macro type mismatch, "sv) + targetType + s(" expected, got "sv) + type, x)); | 3251 | throw std::logic_error(_info.errorMessage(s("macro type mismatch, "sv) + targetType + s(" expected, got "sv) + type, x)); |
| 3139 | } | 3252 | } |
| 3140 | ParseInfo info; | 3253 | ParseInfo info; |
| 3141 | if (usage == ExpUsage::Common) { | 3254 | if (usage == ExpUsage::Common) { |
| 3142 | if (codes.empty()) { | 3255 | if (codes.empty()) { |
| 3143 | return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty}; | 3256 | return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty, std::move(localVars)}; |
| 3144 | } | 3257 | } |
| 3145 | if (type == "expr"sv) { | 3258 | if (type == "expr"sv) { |
| 3146 | info = _parser.parse<Exp_t>(codes); | 3259 | info = _parser.parse<Exp_t>(codes); |
| @@ -3202,7 +3315,7 @@ private: | |||
| 3202 | info.node.set(exp); | 3315 | info.node.set(exp); |
| 3203 | } | 3316 | } |
| 3204 | } | 3317 | } |
| 3205 | return {info.node, std::move(info.codes), Empty}; | 3318 | return {info.node, std::move(info.codes), Empty, std::move(localVars)}; |
| 3206 | } | 3319 | } |
| 3207 | #endif // MOONP_NO_MACRO | 3320 | #endif // MOONP_NO_MACRO |
| 3208 | 3321 | ||
| @@ -3212,10 +3325,11 @@ private: | |||
| 3212 | ast_ptr<false,ast_node> node; | 3325 | ast_ptr<false,ast_node> node; |
| 3213 | std::unique_ptr<input> codes; | 3326 | std::unique_ptr<input> codes; |
| 3214 | std::string luaCodes; | 3327 | std::string luaCodes; |
| 3215 | std::tie(node, codes, luaCodes) = expandMacro(chainValue, usage, allowBlockMacroReturn); | 3328 | str_list localVars; |
| 3329 | std::tie(node, codes, luaCodes, localVars) = expandMacro(chainValue, usage, allowBlockMacroReturn); | ||
| 3216 | Utils::replace(luaCodes, "\r\n"sv, "\n"sv); | 3330 | Utils::replace(luaCodes, "\r\n"sv, "\n"sv); |
| 3217 | Utils::trim(luaCodes); | 3331 | Utils::trim(luaCodes); |
| 3218 | if (!node && !codes) { | 3332 | if (!node) { |
| 3219 | if (!luaCodes.empty()) { | 3333 | if (!luaCodes.empty()) { |
| 3220 | if (_config.reserveLineNumber) { | 3334 | if (_config.reserveLineNumber) { |
| 3221 | luaCodes.insert(0, nll(chainValue).substr(1)); | 3335 | luaCodes.insert(0, nll(chainValue).substr(1)); |
| @@ -3223,6 +3337,11 @@ private: | |||
| 3223 | luaCodes.append(nlr(chainValue)); | 3337 | luaCodes.append(nlr(chainValue)); |
| 3224 | } | 3338 | } |
| 3225 | out.push_back(luaCodes); | 3339 | out.push_back(luaCodes); |
| 3340 | if (!localVars.empty()) { | ||
| 3341 | for (const auto& var : localVars) { | ||
| 3342 | addToScope(var); | ||
| 3343 | } | ||
| 3344 | } | ||
| 3226 | return; | 3345 | return; |
| 3227 | } | 3346 | } |
| 3228 | if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { | 3347 | if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { |
| @@ -3254,6 +3373,7 @@ private: | |||
| 3254 | } | 3373 | } |
| 3255 | return; | 3374 | return; |
| 3256 | #else | 3375 | #else |
| 3376 | (void)allowBlockMacroReturn; | ||
| 3257 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, chainValue)); | 3377 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, chainValue)); |
| 3258 | #endif // MOONP_NO_MACRO | 3378 | #endif // MOONP_NO_MACRO |
| 3259 | } | 3379 | } |
| @@ -4983,11 +5103,9 @@ private: | |||
| 4983 | config.lintGlobalVariable = false; | 5103 | config.lintGlobalVariable = false; |
| 4984 | config.reserveLineNumber = false; | 5104 | config.reserveLineNumber = false; |
| 4985 | config.implicitReturnRoot = _config.implicitReturnRoot; | 5105 | config.implicitReturnRoot = _config.implicitReturnRoot; |
| 4986 | std::string codes, err; | 5106 | auto result = compiler.compile(text, config); |
| 4987 | GlobalVars globals; | 5107 | if (result.codes.empty() && !result.error.empty()) { |
| 4988 | std::tie(codes, err, globals) = compiler.compile(text, config); | 5108 | throw std::logic_error(_info.errorMessage(s("fail to compile module '"sv) + moduleName + s("\': "sv) + result.error, x)); |
| 4989 | if (codes.empty() && !err.empty()) { | ||
| 4990 | throw std::logic_error(_info.errorMessage(s("fail to compile module '"sv) + moduleName + s("\': "sv) + err, x)); | ||
| 4991 | } | 5109 | } |
| 4992 | lua_pop(L, 1); // cur | 5110 | lua_pop(L, 1); // cur |
| 4993 | } | 5111 | } |
| @@ -5325,12 +5443,16 @@ MoonCompiler::MoonCompiler(void* sharedState, | |||
| 5325 | #ifndef MOONP_NO_MACRO | 5443 | #ifndef MOONP_NO_MACRO |
| 5326 | _compiler(std::make_unique<MoonCompilerImpl>(static_cast<lua_State*>(sharedState), luaOpen, sameModule)) {} | 5444 | _compiler(std::make_unique<MoonCompilerImpl>(static_cast<lua_State*>(sharedState), luaOpen, sameModule)) {} |
| 5327 | #else | 5445 | #else |
| 5328 | _compiler(std::make_unique<MoonCompilerImpl>()) {} | 5446 | _compiler(std::make_unique<MoonCompilerImpl>()) { |
| 5447 | (void)sharedState; | ||
| 5448 | (void)luaOpen; | ||
| 5449 | (void)sameModule; | ||
| 5450 | } | ||
| 5329 | #endif // MOONP_NO_MACRO | 5451 | #endif // MOONP_NO_MACRO |
| 5330 | 5452 | ||
| 5331 | MoonCompiler::~MoonCompiler() {} | 5453 | MoonCompiler::~MoonCompiler() {} |
| 5332 | 5454 | ||
| 5333 | std::tuple<std::string,std::string,GlobalVars> MoonCompiler::compile(std::string_view codes, const MoonConfig& config) { | 5455 | CompileInfo MoonCompiler::compile(std::string_view codes, const MoonConfig& config) { |
| 5334 | return _compiler->compile(codes, config); | 5456 | return _compiler->compile(codes, config); |
| 5335 | } | 5457 | } |
| 5336 | 5458 | ||
