diff options
| author | Li Jin <dragon-fly@qq.com> | 2021-11-19 13:23:11 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2021-11-19 13:23:11 +0800 |
| commit | 2ff18b4fb66d25d22e5a25fb386fe171853e0b06 (patch) | |
| tree | d6e6f1671f74a4430b24869c74767aaf0ee2e128 /src/yuescript/yue_compiler.cpp | |
| parent | a8e5aaf64969792741f3a094fe0070ddb5e3bc7d (diff) | |
| download | yuescript-2ff18b4fb66d25d22e5a25fb386fe171853e0b06.tar.gz yuescript-2ff18b4fb66d25d22e5a25fb386fe171853e0b06.tar.bz2 yuescript-2ff18b4fb66d25d22e5a25fb386fe171853e0b06.zip | |
try to fix issue #69 with new macro functions. add builtin macro $MODULE and $LINE.
Diffstat (limited to '')
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 157 |
1 files changed, 86 insertions, 71 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index e004821..14e33a5 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.8.5"sv; | 63 | const std::string_view version = "0.9.0"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 { |
| @@ -68,11 +68,9 @@ public: | |||
| 68 | #ifndef YUE_NO_MACRO | 68 | #ifndef YUE_NO_MACRO |
| 69 | YueCompilerImpl(lua_State* sharedState, | 69 | YueCompilerImpl(lua_State* sharedState, |
| 70 | const std::function<void(void*)>& luaOpen, | 70 | const std::function<void(void*)>& luaOpen, |
| 71 | bool sameModule, | 71 | bool sameModule): |
| 72 | std::string_view moduleName = {}): | ||
| 73 | L(sharedState), | 72 | L(sharedState), |
| 74 | _luaOpen(luaOpen), | 73 | _luaOpen(luaOpen) { |
| 75 | _moduleName(moduleName) { | ||
| 76 | BLOCK_START | 74 | BLOCK_START |
| 77 | BREAK_IF(!sameModule); | 75 | BREAK_IF(!sameModule); |
| 78 | BREAK_IF(!L); | 76 | BREAK_IF(!L); |
| @@ -210,7 +208,6 @@ private: | |||
| 210 | std::ostringstream _buf; | 208 | std::ostringstream _buf; |
| 211 | std::ostringstream _joinBuf; | 209 | std::ostringstream _joinBuf; |
| 212 | const std::string _newLine = "\n"; | 210 | const std::string _newLine = "\n"; |
| 213 | std::string _moduleName; | ||
| 214 | 211 | ||
| 215 | enum class LocalMode { | 212 | enum class LocalMode { |
| 216 | None = 0, | 213 | None = 0, |
| @@ -863,16 +860,10 @@ private: | |||
| 863 | 860 | ||
| 864 | bool isMacroChain(ChainValue_t* chainValue) const { | 861 | bool isMacroChain(ChainValue_t* chainValue) const { |
| 865 | const auto& chainList = chainValue->items.objects(); | 862 | const auto& chainList = chainValue->items.objects(); |
| 866 | BLOCK_START | ||
| 867 | auto callable = ast_cast<Callable_t>(chainList.front()); | 863 | auto callable = ast_cast<Callable_t>(chainList.front()); |
| 868 | BREAK_IF(!callable); | 864 | if (callable && callable->item.is<MacroName_t>()) { |
| 869 | BREAK_IF(!callable->item.is<MacroName_t>()); | 865 | return true; |
| 870 | if (chainList.size() == 1 || | ||
| 871 | !ast_is<Invoke_t,InvokeArgs_t>(*(++chainList.begin()))) { | ||
| 872 | throw std::logic_error(_info.errorMessage("macro expression must be followed by arguments list"sv, callable)); | ||
| 873 | } | 866 | } |
| 874 | return true; | ||
| 875 | BLOCK_END | ||
| 876 | return false; | 867 | return false; |
| 877 | } | 868 | } |
| 878 | 869 | ||
| @@ -1052,7 +1043,7 @@ private: | |||
| 1052 | } | 1043 | } |
| 1053 | } | 1044 | } |
| 1054 | if (auto chainValue = singleValue->item.as<ChainValue_t>()) { | 1045 | if (auto chainValue = singleValue->item.as<ChainValue_t>()) { |
| 1055 | if (isChainValueCall(chainValue)) { | 1046 | if (isChainValueCall(chainValue) || isMacroChain(chainValue)) { |
| 1056 | transformChainValue(chainValue, out, ExpUsage::Common); | 1047 | transformChainValue(chainValue, out, ExpUsage::Common); |
| 1057 | break; | 1048 | break; |
| 1058 | } | 1049 | } |
| @@ -3139,8 +3130,8 @@ private: | |||
| 3139 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, macro->macroLit)); | 3130 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, macro->macroLit)); |
| 3140 | } // cur true macro | 3131 | } // cur true macro |
| 3141 | lua_remove(L, -2); // cur macro | 3132 | lua_remove(L, -2); // cur macro |
| 3142 | if (exporting && !_moduleName.empty()) { | 3133 | if (exporting && _config.exporting && !_config.module.empty()) { |
| 3143 | pushModuleTable(_moduleName); // cur macro module | 3134 | pushModuleTable(_config.module); // cur macro module |
| 3144 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | 3135 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name |
| 3145 | lua_pushvalue(L, -3); // cur macro module name macro | 3136 | lua_pushvalue(L, -3); // cur macro module name macro |
| 3146 | lua_rawset(L, -3); // cur macro module | 3137 | lua_rawset(L, -3); // cur macro module |
| @@ -3929,11 +3920,23 @@ private: | |||
| 3929 | } | 3920 | } |
| 3930 | 3921 | ||
| 3931 | #ifndef YUE_NO_MACRO | 3922 | #ifndef YUE_NO_MACRO |
| 3923 | std::string expandBuiltinMacro(const std::string& name, ast_node* x) { | ||
| 3924 | if (name == "LINE"sv) { | ||
| 3925 | return std::to_string(x->m_begin.m_line + _config.lineOffset); | ||
| 3926 | } | ||
| 3927 | if (name == "MODULE"sv) { | ||
| 3928 | return _config.module.empty() ? "\"yuescript\""s : '"' + _config.module + '"'; | ||
| 3929 | } | ||
| 3930 | return Empty; | ||
| 3931 | } | ||
| 3932 | |||
| 3932 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { | 3933 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { |
| 3933 | const auto& chainList = chainValue->items.objects(); | 3934 | const auto& chainList = chainValue->items.objects(); |
| 3934 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); | 3935 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); |
| 3935 | auto macroName = x->name ? _parser.toString(x->name) : Empty; | 3936 | auto macroName = x->name ? _parser.toString(x->name) : Empty; |
| 3936 | if (!macroName.empty() && !_useModule) { | 3937 | if (!macroName.empty() && !_useModule) { |
| 3938 | auto code = expandBuiltinMacro(macroName, x); | ||
| 3939 | if (!code.empty()) return {Empty, code, {}}; | ||
| 3937 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 3940 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); |
| 3938 | } | 3941 | } |
| 3939 | pushCurrentModule(); // cur | 3942 | pushCurrentModule(); // cur |
| @@ -3941,8 +3944,8 @@ private: | |||
| 3941 | DEFER(lua_settop(L, top)); | 3944 | DEFER(lua_settop(L, top)); |
| 3942 | if (macroName.empty()) { | 3945 | if (macroName.empty()) { |
| 3943 | lua_pop(L, 1); // empty | 3946 | lua_pop(L, 1); // empty |
| 3944 | auto item = *(++chainList.begin()); | ||
| 3945 | const node_container* args = nullptr; | 3947 | const node_container* args = nullptr; |
| 3948 | auto item = *(++chainList.begin()); | ||
| 3946 | if (auto invoke = ast_cast<Invoke_t>(item)) { | 3949 | if (auto invoke = ast_cast<Invoke_t>(item)) { |
| 3947 | args = &invoke->args.objects(); | 3950 | args = &invoke->args.objects(); |
| 3948 | } else { | 3951 | } else { |
| @@ -3993,60 +3996,69 @@ private: | |||
| 3993 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName | 3996 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName |
| 3994 | lua_rawget(L, -2); // cur[macroName], cur macroFunc | 3997 | lua_rawget(L, -2); // cur[macroName], cur macroFunc |
| 3995 | if (lua_isfunction(L, -1) == 0) { | 3998 | if (lua_isfunction(L, -1) == 0) { |
| 3999 | auto code = expandBuiltinMacro(macroName, x); | ||
| 4000 | if (!code.empty()) return {Empty, code, {}}; | ||
| 3996 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 4001 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); |
| 3997 | } // cur macroFunc | 4002 | } // cur macroFunc |
| 3998 | pushYue("pcall"sv); // cur macroFunc pcall | 4003 | pushYue("pcall"sv); // cur macroFunc pcall |
| 3999 | lua_insert(L, -2); // cur pcall macroFunc | 4004 | lua_insert(L, -2); // cur pcall macroFunc |
| 4000 | auto item = *(++chainList.begin()); | ||
| 4001 | const node_container* args = nullptr; | 4005 | const node_container* args = nullptr; |
| 4002 | if (auto invoke = ast_cast<Invoke_t>(item)) { | 4006 | if (chainList.size() > 1) { |
| 4003 | args = &invoke->args.objects(); | 4007 | auto item = *(++chainList.begin()); |
| 4004 | } else { | 4008 | if (auto invoke = ast_cast<Invoke_t>(item)) { |
| 4005 | args = &ast_to<InvokeArgs_t>(item)->args.objects(); | 4009 | args = &invoke->args.objects(); |
| 4006 | } | 4010 | } else if (auto invoke = ast_cast<InvokeArgs_t>(item)){ |
| 4007 | for (auto arg : *args) { | 4011 | args = &invoke->args.objects(); |
| 4008 | std::string str; | 4012 | } |
| 4009 | // check whether arg is reassembled | 4013 | } |
| 4010 | // do some workaround for pipe expression | 4014 | if (args) { |
| 4011 | if (ast_is<Exp_t>(arg) && arg->m_begin.m_it == arg->m_end.m_it) { | 4015 | for (auto arg : *args) { |
| 4012 | auto exp = static_cast<Exp_t*>(arg); | 4016 | std::string str; |
| 4013 | BLOCK_START | 4017 | bool rawString = false; |
| 4014 | BREAK_IF(!exp->opValues.empty()); | 4018 | if (auto lstr = ast_cast<LuaString_t>(arg)) { |
| 4015 | auto chainValue = exp->getByPath<unary_exp_t, Value_t, ChainValue_t>(); | 4019 | str = _parser.toString(lstr->content); |
| 4016 | BREAK_IF(!chainValue); | 4020 | rawString = true; |
| 4017 | BREAK_IF(!isMacroChain(chainValue)); | 4021 | } else { |
| 4018 | BREAK_IF(chainValue->items.size() != 2); | 4022 | BLOCK_START |
| 4019 | str = std::get<1>(expandMacroStr(chainValue)); | 4023 | auto exp = ast_cast<Exp_t>(arg); |
| 4020 | BLOCK_END | 4024 | BREAK_IF(!exp); |
| 4021 | if (str.empty()) { | 4025 | auto value = singleValueFrom(exp); |
| 4022 | // exp is reassembled due to pipe expressions | 4026 | BREAK_IF(!value); |
| 4023 | // in transform stage, toString(exp) won't be able | 4027 | auto lstr = value->getByPath<String_t, LuaString_t>(); |
| 4024 | // to convert its whole text content | 4028 | BREAK_IF(!lstr); |
| 4025 | str = _parser.toString(exp->pipeExprs.front()); | 4029 | str = _parser.toString(lstr->content); |
| 4026 | } | 4030 | rawString = true; |
| 4027 | } else if (auto lstr = ast_cast<LuaString_t>(arg)) { | 4031 | BLOCK_END |
| 4028 | str = _parser.toString(lstr->content); | 4032 | } |
| 4029 | } else { | 4033 | if (!rawString && str.empty()) { |
| 4030 | bool multiLineStr = false; | 4034 | // check whether arg is reassembled |
| 4031 | BLOCK_START | 4035 | // do some workaround for pipe expression |
| 4032 | auto exp = ast_cast<Exp_t>(arg); | 4036 | if (ast_is<Exp_t>(arg)) { |
| 4033 | BREAK_IF(!exp); | 4037 | auto exp = static_cast<Exp_t*>(arg); |
| 4034 | auto value = singleValueFrom(exp); | 4038 | BLOCK_START |
| 4035 | BREAK_IF(!value); | 4039 | BREAK_IF(!exp->opValues.empty()); |
| 4036 | auto lstr = value->getByPath<String_t, LuaString_t>(); | 4040 | auto chainValue = exp->getByPath<unary_exp_t, Value_t, ChainValue_t>(); |
| 4037 | BREAK_IF(!lstr); | 4041 | BREAK_IF(!chainValue); |
| 4038 | str = _parser.toString(lstr->content); | 4042 | BREAK_IF(!isMacroChain(chainValue)); |
| 4039 | multiLineStr = true; | 4043 | str = std::get<1>(expandMacroStr(chainValue)); |
| 4040 | BLOCK_END | 4044 | BLOCK_END |
| 4041 | if (!multiLineStr) { | 4045 | if (str.empty() && arg->m_begin.m_it == arg->m_end.m_it) { |
| 4046 | // exp is reassembled due to pipe expressions | ||
| 4047 | // in transform stage, toString(exp) won't be able | ||
| 4048 | // to convert its whole text content | ||
| 4049 | str = _parser.toString(exp->pipeExprs.front()); | ||
| 4050 | } | ||
| 4051 | } | ||
| 4052 | } | ||
| 4053 | if (!rawString && str.empty()) { | ||
| 4042 | str = _parser.toString(arg); | 4054 | str = _parser.toString(arg); |
| 4043 | } | 4055 | } |
| 4044 | } | 4056 | Utils::trim(str); |
| 4045 | Utils::trim(str); | 4057 | Utils::replace(str, "\r\n"sv, "\n"sv); |
| 4046 | Utils::replace(str, "\r\n"sv, "\n"sv); | 4058 | lua_pushlstring(L, str.c_str(), str.size()); |
| 4047 | lua_pushlstring(L, str.c_str(), str.size()); | 4059 | } // cur pcall macroFunc args... |
| 4048 | } // cur pcall macroFunc args... | 4060 | } |
| 4049 | bool success = lua_pcall(L, static_cast<int>(args->size()) + 1, 2, 0) == 0; | 4061 | bool success = lua_pcall(L, (args ? static_cast<int>(args->size()) : 0) + 1, 2, 0) == 0; |
| 4050 | if (!success) { // cur err | 4062 | if (!success) { // cur err |
| 4051 | std::string err = lua_tostring(L, -1); | 4063 | std::string err = lua_tostring(L, -1); |
| 4052 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | 4064 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); |
| @@ -4063,11 +4075,11 @@ private: | |||
| 4063 | std::string type; | 4075 | std::string type; |
| 4064 | str_list localVars; | 4076 | str_list localVars; |
| 4065 | if (lua_istable(L, -1) != 0) { | 4077 | if (lua_istable(L, -1) != 0) { |
| 4066 | lua_getfield(L, -1, "codes"); // cur res codes | 4078 | lua_getfield(L, -1, "code"); // cur res code |
| 4067 | if (lua_isstring(L, -1) != 0) { | 4079 | if (lua_isstring(L, -1) != 0) { |
| 4068 | codes = lua_tostring(L, -1); | 4080 | codes = lua_tostring(L, -1); |
| 4069 | } else { | 4081 | } else { |
| 4070 | throw std::logic_error(_info.errorMessage("macro table must contain field \"codes\" of string"sv, x)); | 4082 | throw std::logic_error(_info.errorMessage("macro table must contain field \"code\" of string"sv, x)); |
| 4071 | } | 4083 | } |
| 4072 | lua_pop(L, 1); // cur res | 4084 | lua_pop(L, 1); // cur res |
| 4073 | lua_getfield(L, -1, "type"); // cur res type | 4085 | lua_getfield(L, -1, "type"); // cur res type |
| @@ -4108,7 +4120,7 @@ private: | |||
| 4108 | std::string type, codes; | 4120 | std::string type, codes; |
| 4109 | str_list localVars; | 4121 | str_list localVars; |
| 4110 | std::tie(type, codes, localVars) = expandMacroStr(chainValue); | 4122 | std::tie(type, codes, localVars) = expandMacroStr(chainValue); |
| 4111 | bool isBlock = (usage == ExpUsage::Common) && (chainList.size() <= 2); | 4123 | bool isBlock = (usage == ExpUsage::Common) && (chainList.size() < 2 || (chainList.size() == 2 && ast_is<Invoke_t, InvokeArgs_t>(chainList.back()))); |
| 4112 | ParseInfo info; | 4124 | ParseInfo info; |
| 4113 | if (type == "lua"sv) { | 4125 | if (type == "lua"sv) { |
| 4114 | if (!isBlock) { | 4126 | if (!isBlock) { |
| @@ -4161,7 +4173,7 @@ private: | |||
| 4161 | if (!isBlock) { | 4173 | if (!isBlock) { |
| 4162 | ast_ptr<false, Exp_t> exp; | 4174 | ast_ptr<false, Exp_t> exp; |
| 4163 | exp.set(info.node); | 4175 | exp.set(info.node); |
| 4164 | if (!exp->opValues.empty() || chainList.size() > 2) { | 4176 | if (!exp->opValues.empty() || (chainList.size() > 2 || (chainList.size() == 2 && !ast_is<Invoke_t, InvokeArgs_t>(chainList.back())))) { |
| 4165 | auto paren = x->new_ptr<Parens_t>(); | 4177 | auto paren = x->new_ptr<Parens_t>(); |
| 4166 | paren->expr.set(exp); | 4178 | paren->expr.set(exp); |
| 4167 | auto callable = x->new_ptr<Callable_t>(); | 4179 | auto callable = x->new_ptr<Callable_t>(); |
| @@ -4169,7 +4181,8 @@ private: | |||
| 4169 | auto newChain = x->new_ptr<ChainValue_t>(); | 4181 | auto newChain = x->new_ptr<ChainValue_t>(); |
| 4170 | newChain->items.push_back(callable); | 4182 | newChain->items.push_back(callable); |
| 4171 | auto it = chainList.begin(); | 4183 | auto it = chainList.begin(); |
| 4172 | it++; it++; | 4184 | it++; |
| 4185 | if (chainList.size() > 1 && ast_is<Invoke_t, InvokeArgs_t>(*it)) it++; | ||
| 4173 | for (; it != chainList.end(); ++it) { | 4186 | for (; it != chainList.end(); ++it) { |
| 4174 | newChain->items.push_back(*it); | 4187 | newChain->items.push_back(*it); |
| 4175 | } | 4188 | } |
| @@ -6146,12 +6159,14 @@ private: | |||
| 6146 | throw std::logic_error(_info.errorMessage("failed to get module text"sv, x)); | 6159 | throw std::logic_error(_info.errorMessage("failed to get module text"sv, x)); |
| 6147 | } // cur text | 6160 | } // cur text |
| 6148 | std::string text = lua_tostring(L, -1); | 6161 | std::string text = lua_tostring(L, -1); |
| 6149 | auto compiler = YueCompilerImpl(L, _luaOpen, false, moduleFullName); | 6162 | auto compiler = YueCompilerImpl(L, _luaOpen, false); |
| 6150 | YueConfig config; | 6163 | YueConfig config; |
| 6151 | config.lineOffset = 0; | 6164 | config.lineOffset = 0; |
| 6152 | config.lintGlobalVariable = false; | 6165 | config.lintGlobalVariable = false; |
| 6153 | config.reserveLineNumber = false; | 6166 | config.reserveLineNumber = false; |
| 6154 | config.implicitReturnRoot = _config.implicitReturnRoot; | 6167 | config.implicitReturnRoot = _config.implicitReturnRoot; |
| 6168 | config.module = moduleFullName; | ||
| 6169 | config.exporting = true; | ||
| 6155 | auto result = compiler.compile(text, config); | 6170 | auto result = compiler.compile(text, config); |
| 6156 | if (result.codes.empty() && !result.error.empty()) { | 6171 | if (result.codes.empty() && !result.error.empty()) { |
| 6157 | throw std::logic_error(_info.errorMessage("failed to compile module '"s + moduleName + "\': "s + result.error, x)); | 6172 | throw std::logic_error(_info.errorMessage("failed to compile module '"s + moduleName + "\': "s + result.error, x)); |
