aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-11-19 13:23:11 +0800
committerLi Jin <dragon-fly@qq.com>2021-11-19 13:23:11 +0800
commit2ff18b4fb66d25d22e5a25fb386fe171853e0b06 (patch)
treed6e6f1671f74a4430b24869c74767aaf0ee2e128 /src
parenta8e5aaf64969792741f3a094fe0070ddb5e3bc7d (diff)
downloadyuescript-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 'src')
-rw-r--r--src/yue.cpp6
-rw-r--r--src/yuescript/stacktraceplus.h2
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp157
-rw-r--r--src/yuescript/yue_compiler.h2
-rw-r--r--src/yuescript/yuescript.cpp6
-rw-r--r--src/yuescript/yuescript.h3
6 files changed, 101 insertions, 75 deletions
diff --git a/src/yue.cpp b/src/yue.cpp
index b04bd92..1704b57 100644
--- a/src/yue.cpp
+++ b/src/yue.cpp
@@ -429,9 +429,11 @@ int main(int narg, const char** args) {
429 std::string s( 429 std::string s(
430 (std::istreambuf_iterator<char>(input)), 430 (std::istreambuf_iterator<char>(input)),
431 std::istreambuf_iterator<char>()); 431 std::istreambuf_iterator<char>());
432 auto conf = config;
433 conf.module = file.first;
432 if (dumpCompileTime) { 434 if (dumpCompileTime) {
433 auto start = std::chrono::high_resolution_clock::now(); 435 auto start = std::chrono::high_resolution_clock::now();
434 auto result = yue::YueCompiler{YUE_ARGS}.compile(s, config); 436 auto result = yue::YueCompiler{YUE_ARGS}.compile(s, conf);
435 auto end = std::chrono::high_resolution_clock::now(); 437 auto end = std::chrono::high_resolution_clock::now();
436 if (!result.codes.empty()) { 438 if (!result.codes.empty()) {
437 std::chrono::duration<double> diff = end - start; 439 std::chrono::duration<double> diff = end - start;
@@ -451,7 +453,7 @@ int main(int narg, const char** args) {
451 return std::tuple{1, file.first, buf.str()}; 453 return std::tuple{1, file.first, buf.str()};
452 } 454 }
453 } 455 }
454 auto result = yue::YueCompiler{YUE_ARGS}.compile(s, config); 456 auto result = yue::YueCompiler{YUE_ARGS}.compile(s, conf);
455 if (result.error.empty()) { 457 if (result.error.empty()) {
456 if (!writeToFile) { 458 if (!writeToFile) {
457 return std::tuple{0, file.first, result.codes + '\n'}; 459 return std::tuple{0, file.first, result.codes + '\n'};
diff --git a/src/yuescript/stacktraceplus.h b/src/yuescript/stacktraceplus.h
index ac61ba7..83460ef 100644
--- a/src/yuescript/stacktraceplus.h
+++ b/src/yuescript/stacktraceplus.h
@@ -335,7 +335,7 @@ local function getYueLineNumber(fname, line)
335 end 335 end
336 if file_exist then 336 if file_exist then
337 local codes = yue.read_file(file_path) 337 local codes = yue.read_file(file_path)
338 local yueFile = codes:match("^%s*--%s*%[yue%]:%s*([^\n]*)") 338 local yueFile = codes:match("^%s*--%s*%[.*%]:%s*([^\n]*)")
339 if yueFile then 339 if yueFile then
340 fname = yueFile:gsub("^%s*(.-)%s*$", "%1") 340 fname = yueFile:gsub("^%s*(.-)%s*$", "%1")
341 source = codes 341 source = codes
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
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.8.5"sv; 63const std::string_view version = "0.9.0"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class 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));
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h
index 2e8c86a..f15bcfb 100644
--- a/src/yuescript/yue_compiler.h
+++ b/src/yuescript/yue_compiler.h
@@ -28,7 +28,9 @@ struct YueConfig {
28 bool implicitReturnRoot = true; 28 bool implicitReturnRoot = true;
29 bool reserveLineNumber = true; 29 bool reserveLineNumber = true;
30 bool useSpaceOverTab = false; 30 bool useSpaceOverTab = false;
31 bool exporting = false;
31 int lineOffset = 0; 32 int lineOffset = 0;
33 std::string module;
32 Options options; 34 Options options;
33}; 35};
34 36
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp
index d534f3e..b83a454 100644
--- a/src/yuescript/yuescript.cpp
+++ b/src/yuescript/yuescript.cpp
@@ -85,6 +85,12 @@ static int yuetolua(lua_State* L) {
85 config.lineOffset = static_cast<int>(lua_tonumber(L, -1)); 85 config.lineOffset = static_cast<int>(lua_tonumber(L, -1));
86 } 86 }
87 lua_pop(L, 1); 87 lua_pop(L, 1);
88 lua_pushliteral(L, "module");
89 lua_gettable(L, -2);
90 if (lua_isstring(L, -1) != 0) {
91 config.module = lua_tostring(L, -1);
92 }
93 lua_pop(L, 1);
88 } 94 }
89 std::string s(input, size); 95 std::string s(input, size);
90 auto result = yue::YueCompiler(L, nullptr, sameModule).compile(s, config); 96 auto result = yue::YueCompiler(L, nullptr, sameModule).compile(s, config);
diff --git a/src/yuescript/yuescript.h b/src/yuescript/yuescript.h
index 4428fbe..eac95da 100644
--- a/src/yuescript/yuescript.h
+++ b/src/yuescript/yuescript.h
@@ -103,6 +103,7 @@ end
103yue_loadstring = function(...) 103yue_loadstring = function(...)
104 local options, str, chunk_name, mode, env = get_options(...) 104 local options, str, chunk_name, mode, env = get_options(...)
105 chunk_name = chunk_name or "=(yuescript.loadstring)" 105 chunk_name = chunk_name or "=(yuescript.loadstring)"
106 options.module = chunk_name
106 local code, err = yue.to_lua(str, options) 107 local code, err = yue.to_lua(str, options)
107 if not code then 108 if not code then
108 return nil, err 109 return nil, err
@@ -117,7 +118,7 @@ yue_loadstring = function(...)
117end 118end
118local function yue_loadfile(fname, ...) 119local function yue_loadfile(fname, ...)
119 local text = yue.read_file(fname) 120 local text = yue.read_file(fname)
120 return yue_loadstring(text, tostring(fname), ...) 121 return yue_loadstring(text, fname, ...)
121end 122end
122local function yue_dofile(...) 123local function yue_dofile(...)
123 local f = assert(yue_loadfile(...)) 124 local f = assert(yue_loadfile(...))