diff options
| author | Li Jin <dragon-fly@qq.com> | 2021-11-22 01:48:26 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2021-11-22 01:48:26 +0800 |
| commit | 125f709b065acb35bcd216001720c0bb4635dd25 (patch) | |
| tree | 6059f57b12de2ba852197d3e2902b1741e47b42c /src/yuescript/yue_compiler.cpp | |
| parent | 2ff18b4fb66d25d22e5a25fb386fe171853e0b06 (diff) | |
| download | yuescript-125f709b065acb35bcd216001720c0bb4635dd25.tar.gz yuescript-125f709b065acb35bcd216001720c0bb4635dd25.tar.bz2 yuescript-125f709b065acb35bcd216001720c0bb4635dd25.zip | |
clean up.
Diffstat (limited to '')
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 196 |
1 files changed, 97 insertions, 99 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 14e33a5..b3f6bdd 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -60,7 +60,7 @@ using namespace parserlib; | |||
| 60 | 60 | ||
| 61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
| 62 | 62 | ||
| 63 | const std::string_view version = "0.9.0"sv; | 63 | const std::string_view version = "0.9.1"sv; |
| 64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
| 65 | 65 | ||
| 66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
| @@ -1007,6 +1007,7 @@ private: | |||
| 1007 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; | 1007 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; |
| 1008 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; | 1008 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; |
| 1009 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; | 1009 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; |
| 1010 | case id<MacroInPlace_t>(): transformMacroInPlace(static_cast<MacroInPlace_t*>(content)); break; | ||
| 1010 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 1011 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
| 1011 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; | 1012 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; |
| 1012 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; | 1013 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; |
| @@ -3919,6 +3920,55 @@ private: | |||
| 3919 | } | 3920 | } |
| 3920 | } | 3921 | } |
| 3921 | 3922 | ||
| 3923 | void transformMacroInPlace(MacroInPlace_t* macroInPlace) { | ||
| 3924 | #ifdef YUE_NO_MACRO | ||
| 3925 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macroInPlace)); | ||
| 3926 | #else // YUE_NO_MACRO | ||
| 3927 | auto x = macroInPlace; | ||
| 3928 | pushCurrentModule(); // cur | ||
| 3929 | int top = lua_gettop(L) - 1; | ||
| 3930 | DEFER(lua_settop(L, top)); | ||
| 3931 | lua_pop(L, 1); // empty | ||
| 3932 | auto fcodes = _parser.toString(macroInPlace).substr(1); | ||
| 3933 | Utils::trim(fcodes); | ||
| 3934 | pushYue("loadstring"sv); // loadstring | ||
| 3935 | lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes | ||
| 3936 | lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk | ||
| 3937 | pushOptions(macroInPlace->m_begin.m_line - 1); // loadstring codes chunk options | ||
| 3938 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err | ||
| 3939 | std::string err = lua_tostring(L, -1); | ||
| 3940 | throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); | ||
| 3941 | } // f err | ||
| 3942 | if (lua_isnil(L, -2) != 0) { // f == nil, f err | ||
| 3943 | std::string err = lua_tostring(L, -1); | ||
| 3944 | throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); | ||
| 3945 | } | ||
| 3946 | lua_pop(L, 1); // f | ||
| 3947 | pushYue("pcall"sv); // f pcall | ||
| 3948 | lua_insert(L, -2); // pcall f | ||
| 3949 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc | ||
| 3950 | std::string err = lua_tostring(L, -1); | ||
| 3951 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
| 3952 | } // success res | ||
| 3953 | if (lua_toboolean(L, -2) == 0) { | ||
| 3954 | std::string err = lua_tostring(L, -1); | ||
| 3955 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
| 3956 | } // true macroFunc | ||
| 3957 | lua_remove(L, -2); // macroFunc | ||
| 3958 | pushYue("pcall"sv); // macroFunc pcall | ||
| 3959 | lua_insert(L, -2); // pcall macroFunc | ||
| 3960 | bool success = lua_pcall(L, 1, 2, 0) == 0; | ||
| 3961 | if (!success) { // err | ||
| 3962 | std::string err = lua_tostring(L, -1); | ||
| 3963 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
| 3964 | } // success err | ||
| 3965 | if (lua_toboolean(L, -2) == 0) { | ||
| 3966 | std::string err = lua_tostring(L, -1); | ||
| 3967 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
| 3968 | } | ||
| 3969 | #endif // YUE_NO_MACRO | ||
| 3970 | } | ||
| 3971 | |||
| 3922 | #ifndef YUE_NO_MACRO | 3972 | #ifndef YUE_NO_MACRO |
| 3923 | std::string expandBuiltinMacro(const std::string& name, ast_node* x) { | 3973 | std::string expandBuiltinMacro(const std::string& name, ast_node* x) { |
| 3924 | if (name == "LINE"sv) { | 3974 | if (name == "LINE"sv) { |
| @@ -3933,8 +3983,8 @@ private: | |||
| 3933 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { | 3983 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { |
| 3934 | const auto& chainList = chainValue->items.objects(); | 3984 | const auto& chainList = chainValue->items.objects(); |
| 3935 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); | 3985 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); |
| 3936 | auto macroName = x->name ? _parser.toString(x->name) : Empty; | 3986 | auto macroName = _parser.toString(x->name); |
| 3937 | if (!macroName.empty() && !_useModule) { | 3987 | if (!_useModule) { |
| 3938 | auto code = expandBuiltinMacro(macroName, x); | 3988 | auto code = expandBuiltinMacro(macroName, x); |
| 3939 | if (!code.empty()) return {Empty, code, {}}; | 3989 | if (!code.empty()) return {Empty, code, {}}; |
| 3940 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 3990 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); |
| @@ -3942,57 +3992,6 @@ private: | |||
| 3942 | pushCurrentModule(); // cur | 3992 | pushCurrentModule(); // cur |
| 3943 | int top = lua_gettop(L) - 1; | 3993 | int top = lua_gettop(L) - 1; |
| 3944 | DEFER(lua_settop(L, top)); | 3994 | DEFER(lua_settop(L, top)); |
| 3945 | if (macroName.empty()) { | ||
| 3946 | lua_pop(L, 1); // empty | ||
| 3947 | const node_container* args = nullptr; | ||
| 3948 | auto item = *(++chainList.begin()); | ||
| 3949 | if (auto invoke = ast_cast<Invoke_t>(item)) { | ||
| 3950 | args = &invoke->args.objects(); | ||
| 3951 | } else { | ||
| 3952 | args = &ast_to<InvokeArgs_t>(item)->args.objects(); | ||
| 3953 | } | ||
| 3954 | if (args->size() != 1) { | ||
| 3955 | throw std::logic_error(_info.errorMessage("in-place macro must be followed by a compile time function"sv, x)); | ||
| 3956 | } | ||
| 3957 | auto fcodes = _parser.toString(args->back()); | ||
| 3958 | Utils::trim(fcodes); | ||
| 3959 | pushYue("loadstring"sv); // loadstring | ||
| 3960 | lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes | ||
| 3961 | lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk | ||
| 3962 | pushOptions(args->back()->m_begin.m_line - 1); // loadstring codes chunk options | ||
| 3963 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err | ||
| 3964 | std::string err = lua_tostring(L, -1); | ||
| 3965 | throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); | ||
| 3966 | } // f err | ||
| 3967 | if (lua_isnil(L, -2) != 0) { // f == nil, f err | ||
| 3968 | std::string err = lua_tostring(L, -1); | ||
| 3969 | throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); | ||
| 3970 | } | ||
| 3971 | lua_pop(L, 1); // f | ||
| 3972 | pushYue("pcall"sv); // f pcall | ||
| 3973 | lua_insert(L, -2); // pcall f | ||
| 3974 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc | ||
| 3975 | std::string err = lua_tostring(L, -1); | ||
| 3976 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
| 3977 | } // success res | ||
| 3978 | if (lua_toboolean(L, -2) == 0) { | ||
| 3979 | std::string err = lua_tostring(L, -1); | ||
| 3980 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
| 3981 | } // true macroFunc | ||
| 3982 | lua_remove(L, -2); // macroFunc | ||
| 3983 | pushYue("pcall"sv); // macroFunc pcall | ||
| 3984 | lua_insert(L, -2); // pcall macroFunc | ||
| 3985 | bool success = lua_pcall(L, 1, 2, 0) == 0; | ||
| 3986 | if (!success) { // err | ||
| 3987 | std::string err = lua_tostring(L, -1); | ||
| 3988 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
| 3989 | } // success err | ||
| 3990 | if (lua_toboolean(L, -2) == 0) { | ||
| 3991 | std::string err = lua_tostring(L, -1); | ||
| 3992 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
| 3993 | } | ||
| 3994 | return {Empty, Empty, {}}; | ||
| 3995 | } | ||
| 3996 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName | 3995 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName |
| 3997 | lua_rawget(L, -2); // cur[macroName], cur macroFunc | 3996 | lua_rawget(L, -2); // cur[macroName], cur macroFunc |
| 3998 | if (lua_isfunction(L, -1) == 0) { | 3997 | if (lua_isfunction(L, -1) == 0) { |
| @@ -6097,38 +6096,49 @@ private: | |||
| 6097 | auto name = moduleNameFrom(import->literal); | 6096 | auto name = moduleNameFrom(import->literal); |
| 6098 | import->target.set(toAst<Variable_t>(name, x)); | 6097 | import->target.set(toAst<Variable_t>(name, x)); |
| 6099 | } | 6098 | } |
| 6100 | if (auto tabLit = import->target.as<ImportTabLit_t>()) { | 6099 | if (ast_is<import_all_macro_t, ImportTabLit_t>(import->target)) { |
| 6101 | auto newTab = x->new_ptr<ImportTabLit_t>(); | 6100 | bool importAllMacro = import->target.is<import_all_macro_t>(); |
| 6102 | #ifndef YUE_NO_MACRO | ||
| 6103 | bool importAllMacro = false; | ||
| 6104 | std::list<std::pair<std::string,std::string>> macroPairs; | 6101 | std::list<std::pair<std::string,std::string>> macroPairs; |
| 6105 | for (auto item : tabLit->items.objects()) { | 6102 | auto newTab = x->new_ptr<ImportTabLit_t>(); |
| 6106 | switch (item->getId()) { | 6103 | if (auto tabLit = import->target.as<ImportTabLit_t>()) { |
| 6107 | case id<MacroName_t>(): { | 6104 | for (auto item : tabLit->items.objects()) { |
| 6108 | auto macroName = static_cast<MacroName_t*>(item); | 6105 | switch (item->getId()) { |
| 6109 | auto name = _parser.toString(macroName->name); | 6106 | #ifdef YUE_NO_MACRO |
| 6110 | macroPairs.emplace_back(name, name); | 6107 | case id<MacroName_t>(): |
| 6111 | break; | 6108 | case id<macro_name_pair_t>(): |
| 6112 | } | 6109 | case id<import_all_macro_t>(): { |
| 6113 | case id<macro_name_pair_t>(): { | 6110 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); |
| 6114 | auto pair = static_cast<macro_name_pair_t*>(item); | 6111 | break; |
| 6115 | macroPairs.emplace_back(_parser.toString(pair->key->name), _parser.toString(pair->value->name)); | 6112 | } |
| 6116 | break; | 6113 | #else // YUE_NO_MACRO |
| 6114 | case id<MacroName_t>(): { | ||
| 6115 | auto macroName = static_cast<MacroName_t*>(item); | ||
| 6116 | auto name = _parser.toString(macroName->name); | ||
| 6117 | macroPairs.emplace_back(name, name); | ||
| 6118 | break; | ||
| 6119 | } | ||
| 6120 | case id<macro_name_pair_t>(): { | ||
| 6121 | auto pair = static_cast<macro_name_pair_t*>(item); | ||
| 6122 | macroPairs.emplace_back(_parser.toString(pair->key->name), _parser.toString(pair->value->name)); | ||
| 6123 | break; | ||
| 6124 | } | ||
| 6125 | case id<import_all_macro_t>(): | ||
| 6126 | if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); | ||
| 6127 | importAllMacro = true; | ||
| 6128 | break; | ||
| 6129 | #endif // YUE_NO_MACRO | ||
| 6130 | case id<variable_pair_t>(): | ||
| 6131 | case id<normal_pair_t>(): | ||
| 6132 | case id<meta_variable_pair_t>(): | ||
| 6133 | case id<meta_normal_pair_t>(): | ||
| 6134 | case id<Exp_t>(): | ||
| 6135 | newTab->items.push_back(item); | ||
| 6136 | break; | ||
| 6137 | default: YUEE("AST node mismatch", item); break; | ||
| 6117 | } | 6138 | } |
| 6118 | case id<import_all_macro_t>(): | ||
| 6119 | if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); | ||
| 6120 | importAllMacro = true; | ||
| 6121 | break; | ||
| 6122 | case id<variable_pair_t>(): | ||
| 6123 | case id<normal_pair_t>(): | ||
| 6124 | case id<meta_variable_pair_t>(): | ||
| 6125 | case id<meta_normal_pair_t>(): | ||
| 6126 | case id<Exp_t>(): | ||
| 6127 | newTab->items.push_back(item); | ||
| 6128 | break; | ||
| 6129 | default: YUEE("AST node mismatch", item); break; | ||
| 6130 | } | 6139 | } |
| 6131 | } | 6140 | } |
| 6141 | #ifndef YUE_NO_MACRO | ||
| 6132 | if (importAllMacro || !macroPairs.empty()) { | 6142 | if (importAllMacro || !macroPairs.empty()) { |
| 6133 | auto moduleName = _parser.toString(import->literal); | 6143 | auto moduleName = _parser.toString(import->literal); |
| 6134 | Utils::replace(moduleName, "'"sv, ""sv); | 6144 | Utils::replace(moduleName, "'"sv, ""sv); |
| @@ -6188,21 +6198,8 @@ private: | |||
| 6188 | } | 6198 | } |
| 6189 | } | 6199 | } |
| 6190 | #else // YUE_NO_MACRO | 6200 | #else // YUE_NO_MACRO |
| 6191 | for (auto item : tabLit->items.objects()) { | 6201 | if (importAllMacro) { |
| 6192 | switch (item->getId()) { | 6202 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, import->target)); |
| 6193 | case id<MacroName_t>(): | ||
| 6194 | case id<macro_name_pair_t>(): | ||
| 6195 | case id<import_all_macro_t>(): { | ||
| 6196 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); | ||
| 6197 | break; | ||
| 6198 | } | ||
| 6199 | case id<variable_pair_t>(): | ||
| 6200 | case id<normal_pair_t>(): | ||
| 6201 | case id<Exp_t>(): | ||
| 6202 | newTab->items.push_back(item); | ||
| 6203 | break; | ||
| 6204 | default: YUEE("AST node mismatch", item); break; | ||
| 6205 | } | ||
| 6206 | } | 6203 | } |
| 6207 | #endif // YUE_NO_MACRO | 6204 | #endif // YUE_NO_MACRO |
| 6208 | if (newTab->items.empty()) { | 6205 | if (newTab->items.empty()) { |
| @@ -6220,13 +6217,14 @@ private: | |||
| 6220 | auto chainValue = x->new_ptr<ChainValue_t>(); | 6217 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| 6221 | chainValue->items.push_back(callable); | 6218 | chainValue->items.push_back(callable); |
| 6222 | value->item.set(chainValue); | 6219 | value->item.set(chainValue); |
| 6223 | } else { | 6220 | } else if (auto tabLit = ast_cast<ImportTabLit_t>(target)) { |
| 6224 | auto tabLit = ast_to<ImportTabLit_t>(target); | ||
| 6225 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 6221 | auto simpleValue = x->new_ptr<SimpleValue_t>(); |
| 6226 | auto tableLit = x->new_ptr<TableLit_t>(); | 6222 | auto tableLit = x->new_ptr<TableLit_t>(); |
| 6227 | tableLit->values.dup(tabLit->items); | 6223 | tableLit->values.dup(tabLit->items); |
| 6228 | simpleValue->value.set(tableLit); | 6224 | simpleValue->value.set(tableLit); |
| 6229 | value->item.set(simpleValue); | 6225 | value->item.set(simpleValue); |
| 6226 | } else { | ||
| 6227 | return; | ||
| 6230 | } | 6228 | } |
| 6231 | auto exp = newExp(value, x); | 6229 | auto exp = newExp(value, x); |
| 6232 | auto assignList = x->new_ptr<ExpList_t>(); | 6230 | auto assignList = x->new_ptr<ExpList_t>(); |
