diff options
author | Li Jin <dragon-fly@qq.com> | 2023-03-23 09:50:56 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2023-03-23 09:51:15 +0800 |
commit | f52f54f953feb6bb36a279c42882d7a744695271 (patch) | |
tree | e71f1df9ff282adf01938b652ce35894d463ce9d | |
parent | a359ad7a16966c8955ec29e287b78d6a71dd0030 (diff) | |
download | yuescript-f52f54f953feb6bb36a279c42882d7a744695271.tar.gz yuescript-f52f54f953feb6bb36a279c42882d7a744695271.tar.bz2 yuescript-f52f54f953feb6bb36a279c42882d7a744695271.zip |
add yue.check function.
-rw-r--r-- | src/yuescript/stacktraceplus.h | 2 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 405 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.h | 22 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 63 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 46 | ||||
-rw-r--r-- | src/yuescript/yuescript.cpp | 151 | ||||
-rw-r--r-- | src/yuescript/yuescript.h | 7 |
7 files changed, 423 insertions, 273 deletions
diff --git a/src/yuescript/stacktraceplus.h b/src/yuescript/stacktraceplus.h index 83460ef..4b6f370 100644 --- a/src/yuescript/stacktraceplus.h +++ b/src/yuescript/stacktraceplus.h | |||
@@ -345,7 +345,7 @@ local function getYueLineNumber(fname, line) | |||
345 | if source then | 345 | if source then |
346 | local current, target = 1, tonumber(line) | 346 | local current, target = 1, tonumber(line) |
347 | local findLine = line | 347 | local findLine = line |
348 | for lineCode in source:gmatch("([^\n]*)\n") do | 348 | for lineCode in source:gmatch("[^\n\r]*") do |
349 | local num = lineCode:match("--%s*(%d+)%s*$") | 349 | local num = lineCode:match("--%s*(%d+)%s*$") |
350 | if num then | 350 | if num then |
351 | findLine = num | 351 | findLine = num |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 3a9e584..07c0e70 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -52,13 +52,12 @@ namespace yue { | |||
52 | 52 | ||
53 | #define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { code; }) | 53 | #define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { code; }) |
54 | #define DEFER(code) _DEFER(code, __LINE__) | 54 | #define DEFER(code) _DEFER(code, __LINE__) |
55 | #define YUEE(msg, node) throw std::logic_error( \ | 55 | #define YUEE(msg, node) throw CompileError( \ |
56 | _info.errorMessage( \ | 56 | "[File] "s + __FILE__ \ |
57 | "[File] "s + __FILE__ \ | 57 | + ",\n[Func] "s + __FUNCTION__ \ |
58 | + ",\n[Func] "s + __FUNCTION__ \ | 58 | + ",\n[Line] "s + std::to_string(__LINE__) \ |
59 | + ",\n[Line] "s + std::to_string(__LINE__) \ | 59 | + ",\n[Error] "s + msg, \ |
60 | + ",\n[Error] "s + msg, \ | 60 | node) |
61 | node)) | ||
62 | 61 | ||
63 | typedef std::list<std::string> str_list; | 62 | typedef std::list<std::string> str_list; |
64 | 63 | ||
@@ -73,9 +72,51 @@ static std::unordered_set<std::string> Metamethods = { | |||
73 | "close"s // Lua 5.4 | 72 | "close"s // Lua 5.4 |
74 | }; | 73 | }; |
75 | 74 | ||
76 | const std::string_view version = "0.15.28"sv; | 75 | const std::string_view version = "0.15.29"sv; |
77 | const std::string_view extension = "yue"sv; | 76 | const std::string_view extension = "yue"sv; |
78 | 77 | ||
78 | class CompileError : public std::logic_error { | ||
79 | public: | ||
80 | explicit CompileError(std::string_view msg, const input_range* range) | ||
81 | : std::logic_error(std::string(msg)) | ||
82 | , line(range->m_begin.m_line) | ||
83 | , col(range->m_begin.m_col) { } | ||
84 | |||
85 | int line; | ||
86 | int col; | ||
87 | }; | ||
88 | |||
89 | CompileInfo::CompileInfo( | ||
90 | std::string&& codes, | ||
91 | std::optional<Error>&& error, | ||
92 | std::unique_ptr<GlobalVars>&& globals, | ||
93 | std::unique_ptr<Options>&& options, | ||
94 | double parseTime, | ||
95 | double compileTime) | ||
96 | : codes(std::move(codes)) | ||
97 | , error(std::move(error)) | ||
98 | , globals(std::move(globals)) | ||
99 | , options(std::move(options)) | ||
100 | , parseTime(parseTime) | ||
101 | , compileTime(compileTime) { } | ||
102 | |||
103 | CompileInfo::CompileInfo(CompileInfo&& other) | ||
104 | : codes(std::move(other.codes)) | ||
105 | , error(std::move(other.error)) | ||
106 | , globals(std::move(other.globals)) | ||
107 | , options(std::move(other.options)) | ||
108 | , parseTime(other.parseTime) | ||
109 | , compileTime(other.compileTime) { } | ||
110 | |||
111 | void CompileInfo::operator=(CompileInfo&& other) { | ||
112 | codes = std::move(other.codes); | ||
113 | error = std::move(other.error); | ||
114 | globals = std::move(other.globals); | ||
115 | options = std::move(other.options); | ||
116 | parseTime = other.parseTime; | ||
117 | compileTime = other.compileTime; | ||
118 | } | ||
119 | |||
79 | class YueCompilerImpl { | 120 | class YueCompilerImpl { |
80 | public: | 121 | public: |
81 | #ifndef YUE_NO_MACRO | 122 | #ifndef YUE_NO_MACRO |
@@ -162,7 +203,7 @@ public: | |||
162 | if (exportNode->target.is<Macro_t>()) break; | 203 | if (exportNode->target.is<Macro_t>()) break; |
163 | } | 204 | } |
164 | default: | 205 | default: |
165 | throw std::logic_error(_info.errorMessage("macro exporting module only accepts macro definition, macro importing and macro expansion in place", stmt)); | 206 | throw CompileError("macro exporting module only accepts macro definition, macro importing and macro expansion in place"sv, stmt); |
166 | break; | 207 | break; |
167 | } | 208 | } |
168 | } | 209 | } |
@@ -200,7 +241,7 @@ public: | |||
200 | noLabel = false; | 241 | noLabel = false; |
201 | BLOCK_END | 242 | BLOCK_END |
202 | if (noLabel) { | 243 | if (noLabel) { |
203 | throw std::logic_error(_info.errorMessage("no visible label '"s + gotoNode.label + "' for <goto>"s, gotoNode.ptr->label)); | 244 | throw CompileError("no visible label '"s + gotoNode.label + "' for <goto>"s, gotoNode.ptr->label); |
204 | } | 245 | } |
205 | } | 246 | } |
206 | } | 247 | } |
@@ -241,12 +282,42 @@ public: | |||
241 | } | 282 | } |
242 | } | 283 | } |
243 | #endif // YUE_NO_MACRO | 284 | #endif // YUE_NO_MACRO |
244 | return {std::move(out.back()), Empty, std::move(globals), std::move(options), parseTime, compileTime}; | 285 | return {std::move(out.back()), std::nullopt, std::move(globals), std::move(options), parseTime, compileTime}; |
245 | } catch (const std::logic_error& error) { | 286 | } catch (const CompileError& error) { |
246 | return {Empty, error.what(), std::move(globals), std::move(options), parseTime, compileTime}; | 287 | auto displayMessage = _info.errorMessage(error.what(), error.line, error.col); |
288 | return { | ||
289 | std::string(), | ||
290 | CompileInfo::Error{ | ||
291 | error.what(), | ||
292 | error.line, error.col, | ||
293 | displayMessage}, | ||
294 | std::move(globals), | ||
295 | std::move(options), | ||
296 | parseTime, compileTime}; | ||
247 | } | 297 | } |
248 | } else { | 298 | } else { |
249 | return {Empty, std::move(_info.error), std::move(globals), std::move(options), parseTime, compileTime}; | 299 | const auto& error = _info.error.value(); |
300 | if (!_info.codes) { | ||
301 | return { | ||
302 | std::string(), | ||
303 | CompileInfo::Error{ | ||
304 | error.msg, | ||
305 | error.line, error.col, | ||
306 | ""}, | ||
307 | std::move(globals), | ||
308 | std::move(options), | ||
309 | parseTime, compileTime}; | ||
310 | } | ||
311 | auto displayMessage = _info.errorMessage(error.msg, error.line, error.col); | ||
312 | return { | ||
313 | std::string(), | ||
314 | CompileInfo::Error{ | ||
315 | error.msg, | ||
316 | error.line, error.col, | ||
317 | displayMessage}, | ||
318 | std::move(globals), | ||
319 | std::move(options), | ||
320 | parseTime, compileTime}; | ||
250 | } | 321 | } |
251 | } | 322 | } |
252 | 323 | ||
@@ -483,7 +554,7 @@ private: | |||
483 | 554 | ||
484 | void checkConst(const std::string& name, ast_node* x) const { | 555 | void checkConst(const std::string& name, ast_node* x) const { |
485 | if (isConst(name)) { | 556 | if (isConst(name)) { |
486 | throw std::logic_error(_info.errorMessage("attempt to assign to const variable '"s + name + '\'', x)); | 557 | throw CompileError("attempt to assign to const variable '"s + name + '\'', x); |
487 | } | 558 | } |
488 | } | 559 | } |
489 | 560 | ||
@@ -503,7 +574,7 @@ private: | |||
503 | } | 574 | } |
504 | 575 | ||
505 | void addGlobalVar(const std::string& name, ast_node* x) { | 576 | void addGlobalVar(const std::string& name, ast_node* x) { |
506 | if (isLocal(name)) throw std::logic_error(_info.errorMessage("can not declare a local variable to be global"sv, x)); | 577 | if (isLocal(name)) throw CompileError("can not declare a local variable to be global"sv, x); |
507 | auto& scope = _scopes.back(); | 578 | auto& scope = _scopes.back(); |
508 | if (!scope.globals) { | 579 | if (!scope.globals) { |
509 | scope.globals = std::make_unique<std::unordered_set<std::string>>(); | 580 | scope.globals = std::make_unique<std::unordered_set<std::string>>(); |
@@ -1051,7 +1122,7 @@ private: | |||
1051 | for (auto exp_ : expList->exprs.objects()) { | 1122 | for (auto exp_ : expList->exprs.objects()) { |
1052 | Exp_t* exp = static_cast<Exp_t*>(exp_); | 1123 | Exp_t* exp = static_cast<Exp_t*>(exp_); |
1053 | if (!isAssignable(exp)) { | 1124 | if (!isAssignable(exp)) { |
1054 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, exp)); | 1125 | throw CompileError("left hand expression is not assignable"sv, exp); |
1055 | } | 1126 | } |
1056 | } | 1127 | } |
1057 | } | 1128 | } |
@@ -1120,7 +1191,7 @@ private: | |||
1120 | 1191 | ||
1121 | void checkMetamethod(const std::string& name, ast_node* x) { | 1192 | void checkMetamethod(const std::string& name, ast_node* x) { |
1122 | if (Metamethods.find(name) == Metamethods.end()) { | 1193 | if (Metamethods.find(name) == Metamethods.end()) { |
1123 | throw std::logic_error(_info.errorMessage("invalid metamethod name"sv, x)); | 1194 | throw CompileError("invalid metamethod name"sv, x); |
1124 | } | 1195 | } |
1125 | int target = getLuaTarget(x); | 1196 | int target = getLuaTarget(x); |
1126 | switch (target) { | 1197 | switch (target) { |
@@ -1128,33 +1199,30 @@ private: | |||
1128 | case 502: goto metamethod52; | 1199 | case 502: goto metamethod52; |
1129 | case 503: { | 1200 | case 503: { |
1130 | if (name == "ipairs"sv) { | 1201 | if (name == "ipairs"sv) { |
1131 | throw std::logic_error(_info.errorMessage("metamethod is deprecated since Lua 5.3"sv, x)); | 1202 | throw CompileError("metamethod is deprecated since Lua 5.3"sv, x); |
1132 | } | 1203 | } |
1133 | goto metamethod53; | 1204 | goto metamethod53; |
1134 | } | 1205 | } |
1135 | case 504: { | 1206 | case 504: { |
1136 | if (name == "ipairs"sv) { | 1207 | if (name == "ipairs"sv) { |
1137 | throw std::logic_error(_info.errorMessage("metamethod is not supported since Lua 5.4"sv, x)); | 1208 | throw CompileError("metamethod is not supported since Lua 5.4"sv, x); |
1138 | } | 1209 | } |
1139 | goto metamethod54; | 1210 | goto metamethod54; |
1140 | } | 1211 | } |
1141 | } | 1212 | } |
1142 | metamethod51: | 1213 | metamethod51: |
1143 | if (name == "pairs"sv || name == "ipairs"sv) { | 1214 | if (name == "pairs"sv || name == "ipairs"sv) { |
1144 | throw std::logic_error(_info.errorMessage("metamethod is not supported until Lua 5.2"sv, x)); | 1215 | throw CompileError("metamethod is not supported until Lua 5.2"sv, x); |
1145 | } | 1216 | } |
1146 | metamethod52: | 1217 | metamethod52: |
1147 | if (name == "name"sv || name == "idiv"sv || | 1218 | if (name == "name"sv || name == "idiv"sv || name == "band"sv || name == "bor"sv || name == "bxor"sv || name == "bnot"sv || name == "shl"sv || name == "shr"sv) { |
1148 | name == "band"sv || name == "bor"sv || | 1219 | throw CompileError("metamethod is not supported until Lua 5.3"sv, x); |
1149 | name == "bxor"sv || name == "bnot"sv || | ||
1150 | name == "shl"sv || name == "shr"sv) { | ||
1151 | throw std::logic_error(_info.errorMessage("metamethod is not supported until Lua 5.3"sv, x)); | ||
1152 | } | 1220 | } |
1153 | metamethod53: | 1221 | metamethod53: |
1154 | if (name == "close"sv) { | 1222 | if (name == "close"sv) { |
1155 | throw std::logic_error(_info.errorMessage("metamethod is not supported until Lua 5.4"sv, x)); | 1223 | throw CompileError("metamethod is not supported until Lua 5.4"sv, x); |
1156 | } | 1224 | } |
1157 | metamethod54: | 1225 | metamethod54: |
1158 | return; | 1226 | return; |
1159 | } | 1227 | } |
1160 | 1228 | ||
@@ -1236,11 +1304,11 @@ private: | |||
1236 | return; | 1304 | return; |
1237 | } | 1305 | } |
1238 | case id<WhileLine_t>(): { | 1306 | case id<WhileLine_t>(): { |
1239 | throw std::logic_error(_info.errorMessage("while-loop line decorator is not supported here"sv, appendix->item.get())); | 1307 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); |
1240 | break; | 1308 | break; |
1241 | } | 1309 | } |
1242 | case id<CompInner_t>(): { | 1310 | case id<CompInner_t>(): { |
1243 | throw std::logic_error(_info.errorMessage("for-loop line decorator is not supported here"sv, appendix->item.get())); | 1311 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); |
1244 | break; | 1312 | break; |
1245 | } | 1313 | } |
1246 | default: YUEE("AST node mismatch", appendix->item.get()); break; | 1314 | default: YUEE("AST node mismatch", appendix->item.get()); break; |
@@ -1249,10 +1317,10 @@ private: | |||
1249 | auto appendix = statement->appendix->item.get(); | 1317 | auto appendix = statement->appendix->item.get(); |
1250 | switch (statement->content->getId()) { | 1318 | switch (statement->content->getId()) { |
1251 | case id<Return_t>(): | 1319 | case id<Return_t>(): |
1252 | throw std::logic_error(_info.errorMessage("loop line decorator can not be used in a return statement"sv, appendix)); | 1320 | throw CompileError("loop line decorator can not be used in a return statement"sv, appendix); |
1253 | break; | 1321 | break; |
1254 | case id<BreakLoop_t>(): | 1322 | case id<BreakLoop_t>(): |
1255 | throw std::logic_error(_info.errorMessage("loop line decorator can not be used in a break-loop statement"sv, appendix)); | 1323 | throw CompileError("loop line decorator can not be used in a break-loop statement"sv, appendix); |
1256 | break; | 1324 | break; |
1257 | } | 1325 | } |
1258 | } | 1326 | } |
@@ -1343,7 +1411,7 @@ private: | |||
1343 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; | 1411 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; |
1344 | case id<ShortTabAppending_t>(): transformShortTabAppending(static_cast<ShortTabAppending_t*>(content), out); break; | 1412 | case id<ShortTabAppending_t>(): transformShortTabAppending(static_cast<ShortTabAppending_t*>(content), out); break; |
1345 | case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; | 1413 | case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; |
1346 | case id<PipeBody_t>(): throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x)); break; | 1414 | case id<PipeBody_t>(): throw CompileError("pipe chain must be following a value"sv, x); break; |
1347 | case id<ExpListAssign_t>(): { | 1415 | case id<ExpListAssign_t>(): { |
1348 | auto expListAssign = static_cast<ExpListAssign_t*>(content); | 1416 | auto expListAssign = static_cast<ExpListAssign_t*>(content); |
1349 | if (expListAssign->action) { | 1417 | if (expListAssign->action) { |
@@ -1388,7 +1456,7 @@ private: | |||
1388 | break; | 1456 | break; |
1389 | } | 1457 | } |
1390 | } | 1458 | } |
1391 | throw std::logic_error(_info.errorMessage("unexpected expression"sv, expList)); | 1459 | throw CompileError("unexpected expression"sv, expList); |
1392 | } | 1460 | } |
1393 | break; | 1461 | break; |
1394 | } | 1462 | } |
@@ -1478,7 +1546,7 @@ private: | |||
1478 | BLOCK_END | 1546 | BLOCK_END |
1479 | } | 1547 | } |
1480 | } else { | 1548 | } else { |
1481 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, exp)); | 1549 | throw CompileError("left hand expression is not assignable"sv, exp); |
1482 | } | 1550 | } |
1483 | } | 1551 | } |
1484 | return defs; | 1552 | return defs; |
@@ -1558,7 +1626,7 @@ private: | |||
1558 | for (auto& destruct : info.destructures) { | 1626 | for (auto& destruct : info.destructures) { |
1559 | for (auto& item : destruct.items) { | 1627 | for (auto& item : destruct.items) { |
1560 | if (item.targetVar.empty()) { | 1628 | if (item.targetVar.empty()) { |
1561 | throw std::logic_error(_info.errorMessage("can only declare variable as const"sv, item.target)); | 1629 | throw CompileError("can only declare variable as const"sv, item.target); |
1562 | } | 1630 | } |
1563 | markVarConst(item.targetVar); | 1631 | markVarConst(item.targetVar); |
1564 | } | 1632 | } |
@@ -1580,7 +1648,7 @@ private: | |||
1580 | } else { | 1648 | } else { |
1581 | _buf << "only one right value expected, got "sv << values.size(); | 1649 | _buf << "only one right value expected, got "sv << values.size(); |
1582 | } | 1650 | } |
1583 | throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); | 1651 | throw CompileError(clearBuf(), values.front()); |
1584 | } | 1652 | } |
1585 | bool checkValuesLater = false; | 1653 | bool checkValuesLater = false; |
1586 | if (exprs.size() > values.size()) { | 1654 | if (exprs.size() > values.size()) { |
@@ -1595,7 +1663,7 @@ private: | |||
1595 | auto value = singleValueFrom(values.back()); | 1663 | auto value = singleValueFrom(values.back()); |
1596 | if (!value) { | 1664 | if (!value) { |
1597 | _buf << exprs.size() << " right values expected, got "sv << values.size(); | 1665 | _buf << exprs.size() << " right values expected, got "sv << values.size(); |
1598 | throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); | 1666 | throw CompileError(clearBuf(), values.front()); |
1599 | } | 1667 | } |
1600 | if (auto val = value->item.as<SimpleValue_t>()) { | 1668 | if (auto val = value->item.as<SimpleValue_t>()) { |
1601 | switch (val->value->getId()) { | 1669 | switch (val->value->getId()) { |
@@ -1611,7 +1679,7 @@ private: | |||
1611 | auto chainValue = value->item.as<ChainValue_t>(); | 1679 | auto chainValue = value->item.as<ChainValue_t>(); |
1612 | if (!chainValue || !ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) { | 1680 | if (!chainValue || !ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) { |
1613 | _buf << exprs.size() << " right values expected, got "sv << values.size(); | 1681 | _buf << exprs.size() << " right values expected, got "sv << values.size(); |
1614 | throw std::logic_error(_info.errorMessage(clearBuf(), values.front())); | 1682 | throw CompileError(clearBuf(), values.front()); |
1615 | } | 1683 | } |
1616 | auto newAssign = assign->new_ptr<Assign_t>(); | 1684 | auto newAssign = assign->new_ptr<Assign_t>(); |
1617 | newAssign->values.dup(assign->values); | 1685 | newAssign->values.dup(assign->values); |
@@ -1695,7 +1763,7 @@ private: | |||
1695 | tmpChain->items.pop_back(); | 1763 | tmpChain->items.pop_back(); |
1696 | if (tmpChain->items.empty()) { | 1764 | if (tmpChain->items.empty()) { |
1697 | if (_withVars.empty()) { | 1765 | if (_withVars.empty()) { |
1698 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); | 1766 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); |
1699 | } else { | 1767 | } else { |
1700 | args.push_back(_withVars.top()); | 1768 | args.push_back(_withVars.top()); |
1701 | } | 1769 | } |
@@ -1703,7 +1771,7 @@ private: | |||
1703 | transformExp(newExp(tmpChain, tmpChain), args, ExpUsage::Closure); | 1771 | transformExp(newExp(tmpChain, tmpChain), args, ExpUsage::Closure); |
1704 | } | 1772 | } |
1705 | if (vit == values.end()) { | 1773 | if (vit == values.end()) { |
1706 | throw std::logic_error(_info.errorMessage("right value missing"sv, values.front())); | 1774 | throw CompileError("right value missing"sv, values.front()); |
1707 | } | 1775 | } |
1708 | transformAssignItem(*vit, args); | 1776 | transformAssignItem(*vit, args); |
1709 | _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); | 1777 | _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); |
@@ -1714,7 +1782,7 @@ private: | |||
1714 | tmpChain->items.pop_back(); | 1782 | tmpChain->items.pop_back(); |
1715 | if (tmpChain->items.empty()) { | 1783 | if (tmpChain->items.empty()) { |
1716 | if (_withVars.empty()) { | 1784 | if (_withVars.empty()) { |
1717 | throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x)); | 1785 | throw CompileError("short table appending must be called within a with block"sv, x); |
1718 | } else { | 1786 | } else { |
1719 | tmpChain->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue)); | 1787 | tmpChain->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue)); |
1720 | } | 1788 | } |
@@ -1738,7 +1806,7 @@ private: | |||
1738 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | 1806 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); |
1739 | auto assign = x->new_ptr<Assign_t>(); | 1807 | auto assign = x->new_ptr<Assign_t>(); |
1740 | if (vit == values.end()) { | 1808 | if (vit == values.end()) { |
1741 | throw std::logic_error(_info.errorMessage("right value missing"sv, values.front())); | 1809 | throw CompileError("right value missing"sv, values.front()); |
1742 | } | 1810 | } |
1743 | assign->values.push_back(*vit); | 1811 | assign->values.push_back(*vit); |
1744 | newAssignment->action.set(assign); | 1812 | newAssignment->action.set(assign); |
@@ -2176,7 +2244,7 @@ private: | |||
2176 | switch (node->getId()) { | 2244 | switch (node->getId()) { |
2177 | case id<Exp_t>(): { | 2245 | case id<Exp_t>(): { |
2178 | auto item = singleValueFrom(node)->item.get(); | 2246 | auto item = singleValueFrom(node)->item.get(); |
2179 | if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); | 2247 | if (!item) throw CompileError("invalid destructure value"sv, node); |
2180 | auto tbA = item->getByPath<TableLit_t>(); | 2248 | auto tbA = item->getByPath<TableLit_t>(); |
2181 | if (tbA) { | 2249 | if (tbA) { |
2182 | tableItems = &tbA->values.objects(); | 2250 | tableItems = &tbA->values.objects(); |
@@ -2208,7 +2276,7 @@ private: | |||
2208 | } | 2276 | } |
2209 | default: YUEE("AST node mismatch", node); break; | 2277 | default: YUEE("AST node mismatch", node); break; |
2210 | } | 2278 | } |
2211 | if (!tableItems) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); | 2279 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); |
2212 | std::list<DestructItem> pairs; | 2280 | std::list<DestructItem> pairs; |
2213 | int index = 0; | 2281 | int index = 0; |
2214 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); | 2282 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); |
@@ -2223,7 +2291,7 @@ private: | |||
2223 | } | 2291 | } |
2224 | ++index; | 2292 | ++index; |
2225 | if (!isAssignable(static_cast<Exp_t*>(pair))) { | 2293 | if (!isAssignable(static_cast<Exp_t*>(pair))) { |
2226 | throw std::logic_error(_info.errorMessage("can't destructure value"sv, pair)); | 2294 | throw CompileError("can't destructure value"sv, pair); |
2227 | } | 2295 | } |
2228 | auto value = singleValueFrom(pair); | 2296 | auto value = singleValueFrom(pair); |
2229 | auto item = value->item.get(); | 2297 | auto item = value->item.get(); |
@@ -2231,7 +2299,7 @@ private: | |||
2231 | auto subPairs = destructFromExp(pair, optional); | 2299 | auto subPairs = destructFromExp(pair, optional); |
2232 | if (!subPairs.empty()) { | 2300 | if (!subPairs.empty()) { |
2233 | if (defVal) { | 2301 | if (defVal) { |
2234 | throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); | 2302 | throw CompileError("default value is not supported here"sv, defVal); |
2235 | } | 2303 | } |
2236 | } | 2304 | } |
2237 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); | 2305 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); |
@@ -2298,17 +2366,17 @@ private: | |||
2298 | } else if (auto key = np->key.as<String_t>()) { | 2366 | } else if (auto key = np->key.as<String_t>()) { |
2299 | keyIndex = newExp(key, np->key).get(); | 2367 | keyIndex = newExp(key, np->key).get(); |
2300 | } else { | 2368 | } else { |
2301 | throw std::logic_error(_info.errorMessage("unsupported key for destructuring"sv, np)); | 2369 | throw CompileError("unsupported key for destructuring"sv, np); |
2302 | } | 2370 | } |
2303 | } | 2371 | } |
2304 | if (auto exp = np->value.as<Exp_t>()) { | 2372 | if (auto exp = np->value.as<Exp_t>()) { |
2305 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't do destructure value"sv, exp)); | 2373 | if (!isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); |
2306 | auto item = singleValueFrom(exp)->item.get(); | 2374 | auto item = singleValueFrom(exp)->item.get(); |
2307 | if (ast_is<SimpleTable_t>(item) || item->getByPath<TableLit_t>()) { | 2375 | if (ast_is<SimpleTable_t>(item) || item->getByPath<TableLit_t>()) { |
2308 | auto subPairs = destructFromExp(exp, optional); | 2376 | auto subPairs = destructFromExp(exp, optional); |
2309 | if (!subPairs.empty()) { | 2377 | if (!subPairs.empty()) { |
2310 | if (defVal) { | 2378 | if (defVal) { |
2311 | throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); | 2379 | throw CompileError("default value is not supported here"sv, defVal); |
2312 | } | 2380 | } |
2313 | } | 2381 | } |
2314 | for (auto& p : subPairs) { | 2382 | for (auto& p : subPairs) { |
@@ -2333,7 +2401,7 @@ private: | |||
2333 | auto subPairs = destructFromExp(np->value, optional); | 2401 | auto subPairs = destructFromExp(np->value, optional); |
2334 | if (!subPairs.empty()) { | 2402 | if (!subPairs.empty()) { |
2335 | if (defVal) { | 2403 | if (defVal) { |
2336 | throw std::logic_error(_info.errorMessage("default value is not supported here"sv, defVal)); | 2404 | throw CompileError("default value is not supported here"sv, defVal); |
2337 | } | 2405 | } |
2338 | } | 2406 | } |
2339 | for (auto& p : subPairs) { | 2407 | for (auto& p : subPairs) { |
@@ -2461,13 +2529,13 @@ private: | |||
2461 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 2529 | if (auto ssVal = simpleSingleValueFrom(*j)) { |
2462 | switch (ssVal->value->getId()) { | 2530 | switch (ssVal->value->getId()) { |
2463 | case id<ConstValue_t>(): | 2531 | case id<ConstValue_t>(): |
2464 | throw std::logic_error(_info.errorMessage("can not destructure a constant"sv, ssVal->value)); | 2532 | throw CompileError("can not destructure a constant"sv, ssVal->value); |
2465 | break; | 2533 | break; |
2466 | case id<Num_t>(): | 2534 | case id<Num_t>(): |
2467 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); | 2535 | throw CompileError("can not destructure a number"sv, ssVal->value); |
2468 | break; | 2536 | break; |
2469 | case id<FunLit_t>(): | 2537 | case id<FunLit_t>(): |
2470 | throw std::logic_error(_info.errorMessage("can not destructure a function"sv, ssVal->value)); | 2538 | throw CompileError("can not destructure a function"sv, ssVal->value); |
2471 | break; | 2539 | break; |
2472 | } | 2540 | } |
2473 | } | 2541 | } |
@@ -2613,7 +2681,7 @@ private: | |||
2613 | simpleValue->value.set(tab); | 2681 | simpleValue->value.set(tab); |
2614 | auto pairs = destructFromExp(newExp(simpleValue, expr), optional); | 2682 | auto pairs = destructFromExp(newExp(simpleValue, expr), optional); |
2615 | if (pairs.empty()) { | 2683 | if (pairs.empty()) { |
2616 | throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); | 2684 | throw CompileError("expect items to be destructured"sv, tab); |
2617 | } | 2685 | } |
2618 | destruct.items = std::move(pairs); | 2686 | destruct.items = std::move(pairs); |
2619 | if (!varDefOnly) { | 2687 | if (!varDefOnly) { |
@@ -2715,17 +2783,17 @@ private: | |||
2715 | auto action = assignment->action.get(); | 2783 | auto action = assignment->action.get(); |
2716 | switch (action->getId()) { | 2784 | switch (action->getId()) { |
2717 | case id<Update_t>(): { | 2785 | case id<Update_t>(): { |
2718 | if (expList->exprs.size() > 1) throw std::logic_error(_info.errorMessage("can not apply update to multiple values"sv, expList)); | 2786 | if (expList->exprs.size() > 1) throw CompileError("can not apply update to multiple values"sv, expList); |
2719 | auto update = static_cast<Update_t*>(action); | 2787 | auto update = static_cast<Update_t*>(action); |
2720 | auto leftExp = static_cast<Exp_t*>(expList->exprs.objects().front()); | 2788 | auto leftExp = static_cast<Exp_t*>(expList->exprs.objects().front()); |
2721 | auto leftValue = singleValueFrom(leftExp); | 2789 | auto leftValue = singleValueFrom(leftExp); |
2722 | if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); | 2790 | if (!leftValue) throw CompileError("left hand expression is not assignable"sv, leftExp); |
2723 | auto chain = leftValue->item.as<ChainValue_t>(); | 2791 | auto chain = leftValue->item.as<ChainValue_t>(); |
2724 | if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftValue)); | 2792 | if (!chain) throw CompileError("left hand expression is not assignable"sv, leftValue); |
2725 | BLOCK_START { | 2793 | BLOCK_START { |
2726 | auto dot = ast_cast<DotChainItem_t>(chain->items.back()); | 2794 | auto dot = ast_cast<DotChainItem_t>(chain->items.back()); |
2727 | if (dot && dot->name.is<Metatable_t>()) { | 2795 | if (dot && dot->name.is<Metatable_t>()) { |
2728 | throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); | 2796 | throw CompileError("can not apply update to a metatable"sv, leftExp); |
2729 | } | 2797 | } |
2730 | BREAK_IF(chain->items.size() < 2); | 2798 | BREAK_IF(chain->items.size() < 2); |
2731 | if (chain->items.size() == 2) { | 2799 | if (chain->items.size() == 2) { |
@@ -3060,9 +3128,9 @@ private: | |||
3060 | auto unary = static_cast<UnaryExp_t*>(*it); | 3128 | auto unary = static_cast<UnaryExp_t*>(*it); |
3061 | auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); | 3129 | auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); |
3062 | if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { | 3130 | if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { |
3063 | throw std::logic_error(_info.errorMessage("unexpected expression"sv, x)); | 3131 | throw CompileError("unexpected expression"sv, x); |
3064 | } | 3132 | } |
3065 | if (!value) throw std::logic_error(_info.errorMessage("pipe operator must be followed by chain value"sv, *it)); | 3133 | if (!value) throw CompileError("pipe operator must be followed by chain value"sv, *it); |
3066 | if (auto chainValue = value->item.as<ChainValue_t>()) { | 3134 | if (auto chainValue = value->item.as<ChainValue_t>()) { |
3067 | if (isChainValueCall(chainValue)) { | 3135 | if (isChainValueCall(chainValue)) { |
3068 | auto last = chainValue->items.back(); | 3136 | auto last = chainValue->items.back(); |
@@ -3080,7 +3148,7 @@ private: | |||
3080 | args->swap(a, arg); | 3148 | args->swap(a, arg); |
3081 | findPlaceHolder = true; | 3149 | findPlaceHolder = true; |
3082 | } else { | 3150 | } else { |
3083 | throw std::logic_error(_info.errorMessage("pipe placeholder can be used only in one place"sv, a)); | 3151 | throw CompileError("pipe placeholder can be used only in one place"sv, a); |
3084 | } | 3152 | } |
3085 | } | 3153 | } |
3086 | } | 3154 | } |
@@ -3094,7 +3162,7 @@ private: | |||
3094 | } | 3162 | } |
3095 | arg.set(newExp(unary, x)); | 3163 | arg.set(newExp(unary, x)); |
3096 | } else { | 3164 | } else { |
3097 | throw std::logic_error(_info.errorMessage("pipe operator must be followed by chain value"sv, value)); | 3165 | throw CompileError("pipe operator must be followed by chain value"sv, value); |
3098 | } | 3166 | } |
3099 | } | 3167 | } |
3100 | switch (usage) { | 3168 | switch (usage) { |
@@ -3428,7 +3496,7 @@ private: | |||
3428 | --last; | 3496 | --last; |
3429 | auto lst = static_cast<Statement_t*>(*last); | 3497 | auto lst = static_cast<Statement_t*>(*last); |
3430 | if (lst->appendix) { | 3498 | if (lst->appendix) { |
3431 | throw std::logic_error(_info.errorMessage("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get())); | 3499 | throw CompileError("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get()); |
3432 | } | 3500 | } |
3433 | lst->appendix.set(stmt->appendix); | 3501 | lst->appendix.set(stmt->appendix); |
3434 | stmt->appendix.set(nullptr); | 3502 | stmt->appendix.set(nullptr); |
@@ -3441,14 +3509,14 @@ private: | |||
3441 | } | 3509 | } |
3442 | cond = true; | 3510 | cond = true; |
3443 | BLOCK_END | 3511 | BLOCK_END |
3444 | if (!cond) throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x)); | 3512 | if (!cond) throw CompileError("pipe chain must be following a value"sv, x); |
3445 | stmt->content.set(nullptr); | 3513 | stmt->content.set(nullptr); |
3446 | auto next = it; | 3514 | auto next = it; |
3447 | ++next; | 3515 | ++next; |
3448 | BLOCK_START | 3516 | BLOCK_START |
3449 | BREAK_IF(next == nodes.end()); | 3517 | BREAK_IF(next == nodes.end()); |
3450 | BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<PipeBody_t>()); | 3518 | BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<PipeBody_t>()); |
3451 | throw std::logic_error(_info.errorMessage("indent mismatch in pipe chain"sv, *next)); | 3519 | throw CompileError("indent mismatch in pipe chain"sv, *next); |
3452 | BLOCK_END | 3520 | BLOCK_END |
3453 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { | 3521 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { |
3454 | auto x = *nodes.begin(); | 3522 | auto x = *nodes.begin(); |
@@ -3496,7 +3564,7 @@ private: | |||
3496 | args->swap(a, arg); | 3564 | args->swap(a, arg); |
3497 | findPlaceHolder = true; | 3565 | findPlaceHolder = true; |
3498 | } else { | 3566 | } else { |
3499 | throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place"sv, a)); | 3567 | throw CompileError("backcall placeholder can be used only in one place"sv, a); |
3500 | } | 3568 | } |
3501 | } | 3569 | } |
3502 | } | 3570 | } |
@@ -3663,15 +3731,15 @@ private: | |||
3663 | } | 3731 | } |
3664 | case ExpUsage::Assignment: { | 3732 | case ExpUsage::Assignment: { |
3665 | auto last = lastStatementFrom(block); | 3733 | auto last = lastStatementFrom(block); |
3666 | if (!last) throw std::logic_error(_info.errorMessage("block is not assignable"sv, block)); | 3734 | if (!last) throw CompileError("block is not assignable"sv, block); |
3667 | if (last->appendix) { | 3735 | if (last->appendix) { |
3668 | auto appendix = last->appendix->item.get(); | 3736 | auto appendix = last->appendix->item.get(); |
3669 | switch (appendix->getId()) { | 3737 | switch (appendix->getId()) { |
3670 | case id<WhileLine_t>(): | 3738 | case id<WhileLine_t>(): |
3671 | throw std::logic_error(_info.errorMessage("while-loop line decorator is not supported here"sv, appendix)); | 3739 | throw CompileError("while-loop line decorator is not supported here"sv, appendix); |
3672 | break; | 3740 | break; |
3673 | case id<CompFor_t>(): | 3741 | case id<CompFor_t>(): |
3674 | throw std::logic_error(_info.errorMessage("for-loop line decorator is not supported here"sv, appendix)); | 3742 | throw CompileError("for-loop line decorator is not supported here"sv, appendix); |
3675 | break; | 3743 | break; |
3676 | } | 3744 | } |
3677 | } | 3745 | } |
@@ -3697,7 +3765,7 @@ private: | |||
3697 | static_cast<Statement_t*>(*bLast)->needSep.set(nullptr); | 3765 | static_cast<Statement_t*>(*bLast)->needSep.set(nullptr); |
3698 | } | 3766 | } |
3699 | } else if (!last->content.is<BreakLoop_t>()) { | 3767 | } else if (!last->content.is<BreakLoop_t>()) { |
3700 | throw std::logic_error(_info.errorMessage("expecting assignable statement or break loop"sv, last)); | 3768 | throw CompileError("expecting assignable statement or break loop"sv, last); |
3701 | } | 3769 | } |
3702 | break; | 3770 | break; |
3703 | } | 3771 | } |
@@ -3750,7 +3818,7 @@ private: | |||
3750 | } else if (target.value() == "5.4"sv) { | 3818 | } else if (target.value() == "5.4"sv) { |
3751 | return 504; | 3819 | return 504; |
3752 | } else { | 3820 | } else { |
3753 | throw std::logic_error(_info.errorMessage("get invalid Lua target \""s + target.value() + "\", should be 5.1, 5.2, 5.3 or 5.4"s, x)); | 3821 | throw CompileError("get invalid Lua target \""s + target.value() + "\", should be 5.1, 5.2, 5.3 or 5.4"s, x); |
3754 | } | 3822 | } |
3755 | } | 3823 | } |
3756 | #ifndef YUE_NO_MACRO | 3824 | #ifndef YUE_NO_MACRO |
@@ -3865,7 +3933,7 @@ private: | |||
3865 | 3933 | ||
3866 | void transformMacro(Macro_t* macro, str_list& out, bool exporting) { | 3934 | void transformMacro(Macro_t* macro, str_list& out, bool exporting) { |
3867 | if (_scopes.size() > 1) { | 3935 | if (_scopes.size() > 1) { |
3868 | throw std::logic_error(_info.errorMessage("can not define macro outside the root block"sv, macro)); | 3936 | throw CompileError("can not define macro outside the root block"sv, macro); |
3869 | } | 3937 | } |
3870 | auto macroName = _parser.toString(macro->name); | 3938 | auto macroName = _parser.toString(macro->name); |
3871 | auto argsDef = macro->macroLit->argsDef.get(); | 3939 | auto argsDef = macro->macroLit->argsDef.get(); |
@@ -3874,7 +3942,7 @@ private: | |||
3874 | for (auto def_ : argsDef->definitions.objects()) { | 3942 | for (auto def_ : argsDef->definitions.objects()) { |
3875 | auto def = static_cast<FnArgDef_t*>(def_); | 3943 | auto def = static_cast<FnArgDef_t*>(def_); |
3876 | if (def->name.is<SelfItem_t>()) { | 3944 | if (def->name.is<SelfItem_t>()) { |
3877 | throw std::logic_error(_info.errorMessage("self name is not supported for macro function argument"sv, def->name)); | 3945 | throw CompileError("self name is not supported for macro function argument"sv, def->name); |
3878 | } else { | 3946 | } else { |
3879 | std::string defVal; | 3947 | std::string defVal; |
3880 | if (def->defaultValue) { | 3948 | if (def->defaultValue) { |
@@ -3904,22 +3972,22 @@ private: | |||
3904 | pushOptions(macro->m_begin.m_line - 1); // cur loadstring codes chunk options | 3972 | pushOptions(macro->m_begin.m_line - 1); // cur loadstring codes chunk options |
3905 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), cur f err | 3973 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), cur f err |
3906 | std::string err = lua_tostring(L, -1); | 3974 | std::string err = lua_tostring(L, -1); |
3907 | throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, macro->macroLit)); | 3975 | throw CompileError("failed to load macro codes\n"s + err, macro->macroLit); |
3908 | } // cur f err | 3976 | } // cur f err |
3909 | if (lua_isnil(L, -2) != 0) { // f == nil, cur f err | 3977 | if (lua_isnil(L, -2) != 0) { // f == nil, cur f err |
3910 | std::string err = lua_tostring(L, -1); | 3978 | std::string err = lua_tostring(L, -1); |
3911 | throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro "s + macroName + "): "s + err, macro->macroLit)); | 3979 | throw CompileError("failed to load macro codes, at (macro "s + macroName + "): "s + err, macro->macroLit); |
3912 | } | 3980 | } |
3913 | lua_pop(L, 1); // cur f | 3981 | lua_pop(L, 1); // cur f |
3914 | pushYue("pcall"sv); // cur f pcall | 3982 | pushYue("pcall"sv); // cur f pcall |
3915 | lua_insert(L, -2); // cur pcall f | 3983 | lua_insert(L, -2); // cur pcall f |
3916 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), cur success macro | 3984 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), cur success macro |
3917 | std::string err = lua_tostring(L, -1); | 3985 | std::string err = lua_tostring(L, -1); |
3918 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, macro->macroLit)); | 3986 | throw CompileError("failed to generate macro function\n"s + err, macro->macroLit); |
3919 | } // cur success res | 3987 | } // cur success res |
3920 | if (lua_toboolean(L, -2) == 0) { | 3988 | if (lua_toboolean(L, -2) == 0) { |
3921 | std::string err = lua_tostring(L, -1); | 3989 | std::string err = lua_tostring(L, -1); |
3922 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, macro->macroLit)); | 3990 | throw CompileError("failed to generate macro function\n"s + err, macro->macroLit); |
3923 | } // cur true macro | 3991 | } // cur true macro |
3924 | lua_remove(L, -2); // cur macro | 3992 | lua_remove(L, -2); // cur macro |
3925 | if (exporting && _config.exporting && !_config.module.empty()) { | 3993 | if (exporting && _config.exporting && !_config.module.empty()) { |
@@ -3936,7 +4004,7 @@ private: | |||
3936 | } | 4004 | } |
3937 | #else | 4005 | #else |
3938 | void transformMacro(Macro_t* macro, str_list&, bool) { | 4006 | void transformMacro(Macro_t* macro, str_list&, bool) { |
3939 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macro)); | 4007 | throw CompileError("macro feature not supported"sv, macro)); |
3940 | } | 4008 | } |
3941 | #endif // YUE_NO_MACRO | 4009 | #endif // YUE_NO_MACRO |
3942 | 4010 | ||
@@ -3944,7 +4012,7 @@ private: | |||
3944 | if (!_enableReturn.top()) { | 4012 | if (!_enableReturn.top()) { |
3945 | ast_node* target = returnNode->valueList.get(); | 4013 | ast_node* target = returnNode->valueList.get(); |
3946 | if (!target) target = returnNode; | 4014 | if (!target) target = returnNode; |
3947 | throw std::logic_error(_info.errorMessage("can not mix use of return and export statements in module scope"sv, target)); | 4015 | throw CompileError("can not mix use of return and export statements in module scope"sv, target); |
3948 | } | 4016 | } |
3949 | if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { | 4017 | if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { |
3950 | if (valueList->exprs.size() == 1) { | 4018 | if (valueList->exprs.size() == 1) { |
@@ -4067,7 +4135,7 @@ private: | |||
4067 | assignSelf = true; | 4135 | assignSelf = true; |
4068 | if (def->op) { | 4136 | if (def->op) { |
4069 | if (def->defaultValue) { | 4137 | if (def->defaultValue) { |
4070 | throw std::logic_error(_info.errorMessage("argument with default value should not check for existence"sv, def->op)); | 4138 | throw CompileError("argument with default value should not check for existence"sv, def->op); |
4071 | } | 4139 | } |
4072 | arg.checkExistence = true; | 4140 | arg.checkExistence = true; |
4073 | } | 4141 | } |
@@ -4087,10 +4155,10 @@ private: | |||
4087 | } | 4155 | } |
4088 | case id<Self_t>(): | 4156 | case id<Self_t>(): |
4089 | arg.name = "self"sv; | 4157 | arg.name = "self"sv; |
4090 | if (def->op) throw std::logic_error(_info.errorMessage("can only check existence for assigning self field"sv, selfName->name)); | 4158 | if (def->op) throw CompileError("can only check existence for assigning self field"sv, selfName->name); |
4091 | break; | 4159 | break; |
4092 | default: | 4160 | default: |
4093 | throw std::logic_error(_info.errorMessage("invald self expression here"sv, selfName->name)); | 4161 | throw CompileError("invald self expression here"sv, selfName->name); |
4094 | break; | 4162 | break; |
4095 | } | 4163 | } |
4096 | break; | 4164 | break; |
@@ -4296,7 +4364,7 @@ private: | |||
4296 | chainValue->items.pop_back(); | 4364 | chainValue->items.pop_back(); |
4297 | if (chainValue->items.empty()) { | 4365 | if (chainValue->items.empty()) { |
4298 | if (_withVars.empty()) { | 4366 | if (_withVars.empty()) { |
4299 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); | 4367 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); |
4300 | } | 4368 | } |
4301 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 4369 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); |
4302 | } | 4370 | } |
@@ -4434,7 +4502,7 @@ private: | |||
4434 | case id<ColonChainItem_t>(): | 4502 | case id<ColonChainItem_t>(): |
4435 | case id<Exp_t>(): | 4503 | case id<Exp_t>(): |
4436 | if (_withVars.empty()) { | 4504 | if (_withVars.empty()) { |
4437 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, chainList.front())); | 4505 | throw CompileError("short dot/colon syntax must be called within a with block"sv, chainList.front()); |
4438 | } else { | 4506 | } else { |
4439 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 4507 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); |
4440 | } | 4508 | } |
@@ -4527,7 +4595,7 @@ private: | |||
4527 | auto chain = x->new_ptr<ChainValue_t>(); | 4595 | auto chain = x->new_ptr<ChainValue_t>(); |
4528 | if (opIt == chainList.begin() && ast_is<ColonChainItem_t, DotChainItem_t>(x)) { | 4596 | if (opIt == chainList.begin() && ast_is<ColonChainItem_t, DotChainItem_t>(x)) { |
4529 | if (_withVars.empty()) { | 4597 | if (_withVars.empty()) { |
4530 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); | 4598 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); |
4531 | } else { | 4599 | } else { |
4532 | chain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 4600 | chain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); |
4533 | } | 4601 | } |
@@ -4671,7 +4739,7 @@ private: | |||
4671 | case id<ColonChainItem_t>(): | 4739 | case id<ColonChainItem_t>(): |
4672 | case id<Exp_t>(): | 4740 | case id<Exp_t>(): |
4673 | if (_withVars.empty()) { | 4741 | if (_withVars.empty()) { |
4674 | throw std::logic_error(_info.errorMessage("short dot/colon and indexing syntax must be called within a with block"sv, x)); | 4742 | throw CompileError("short dot/colon and indexing syntax must be called within a with block"sv, x); |
4675 | } else { | 4743 | } else { |
4676 | temp.push_back(_withVars.top()); | 4744 | temp.push_back(_withVars.top()); |
4677 | } | 4745 | } |
@@ -4704,7 +4772,7 @@ private: | |||
4704 | --next; | 4772 | --next; |
4705 | } | 4773 | } |
4706 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { | 4774 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { |
4707 | throw std::logic_error(_info.errorMessage("colon chain item must be followed by invoke arguments"sv, colonItem)); | 4775 | throw CompileError("colon chain item must be followed by invoke arguments"sv, colonItem); |
4708 | } | 4776 | } |
4709 | if (colonItem->name.is<LuaKeyword_t>()) { | 4777 | if (colonItem->name.is<LuaKeyword_t>()) { |
4710 | std::string callVar; | 4778 | std::string callVar; |
@@ -4843,7 +4911,7 @@ private: | |||
4843 | 4911 | ||
4844 | void transformMacroInPlace(MacroInPlace_t* macroInPlace) { | 4912 | void transformMacroInPlace(MacroInPlace_t* macroInPlace) { |
4845 | #ifdef YUE_NO_MACRO | 4913 | #ifdef YUE_NO_MACRO |
4846 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macroInPlace)); | 4914 | throw CompileError("macro feature not supported"sv, macroInPlace)); |
4847 | #else // YUE_NO_MACRO | 4915 | #else // YUE_NO_MACRO |
4848 | auto x = macroInPlace; | 4916 | auto x = macroInPlace; |
4849 | pushCurrentModule(); // cur | 4917 | pushCurrentModule(); // cur |
@@ -4858,22 +4926,22 @@ private: | |||
4858 | pushOptions(macroInPlace->m_begin.m_line - 1); // loadstring codes chunk options | 4926 | pushOptions(macroInPlace->m_begin.m_line - 1); // loadstring codes chunk options |
4859 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err | 4927 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err |
4860 | std::string err = lua_tostring(L, -1); | 4928 | std::string err = lua_tostring(L, -1); |
4861 | throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); | 4929 | throw CompileError("failed to load macro codes\n"s + err, x); |
4862 | } // f err | 4930 | } // f err |
4863 | if (lua_isnil(L, -2) != 0) { // f == nil, f err | 4931 | if (lua_isnil(L, -2) != 0) { // f == nil, f err |
4864 | std::string err = lua_tostring(L, -1); | 4932 | std::string err = lua_tostring(L, -1); |
4865 | throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); | 4933 | throw CompileError("failed to load macro codes, at (macro in-place): "s + err, x); |
4866 | } | 4934 | } |
4867 | lua_pop(L, 1); // f | 4935 | lua_pop(L, 1); // f |
4868 | pushYue("pcall"sv); // f pcall | 4936 | pushYue("pcall"sv); // f pcall |
4869 | lua_insert(L, -2); // pcall f | 4937 | lua_insert(L, -2); // pcall f |
4870 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc | 4938 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc |
4871 | std::string err = lua_tostring(L, -1); | 4939 | std::string err = lua_tostring(L, -1); |
4872 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | 4940 | throw CompileError("failed to generate macro function\n"s + err, x); |
4873 | } // success res | 4941 | } // success res |
4874 | if (lua_toboolean(L, -2) == 0) { | 4942 | if (lua_toboolean(L, -2) == 0) { |
4875 | std::string err = lua_tostring(L, -1); | 4943 | std::string err = lua_tostring(L, -1); |
4876 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | 4944 | throw CompileError("failed to generate macro function\n"s + err, x); |
4877 | } // true macroFunc | 4945 | } // true macroFunc |
4878 | lua_remove(L, -2); // macroFunc | 4946 | lua_remove(L, -2); // macroFunc |
4879 | pushYue("pcall"sv); // macroFunc pcall | 4947 | pushYue("pcall"sv); // macroFunc pcall |
@@ -4881,11 +4949,11 @@ private: | |||
4881 | bool success = lua_pcall(L, 1, 2, 0) == 0; | 4949 | bool success = lua_pcall(L, 1, 2, 0) == 0; |
4882 | if (!success) { // err | 4950 | if (!success) { // err |
4883 | std::string err = lua_tostring(L, -1); | 4951 | std::string err = lua_tostring(L, -1); |
4884 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | 4952 | throw CompileError("failed to expand macro: "s + err, x); |
4885 | } // success err | 4953 | } // success err |
4886 | if (lua_toboolean(L, -2) == 0) { | 4954 | if (lua_toboolean(L, -2) == 0) { |
4887 | std::string err = lua_tostring(L, -1); | 4955 | std::string err = lua_tostring(L, -1); |
4888 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | 4956 | throw CompileError("failed to expand macro: "s + err, x); |
4889 | } | 4957 | } |
4890 | #endif // YUE_NO_MACRO | 4958 | #endif // YUE_NO_MACRO |
4891 | } | 4959 | } |
@@ -4908,7 +4976,7 @@ private: | |||
4908 | if (!_useModule) { | 4976 | if (!_useModule) { |
4909 | auto code = expandBuiltinMacro(macroName, x); | 4977 | auto code = expandBuiltinMacro(macroName, x); |
4910 | if (!code.empty()) return {Empty, code, {}}; | 4978 | if (!code.empty()) return {Empty, code, {}}; |
4911 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 4979 | throw CompileError("can not resolve macro"sv, x); |
4912 | } | 4980 | } |
4913 | pushCurrentModule(); // cur | 4981 | pushCurrentModule(); // cur |
4914 | int top = lua_gettop(L) - 1; | 4982 | int top = lua_gettop(L) - 1; |
@@ -4918,7 +4986,7 @@ private: | |||
4918 | if (lua_isfunction(L, -1) == 0) { | 4986 | if (lua_isfunction(L, -1) == 0) { |
4919 | auto code = expandBuiltinMacro(macroName, x); | 4987 | auto code = expandBuiltinMacro(macroName, x); |
4920 | if (!code.empty()) return {Empty, code, {}}; | 4988 | if (!code.empty()) return {Empty, code, {}}; |
4921 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 4989 | throw CompileError("can not resolve macro"sv, x); |
4922 | } // cur macroFunc | 4990 | } // cur macroFunc |
4923 | pushYue("pcall"sv); // cur macroFunc pcall | 4991 | pushYue("pcall"sv); // cur macroFunc pcall |
4924 | lua_insert(L, -2); // cur pcall macroFunc | 4992 | lua_insert(L, -2); // cur pcall macroFunc |
@@ -4981,15 +5049,15 @@ private: | |||
4981 | bool success = lua_pcall(L, (args ? static_cast<int>(args->size()) : 0) + 1, 2, 0) == 0; | 5049 | bool success = lua_pcall(L, (args ? static_cast<int>(args->size()) : 0) + 1, 2, 0) == 0; |
4982 | if (!success) { // cur err | 5050 | if (!success) { // cur err |
4983 | std::string err = lua_tostring(L, -1); | 5051 | std::string err = lua_tostring(L, -1); |
4984 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | 5052 | throw CompileError("failed to expand macro: "s + err, x); |
4985 | } // cur success res | 5053 | } // cur success res |
4986 | if (lua_toboolean(L, -2) == 0) { | 5054 | if (lua_toboolean(L, -2) == 0) { |
4987 | std::string err = lua_tostring(L, -1); | 5055 | std::string err = lua_tostring(L, -1); |
4988 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | 5056 | throw CompileError("failed to expand macro: "s + err, x); |
4989 | } | 5057 | } |
4990 | lua_remove(L, -2); // cur res | 5058 | lua_remove(L, -2); // cur res |
4991 | if (lua_isstring(L, -1) == 0 && lua_istable(L, -1) == 0) { | 5059 | if (lua_isstring(L, -1) == 0 && lua_istable(L, -1) == 0) { |
4992 | throw std::logic_error(_info.errorMessage("macro function must return string or table"sv, x)); | 5060 | throw CompileError("macro function must return string or table"sv, x); |
4993 | } // cur res | 5061 | } // cur res |
4994 | std::string codes; | 5062 | std::string codes; |
4995 | std::string type; | 5063 | std::string type; |
@@ -4999,7 +5067,7 @@ private: | |||
4999 | if (lua_isstring(L, -1) != 0) { | 5067 | if (lua_isstring(L, -1) != 0) { |
5000 | codes = lua_tostring(L, -1); | 5068 | codes = lua_tostring(L, -1); |
5001 | } else { | 5069 | } else { |
5002 | throw std::logic_error(_info.errorMessage("macro table must contain field \"code\" of string"sv, x)); | 5070 | throw CompileError("macro table must contain field \"code\" of string"sv, x); |
5003 | } | 5071 | } |
5004 | lua_pop(L, 1); // cur res | 5072 | lua_pop(L, 1); // cur res |
5005 | lua_getfield(L, -1, "type"); // cur res type | 5073 | lua_getfield(L, -1, "type"); // cur res type |
@@ -5007,7 +5075,7 @@ private: | |||
5007 | type = lua_tostring(L, -1); | 5075 | type = lua_tostring(L, -1); |
5008 | } | 5076 | } |
5009 | if (type != "lua"sv && type != "text"sv) { | 5077 | if (type != "lua"sv && type != "text"sv) { |
5010 | throw std::logic_error(_info.errorMessage("macro table must contain field \"type\" of value \"lua\" or \"text\""sv, x)); | 5078 | throw CompileError("macro table must contain field \"type\" of value \"lua\" or \"text\""sv, x); |
5011 | } | 5079 | } |
5012 | lua_pop(L, 1); // cur res | 5080 | lua_pop(L, 1); // cur res |
5013 | lua_getfield(L, -1, "locals"); // cur res locals | 5081 | lua_getfield(L, -1, "locals"); // cur res locals |
@@ -5016,13 +5084,13 @@ private: | |||
5016 | lua_rawgeti(L, -1, i + 1); // cur res locals item | 5084 | lua_rawgeti(L, -1, i + 1); // cur res locals item |
5017 | size_t len = 0; | 5085 | size_t len = 0; |
5018 | if (lua_isstring(L, -1) == 0) { | 5086 | if (lua_isstring(L, -1) == 0) { |
5019 | throw std::logic_error(_info.errorMessage("macro table field \"locals\" must be a table of strings"sv, x)); | 5087 | throw CompileError("macro table field \"locals\" must be a table of strings"sv, x); |
5020 | } | 5088 | } |
5021 | auto name = lua_tolstring(L, -1, &len); | 5089 | auto name = lua_tolstring(L, -1, &len); |
5022 | if (_parser.match<Variable_t>({name, len})) { | 5090 | if (_parser.match<Variable_t>({name, len})) { |
5023 | localVars.push_back(std::string(name, len)); | 5091 | localVars.push_back(std::string(name, len)); |
5024 | } else { | 5092 | } else { |
5025 | throw std::logic_error(_info.errorMessage("macro table field \"locals\" must contain names for local variables, got \""s + std::string(name, len) + '"', x)); | 5093 | throw CompileError("macro table field \"locals\" must contain names for local variables, got \""s + std::string(name, len) + '"', x); |
5026 | } | 5094 | } |
5027 | lua_pop(L, 1); | 5095 | lua_pop(L, 1); |
5028 | } | 5096 | } |
@@ -5046,14 +5114,14 @@ private: | |||
5046 | ParseInfo info; | 5114 | ParseInfo info; |
5047 | if (type == "lua"sv) { | 5115 | if (type == "lua"sv) { |
5048 | if (!isBlock) { | 5116 | if (!isBlock) { |
5049 | throw std::logic_error(_info.errorMessage("lua macro can only be placed where block macro is allowed"sv, x)); | 5117 | throw CompileError("lua macro can only be placed where block macro is allowed"sv, x); |
5050 | } | 5118 | } |
5051 | auto macroChunk = "=(macro "s + _parser.toString(x->name) + ')'; | 5119 | auto macroChunk = "=(macro "s + _parser.toString(x->name) + ')'; |
5052 | int top = lua_gettop(L); | 5120 | int top = lua_gettop(L); |
5053 | DEFER(lua_settop(L, top)); | 5121 | DEFER(lua_settop(L, top)); |
5054 | if (luaL_loadbuffer(L, codes.c_str(), codes.size(), macroChunk.c_str()) != 0) { | 5122 | if (luaL_loadbuffer(L, codes.c_str(), codes.size(), macroChunk.c_str()) != 0) { |
5055 | std::string err = lua_tostring(L, -1); | 5123 | std::string err = lua_tostring(L, -1); |
5056 | throw std::logic_error(_info.errorMessage(err, x)); | 5124 | throw CompileError(err, x); |
5057 | } | 5125 | } |
5058 | if (!codes.empty()) { | 5126 | if (!codes.empty()) { |
5059 | if (_config.reserveLineNumber) { | 5127 | if (_config.reserveLineNumber) { |
@@ -5064,7 +5132,7 @@ private: | |||
5064 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; | 5132 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; |
5065 | } else if (type == "text"sv) { | 5133 | } else if (type == "text"sv) { |
5066 | if (!isBlock) { | 5134 | if (!isBlock) { |
5067 | throw std::logic_error(_info.errorMessage("text macro can only be placed where block macro is allowed"sv, x)); | 5135 | throw CompileError("text macro can only be placed where block macro is allowed"sv, x); |
5068 | } | 5136 | } |
5069 | if (!codes.empty()) { | 5137 | if (!codes.empty()) { |
5070 | codes.append(_newLine); | 5138 | codes.append(_newLine); |
@@ -5074,22 +5142,19 @@ private: | |||
5074 | if (!codes.empty()) { | 5142 | if (!codes.empty()) { |
5075 | if (isBlock) { | 5143 | if (isBlock) { |
5076 | info = _parser.parse<BlockEnd_t>(codes); | 5144 | info = _parser.parse<BlockEnd_t>(codes); |
5077 | if (!info.node) { | 5145 | if (info.error) { |
5078 | info.error = info.error.substr(info.error.find(':') + 2); | 5146 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); |
5079 | throw std::logic_error(_info.errorMessage("failed to expand macro as block: "s + info.error, x)); | ||
5080 | } | 5147 | } |
5081 | } else { | 5148 | } else { |
5082 | info = _parser.parse<Exp_t>(codes); | 5149 | info = _parser.parse<Exp_t>(codes); |
5083 | if (!info.node && allowBlockMacroReturn) { | 5150 | if (!info.node && allowBlockMacroReturn) { |
5084 | info = _parser.parse<BlockEnd_t>(codes); | 5151 | info = _parser.parse<BlockEnd_t>(codes); |
5085 | if (!info.node) { | 5152 | if (info.error) { |
5086 | info.error = info.error.substr(info.error.find(':') + 2); | 5153 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); |
5087 | throw std::logic_error(_info.errorMessage("failed to expand macro as expr or block: "s + info.error, x)); | ||
5088 | } | 5154 | } |
5089 | isBlock = true; | 5155 | isBlock = true; |
5090 | } else if (!info.node) { | 5156 | } else if (info.error) { |
5091 | info.error = info.error.substr(info.error.find(':') + 2); | 5157 | throw CompileError("failed to expand macro as expr: "s + info.error.value().msg, x); |
5092 | throw std::logic_error(_info.errorMessage("failed to expand macro as expr: "s + info.error, x)); | ||
5093 | } | 5158 | } |
5094 | } | 5159 | } |
5095 | int line = x->m_begin.m_line; | 5160 | int line = x->m_begin.m_line; |
@@ -5140,18 +5205,18 @@ private: | |||
5140 | auto stmt = static_cast<Statement_t*>(stmt_); | 5205 | auto stmt = static_cast<Statement_t*>(stmt_); |
5141 | if (auto global = stmt->content.as<Global_t>()) { | 5206 | if (auto global = stmt->content.as<Global_t>()) { |
5142 | if (global->item.is<GlobalOp_t>()) { | 5207 | if (global->item.is<GlobalOp_t>()) { |
5143 | throw std::logic_error(_info.errorMessage("can not insert global statement with wildcard operator from macro"sv, x)); | 5208 | throw CompileError("can not insert global statement with wildcard operator from macro"sv, x); |
5144 | } | 5209 | } |
5145 | } else if (auto local = stmt->content.as<Local_t>()) { | 5210 | } else if (auto local = stmt->content.as<Local_t>()) { |
5146 | if (local->item.is<LocalFlag_t>()) { | 5211 | if (local->item.is<LocalFlag_t>()) { |
5147 | throw std::logic_error(_info.errorMessage("can not insert local statement with wildcard operator from macro"sv, x)); | 5212 | throw CompileError("can not insert local statement with wildcard operator from macro"sv, x); |
5148 | } | 5213 | } |
5149 | } | 5214 | } |
5150 | } | 5215 | } |
5151 | } | 5216 | } |
5152 | return {info.node, std::move(info.codes), Empty, std::move(localVars)}; | 5217 | return {info.node, std::move(info.codes), Empty, std::move(localVars)}; |
5153 | } else { | 5218 | } else { |
5154 | if (!isBlock) throw std::logic_error(_info.errorMessage("failed to expand empty macro as expr"sv, x)); | 5219 | if (!isBlock) throw CompileError("failed to expand empty macro as expr"sv, x); |
5155 | return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty, std::move(localVars)}; | 5220 | return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty, std::move(localVars)}; |
5156 | } | 5221 | } |
5157 | } | 5222 | } |
@@ -5205,7 +5270,7 @@ private: | |||
5205 | return; | 5270 | return; |
5206 | #else | 5271 | #else |
5207 | (void)allowBlockMacroReturn; | 5272 | (void)allowBlockMacroReturn; |
5208 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, chainValue)); | 5273 | throw CompileError("macro feature not supported"sv, chainValue)); |
5209 | #endif // YUE_NO_MACRO | 5274 | #endif // YUE_NO_MACRO |
5210 | } | 5275 | } |
5211 | const auto& chainList = chainValue->items.objects(); | 5276 | const auto& chainList = chainValue->items.objects(); |
@@ -5243,11 +5308,11 @@ private: | |||
5243 | } | 5308 | } |
5244 | 5309 | ||
5245 | void transformSlice(Slice_t* slice, str_list&) { | 5310 | void transformSlice(Slice_t* slice, str_list&) { |
5246 | throw std::logic_error(_info.errorMessage("slice syntax not supported here"sv, slice)); | 5311 | throw CompileError("slice syntax not supported here"sv, slice); |
5247 | } | 5312 | } |
5248 | 5313 | ||
5249 | void transform_table_appending_op(TableAppendingOp_t* op, str_list&) { | 5314 | void transform_table_appending_op(TableAppendingOp_t* op, str_list&) { |
5250 | throw std::logic_error(_info.errorMessage("table appending syntax not supported here"sv, op)); | 5315 | throw CompileError("table appending syntax not supported here"sv, op); |
5251 | } | 5316 | } |
5252 | 5317 | ||
5253 | void transformInvoke(Invoke_t* invoke, str_list& out) { | 5318 | void transformInvoke(Invoke_t* invoke, str_list& out) { |
@@ -5270,7 +5335,7 @@ private: | |||
5270 | for (auto _op : unary_value->ops.objects()) { | 5335 | for (auto _op : unary_value->ops.objects()) { |
5271 | std::string op = _parser.toString(_op); | 5336 | std::string op = _parser.toString(_op); |
5272 | if (op == "~"sv && getLuaTarget(_op) < 503) { | 5337 | if (op == "~"sv && getLuaTarget(_op) < 503) { |
5273 | throw std::logic_error(_info.errorMessage("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, _op)); | 5338 | throw CompileError("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, _op); |
5274 | } | 5339 | } |
5275 | temp.push_back(op == "not"sv ? op + ' ' : op); | 5340 | temp.push_back(op == "not"sv ? op + ' ' : op); |
5276 | } | 5341 | } |
@@ -5287,7 +5352,7 @@ private: | |||
5287 | for (auto _op : unary_exp->ops.objects()) { | 5352 | for (auto _op : unary_exp->ops.objects()) { |
5288 | std::string op = _parser.toString(_op); | 5353 | std::string op = _parser.toString(_op); |
5289 | if (op == "~"sv && getLuaTarget(_op) < 503) { | 5354 | if (op == "~"sv && getLuaTarget(_op) < 503) { |
5290 | throw std::logic_error(_info.errorMessage("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, _op)); | 5355 | throw CompileError("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, _op); |
5291 | } | 5356 | } |
5292 | unary_op.append(op == "not"sv ? op + ' ' : op); | 5357 | unary_op.append(op == "not"sv ? op + ' ' : op); |
5293 | } | 5358 | } |
@@ -5311,7 +5376,7 @@ private: | |||
5311 | 5376 | ||
5312 | void transformVarArg(VarArg_t* varArg, str_list& out) { | 5377 | void transformVarArg(VarArg_t* varArg, str_list& out) { |
5313 | if (_varArgs.empty() || !_varArgs.top().hasVar) { | 5378 | if (_varArgs.empty() || !_varArgs.top().hasVar) { |
5314 | throw std::logic_error(_info.errorMessage("cannot use '...' outside a vararg function near '...'"sv, varArg)); | 5379 | throw CompileError("cannot use '...' outside a vararg function near '...'"sv, varArg); |
5315 | } | 5380 | } |
5316 | _varArgs.top().usedVar = true; | 5381 | _varArgs.top().usedVar = true; |
5317 | out.push_back("..."s); | 5382 | out.push_back("..."s); |
@@ -5385,7 +5450,7 @@ private: | |||
5385 | case id<VariablePairDef_t>(): { | 5450 | case id<VariablePairDef_t>(): { |
5386 | if (auto pair = ast_cast<VariablePairDef_t>(item)) { | 5451 | if (auto pair = ast_cast<VariablePairDef_t>(item)) { |
5387 | if (pair->defVal) { | 5452 | if (pair->defVal) { |
5388 | throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); | 5453 | throw CompileError("invalid default value here"sv, pair->defVal); |
5389 | } | 5454 | } |
5390 | item = pair->pair.get(); | 5455 | item = pair->pair.get(); |
5391 | } | 5456 | } |
@@ -5399,7 +5464,7 @@ private: | |||
5399 | case id<NormalPairDef_t>(): { | 5464 | case id<NormalPairDef_t>(): { |
5400 | if (auto pair = ast_cast<NormalPairDef_t>(item)) { | 5465 | if (auto pair = ast_cast<NormalPairDef_t>(item)) { |
5401 | if (pair->defVal) { | 5466 | if (pair->defVal) { |
5402 | throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); | 5467 | throw CompileError("invalid default value here"sv, pair->defVal); |
5403 | } | 5468 | } |
5404 | item = pair->pair.get(); | 5469 | item = pair->pair.get(); |
5405 | } | 5470 | } |
@@ -5451,7 +5516,7 @@ private: | |||
5451 | auto current = item; | 5516 | auto current = item; |
5452 | if (auto pair = ast_cast<NormalDef_t>(item)) { | 5517 | if (auto pair = ast_cast<NormalDef_t>(item)) { |
5453 | if (pair->defVal) { | 5518 | if (pair->defVal) { |
5454 | throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); | 5519 | throw CompileError("invalid default value here"sv, pair->defVal); |
5455 | } | 5520 | } |
5456 | item = pair->item.get(); | 5521 | item = pair->item.get(); |
5457 | } | 5522 | } |
@@ -5500,7 +5565,7 @@ private: | |||
5500 | case id<MetaVariablePairDef_t>(): { | 5565 | case id<MetaVariablePairDef_t>(): { |
5501 | if (auto pair = ast_cast<MetaVariablePairDef_t>(item)) { | 5566 | if (auto pair = ast_cast<MetaVariablePairDef_t>(item)) { |
5502 | if (pair->defVal) { | 5567 | if (pair->defVal) { |
5503 | throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); | 5568 | throw CompileError("invalid default value here"sv, pair->defVal); |
5504 | } | 5569 | } |
5505 | item = pair->pair.get(); | 5570 | item = pair->pair.get(); |
5506 | } | 5571 | } |
@@ -5514,7 +5579,7 @@ private: | |||
5514 | case id<MetaNormalPairDef_t>(): { | 5579 | case id<MetaNormalPairDef_t>(): { |
5515 | if (auto pair = ast_cast<MetaNormalPairDef_t>(item)) { | 5580 | if (auto pair = ast_cast<MetaNormalPairDef_t>(item)) { |
5516 | if (pair->defVal) { | 5581 | if (pair->defVal) { |
5517 | throw std::logic_error(_info.errorMessage("invalid default value here"sv, pair->defVal)); | 5582 | throw CompileError("invalid default value here"sv, pair->defVal); |
5518 | } | 5583 | } |
5519 | item = pair->pair.get(); | 5584 | item = pair->pair.get(); |
5520 | } | 5585 | } |
@@ -5601,7 +5666,7 @@ private: | |||
5601 | case id<VariablePairDef_t>(): { | 5666 | case id<VariablePairDef_t>(): { |
5602 | auto pair = static_cast<VariablePairDef_t*>(item); | 5667 | auto pair = static_cast<VariablePairDef_t*>(item); |
5603 | if (pair->defVal) { | 5668 | if (pair->defVal) { |
5604 | throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); | 5669 | throw CompileError("invalid default value"sv, pair->defVal); |
5605 | } | 5670 | } |
5606 | item = pair->pair.get(); | 5671 | item = pair->pair.get(); |
5607 | break; | 5672 | break; |
@@ -5609,7 +5674,7 @@ private: | |||
5609 | case id<NormalPairDef_t>(): { | 5674 | case id<NormalPairDef_t>(): { |
5610 | auto pair = static_cast<NormalPairDef_t*>(item); | 5675 | auto pair = static_cast<NormalPairDef_t*>(item); |
5611 | if (pair->defVal) { | 5676 | if (pair->defVal) { |
5612 | throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); | 5677 | throw CompileError("invalid default value"sv, pair->defVal); |
5613 | } | 5678 | } |
5614 | item = pair->pair.get(); | 5679 | item = pair->pair.get(); |
5615 | break; | 5680 | break; |
@@ -5617,7 +5682,7 @@ private: | |||
5617 | case id<MetaVariablePairDef_t>(): { | 5682 | case id<MetaVariablePairDef_t>(): { |
5618 | auto pair = static_cast<MetaVariablePairDef_t*>(item); | 5683 | auto pair = static_cast<MetaVariablePairDef_t*>(item); |
5619 | if (pair->defVal) { | 5684 | if (pair->defVal) { |
5620 | throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); | 5685 | throw CompileError("invalid default value"sv, pair->defVal); |
5621 | } | 5686 | } |
5622 | item = pair->pair.get(); | 5687 | item = pair->pair.get(); |
5623 | break; | 5688 | break; |
@@ -5625,7 +5690,7 @@ private: | |||
5625 | case id<MetaNormalPairDef_t>(): { | 5690 | case id<MetaNormalPairDef_t>(): { |
5626 | auto pair = static_cast<MetaNormalPairDef_t*>(item); | 5691 | auto pair = static_cast<MetaNormalPairDef_t*>(item); |
5627 | if (pair->defVal) { | 5692 | if (pair->defVal) { |
5628 | throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); | 5693 | throw CompileError("invalid default value"sv, pair->defVal); |
5629 | } | 5694 | } |
5630 | item = pair->pair.get(); | 5695 | item = pair->pair.get(); |
5631 | break; | 5696 | break; |
@@ -5633,7 +5698,7 @@ private: | |||
5633 | case id<NormalDef_t>(): { | 5698 | case id<NormalDef_t>(): { |
5634 | auto pair = static_cast<NormalDef_t*>(item); | 5699 | auto pair = static_cast<NormalDef_t*>(item); |
5635 | if (pair->defVal) { | 5700 | if (pair->defVal) { |
5636 | throw std::logic_error(_info.errorMessage("invalid default value"sv, pair->defVal)); | 5701 | throw CompileError("invalid default value"sv, pair->defVal); |
5637 | } | 5702 | } |
5638 | item = pair->item.get(); | 5703 | item = pair->item.get(); |
5639 | break; | 5704 | break; |
@@ -5650,7 +5715,7 @@ private: | |||
5650 | isMetamethod = true; | 5715 | isMetamethod = true; |
5651 | auto mp = static_cast<MetaVariablePair_t*>(item); | 5716 | auto mp = static_cast<MetaVariablePair_t*>(item); |
5652 | if (metatableItem) { | 5717 | if (metatableItem) { |
5653 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); | 5718 | throw CompileError("too many metatable declarations"sv, mp->name); |
5654 | } | 5719 | } |
5655 | auto name = _parser.toString(mp->name); | 5720 | auto name = _parser.toString(mp->name); |
5656 | checkMetamethod(name, mp->name); | 5721 | checkMetamethod(name, mp->name); |
@@ -5665,7 +5730,7 @@ private: | |||
5665 | auto newPair = item->new_ptr<NormalPair_t>(); | 5730 | auto newPair = item->new_ptr<NormalPair_t>(); |
5666 | if (mp->key) { | 5731 | if (mp->key) { |
5667 | if (metatableItem) { | 5732 | if (metatableItem) { |
5668 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->key)); | 5733 | throw CompileError("too many metatable declarations"sv, mp->key); |
5669 | } | 5734 | } |
5670 | switch (mp->key->getId()) { | 5735 | switch (mp->key->getId()) { |
5671 | case id<Name_t>(): { | 5736 | case id<Name_t>(): { |
@@ -5690,7 +5755,7 @@ private: | |||
5690 | metatable->pairs.push_back(newPair); | 5755 | metatable->pairs.push_back(newPair); |
5691 | } else { | 5756 | } else { |
5692 | if (!metatable->pairs.empty()) { | 5757 | if (!metatable->pairs.empty()) { |
5693 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->value)); | 5758 | throw CompileError("too many metatable declarations"sv, mp->value); |
5694 | } | 5759 | } |
5695 | metatableItem.set(mp->value); | 5760 | metatableItem.set(mp->value); |
5696 | } | 5761 | } |
@@ -5910,7 +5975,7 @@ private: | |||
5910 | auto indexVar = getUnusedName("_index_"sv); | 5975 | auto indexVar = getUnusedName("_index_"sv); |
5911 | varAfter.push_back(indexVar); | 5976 | varAfter.push_back(indexVar); |
5912 | auto value = singleValueFrom(star_exp->value); | 5977 | auto value = singleValueFrom(star_exp->value); |
5913 | if (!value) throw std::logic_error(_info.errorMessage("invalid star syntax"sv, star_exp)); | 5978 | if (!value) throw CompileError("invalid star syntax"sv, star_exp); |
5914 | bool endWithSlice = false; | 5979 | bool endWithSlice = false; |
5915 | BLOCK_START | 5980 | BLOCK_START |
5916 | auto chainValue = value->item.as<ChainValue_t>(); | 5981 | auto chainValue = value->item.as<ChainValue_t>(); |
@@ -6422,11 +6487,11 @@ private: | |||
6422 | void checkOperatorAvailable(const std::string& op, ast_node* node) { | 6487 | void checkOperatorAvailable(const std::string& op, ast_node* node) { |
6423 | if (op == "&"sv || op == "~"sv || op == "|"sv || op == ">>"sv || op == "<<"sv) { | 6488 | if (op == "&"sv || op == "~"sv || op == "|"sv || op == ">>"sv || op == "<<"sv) { |
6424 | if (getLuaTarget(node) < 503) { | 6489 | if (getLuaTarget(node) < 503) { |
6425 | throw std::logic_error(_info.errorMessage("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, node)); | 6490 | throw CompileError("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, node); |
6426 | } | 6491 | } |
6427 | } else if (op == "//"sv) { | 6492 | } else if (op == "//"sv) { |
6428 | if (getLuaTarget(node) < 503) { | 6493 | if (getLuaTarget(node) < 503) { |
6429 | throw std::logic_error(_info.errorMessage("floor division is not available when not targeting Lua version 5.3 or higher"sv, node)); | 6494 | throw CompileError("floor division is not available when not targeting Lua version 5.3 or higher"sv, node); |
6430 | } | 6495 | } |
6431 | } | 6496 | } |
6432 | } | 6497 | } |
@@ -6668,7 +6733,7 @@ private: | |||
6668 | std::string assignItem; | 6733 | std::string assignItem; |
6669 | if (assignable) { | 6734 | if (assignable) { |
6670 | if (!isAssignable(assignable)) { | 6735 | if (!isAssignable(assignable)) { |
6671 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, assignable)); | 6736 | throw CompileError("left hand expression is not assignable"sv, assignable); |
6672 | } | 6737 | } |
6673 | bool newDefined = false; | 6738 | bool newDefined = false; |
6674 | std::tie(className, newDefined) = defineClassVariable(assignable); | 6739 | std::tie(className, newDefined) = defineClassVariable(assignable); |
@@ -6962,7 +7027,7 @@ private: | |||
6962 | if (selfItem) { | 7027 | if (selfItem) { |
6963 | type = MemType::Property; | 7028 | type = MemType::Property; |
6964 | auto name = ast_cast<SelfName_t>(selfItem->name); | 7029 | auto name = ast_cast<SelfName_t>(selfItem->name); |
6965 | if (!name) throw std::logic_error(_info.errorMessage("invalid class poperty name"sv, selfItem->name)); | 7030 | if (!name) throw CompileError("invalid class poperty name"sv, selfItem->name); |
6966 | newSuperCall = classVar + ".__parent."s + _parser.toString(name->name); | 7031 | newSuperCall = classVar + ".__parent."s + _parser.toString(name->name); |
6967 | } else { | 7032 | } else { |
6968 | auto x = keyName; | 7033 | auto x = keyName; |
@@ -7287,17 +7352,17 @@ private: | |||
7287 | void transformExport(Export_t* exportNode, str_list& out) { | 7352 | void transformExport(Export_t* exportNode, str_list& out) { |
7288 | auto x = exportNode; | 7353 | auto x = exportNode; |
7289 | if (_scopes.size() > 1) { | 7354 | if (_scopes.size() > 1) { |
7290 | throw std::logic_error(_info.errorMessage("can not do module export outside the root block"sv, exportNode)); | 7355 | throw CompileError("can not do module export outside the root block"sv, exportNode); |
7291 | } | 7356 | } |
7292 | if (exportNode->assign) { | 7357 | if (exportNode->assign) { |
7293 | auto expList = exportNode->target.to<ExpList_t>(); | 7358 | auto expList = exportNode->target.to<ExpList_t>(); |
7294 | if (expList->exprs.size() != exportNode->assign->values.size()) { | 7359 | if (expList->exprs.size() != exportNode->assign->values.size()) { |
7295 | throw std::logic_error(_info.errorMessage("left and right expressions must be matched in export statement"sv, x)); | 7360 | throw CompileError("left and right expressions must be matched in export statement"sv, x); |
7296 | } | 7361 | } |
7297 | for (auto _exp : expList->exprs.objects()) { | 7362 | for (auto _exp : expList->exprs.objects()) { |
7298 | auto exp = static_cast<Exp_t*>(_exp); | 7363 | auto exp = static_cast<Exp_t*>(_exp); |
7299 | if (!variableFrom(exp) && !exp->getByPath<UnaryExp_t, Value_t, SimpleValue_t, TableLit_t>() && !exp->getByPath<UnaryExp_t, Value_t, SimpleTable_t>()) { | 7364 | if (!variableFrom(exp) && !exp->getByPath<UnaryExp_t, Value_t, SimpleValue_t, TableLit_t>() && !exp->getByPath<UnaryExp_t, Value_t, SimpleTable_t>()) { |
7300 | throw std::logic_error(_info.errorMessage("left hand expressions must be variables in export statement"sv, x)); | 7365 | throw CompileError("left hand expressions must be variables in export statement"sv, x); |
7301 | } | 7366 | } |
7302 | } | 7367 | } |
7303 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 7368 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
@@ -7696,7 +7761,7 @@ private: | |||
7696 | case id<MacroName_t>(): | 7761 | case id<MacroName_t>(): |
7697 | case id<MacroNamePair_t>(): | 7762 | case id<MacroNamePair_t>(): |
7698 | case id<ImportAllMacro_t>(): { | 7763 | case id<ImportAllMacro_t>(): { |
7699 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); | 7764 | throw CompileError("macro feature not supported"sv, item)); |
7700 | break; | 7765 | break; |
7701 | } | 7766 | } |
7702 | #else // YUE_NO_MACRO | 7767 | #else // YUE_NO_MACRO |
@@ -7712,7 +7777,7 @@ private: | |||
7712 | break; | 7777 | break; |
7713 | } | 7778 | } |
7714 | case id<ImportAllMacro_t>(): | 7779 | case id<ImportAllMacro_t>(): |
7715 | if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); | 7780 | if (importAllMacro) throw CompileError("import all macro symbol duplicated"sv, item); |
7716 | importAllMacro = true; | 7781 | importAllMacro = true; |
7717 | break; | 7782 | break; |
7718 | #endif // YUE_NO_MACRO | 7783 | #endif // YUE_NO_MACRO |
@@ -7740,7 +7805,7 @@ private: | |||
7740 | lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur find_modulepath moduleName | 7805 | lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur find_modulepath moduleName |
7741 | if (lua_pcall(L, 1, 2, 0) != 0) { | 7806 | if (lua_pcall(L, 1, 2, 0) != 0) { |
7742 | std::string err = lua_tostring(L, -1); | 7807 | std::string err = lua_tostring(L, -1); |
7743 | throw std::logic_error(_info.errorMessage("failed to resolve module path\n"s + err, x)); | 7808 | throw CompileError("failed to resolve module path\n"s + err, x); |
7744 | } | 7809 | } |
7745 | if (lua_isnil(L, -2) != 0) { | 7810 | if (lua_isnil(L, -2) != 0) { |
7746 | str_list files; | 7811 | str_list files; |
@@ -7752,7 +7817,7 @@ private: | |||
7752 | lua_pop(L, 1); | 7817 | lua_pop(L, 1); |
7753 | } | 7818 | } |
7754 | } | 7819 | } |
7755 | throw std::logic_error(_info.errorMessage("module '"s + moduleName + "\' not found:\n\t"s + join(files, "\n\t"sv), x)); | 7820 | throw CompileError("module '"s + moduleName + "\' not found:\n\t"s + join(files, "\n\t"sv), x); |
7756 | } | 7821 | } |
7757 | lua_pop(L, 1); | 7822 | lua_pop(L, 1); |
7758 | std::string moduleFullName = lua_tostring(L, -1); | 7823 | std::string moduleFullName = lua_tostring(L, -1); |
@@ -7762,10 +7827,10 @@ private: | |||
7762 | lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur load_text moduleFullName | 7827 | lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur load_text moduleFullName |
7763 | if (lua_pcall(L, 1, 1, 0) != 0) { | 7828 | if (lua_pcall(L, 1, 1, 0) != 0) { |
7764 | std::string err = lua_tostring(L, -1); | 7829 | std::string err = lua_tostring(L, -1); |
7765 | throw std::logic_error(_info.errorMessage("failed to read module file\n"s + err, x)); | 7830 | throw CompileError("failed to read module file\n"s + err, x); |
7766 | } // cur text | 7831 | } // cur text |
7767 | if (lua_isnil(L, -1) != 0) { | 7832 | if (lua_isnil(L, -1) != 0) { |
7768 | throw std::logic_error(_info.errorMessage("failed to get module text"sv, x)); | 7833 | throw CompileError("failed to get module text"sv, x); |
7769 | } // cur text | 7834 | } // cur text |
7770 | std::string text = lua_tostring(L, -1); | 7835 | std::string text = lua_tostring(L, -1); |
7771 | auto compiler = YueCompilerImpl(L, _luaOpen, false); | 7836 | auto compiler = YueCompilerImpl(L, _luaOpen, false); |
@@ -7777,8 +7842,8 @@ private: | |||
7777 | config.module = moduleFullName; | 7842 | config.module = moduleFullName; |
7778 | config.exporting = true; | 7843 | config.exporting = true; |
7779 | auto result = compiler.compile(text, config); | 7844 | auto result = compiler.compile(text, config); |
7780 | if (result.codes.empty() && !result.error.empty()) { | 7845 | if (result.error) { |
7781 | throw std::logic_error(_info.errorMessage("failed to compile module '"s + moduleName + "\': "s + result.error, x)); | 7846 | throw CompileError("failed to compile module '"s + moduleName + "\': "s + result.error.value().msg, x); |
7782 | } | 7847 | } |
7783 | lua_pop(L, 1); // cur | 7848 | lua_pop(L, 1); // cur |
7784 | } | 7849 | } |
@@ -7798,7 +7863,7 @@ private: | |||
7798 | } | 7863 | } |
7799 | #else // YUE_NO_MACRO | 7864 | #else // YUE_NO_MACRO |
7800 | if (importAllMacro) { | 7865 | if (importAllMacro) { |
7801 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, import->target)); | 7866 | throw CompileError("macro feature not supported"sv, import->target)); |
7802 | } | 7867 | } |
7803 | #endif // YUE_NO_MACRO | 7868 | #endif // YUE_NO_MACRO |
7804 | if (newTab->items.empty()) { | 7869 | if (newTab->items.empty()) { |
@@ -8034,10 +8099,12 @@ private: | |||
8034 | pushScope(); | 8099 | pushScope(); |
8035 | extraScope = true; | 8100 | extraScope = true; |
8036 | } | 8101 | } |
8102 | auto typeVar = getUnusedName("_type_"); | ||
8103 | forceAddToScope(typeVar); | ||
8037 | tabCheckVar = getUnusedName("_tab_"); | 8104 | tabCheckVar = getUnusedName("_tab_"); |
8038 | forceAddToScope(tabCheckVar); | 8105 | forceAddToScope(tabCheckVar); |
8039 | temp.push_back(indent() + "local "s + tabCheckVar + " = "s + globalVar("type", branch) + '(' + objVar + ')' + nll(branch)); | 8106 | temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type", branch) + '(' + objVar + ')' + nll(branch)); |
8040 | temp.push_back(indent() + tabCheckVar + " = \"table\" == "s + tabCheckVar + " or \"userdata\" == "s + tabCheckVar + nll(branch)); | 8107 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nll(branch)); |
8041 | } | 8108 | } |
8042 | std::string matchVar; | 8109 | std::string matchVar; |
8043 | bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; | 8110 | bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; |
@@ -8199,7 +8266,7 @@ private: | |||
8199 | } else { | 8266 | } else { |
8200 | _buf << "only one right value expected, got "sv << x->assign->values.size(); | 8267 | _buf << "only one right value expected, got "sv << x->assign->values.size(); |
8201 | } | 8268 | } |
8202 | throw std::logic_error(_info.errorMessage(clearBuf(), x->assign->values.front())); | 8269 | throw CompileError(clearBuf(), x->assign->values.front()); |
8203 | } | 8270 | } |
8204 | auto listA = x->new_ptr<NameList_t>(); | 8271 | auto listA = x->new_ptr<NameList_t>(); |
8205 | auto assignA = x->new_ptr<Assign_t>(); | 8272 | auto assignA = x->new_ptr<Assign_t>(); |
@@ -8257,7 +8324,7 @@ private: | |||
8257 | } | 8324 | } |
8258 | } else { | 8325 | } else { |
8259 | if (localAttrib->attrib.is<CloseAttrib_t>()) { | 8326 | if (localAttrib->attrib.is<CloseAttrib_t>()) { |
8260 | throw std::logic_error(_info.errorMessage("close attribute is not available when not targeting Lua version 5.4 or higher"sv, x)); | 8327 | throw CompileError("close attribute is not available when not targeting Lua version 5.4 or higher"sv, x); |
8261 | } | 8328 | } |
8262 | for (auto& var : vars) { | 8329 | for (auto& var : vars) { |
8263 | markVarConst(var); | 8330 | markVarConst(var); |
@@ -8281,13 +8348,13 @@ private: | |||
8281 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 8348 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
8282 | auto keyword = _parser.toString(breakLoop); | 8349 | auto keyword = _parser.toString(breakLoop); |
8283 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { | 8350 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { |
8284 | throw std::logic_error(_info.errorMessage(keyword + " is not inside a loop"s, breakLoop)); | 8351 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); |
8285 | } | 8352 | } |
8286 | if (keyword == "break"sv) { | 8353 | if (keyword == "break"sv) { |
8287 | out.push_back(indent() + keyword + nll(breakLoop)); | 8354 | out.push_back(indent() + keyword + nll(breakLoop)); |
8288 | return; | 8355 | return; |
8289 | } | 8356 | } |
8290 | if (_continueVars.empty()) throw std::logic_error(_info.errorMessage("continue is not inside a loop"sv, breakLoop)); | 8357 | if (_continueVars.empty()) throw CompileError("continue is not inside a loop"sv, breakLoop); |
8291 | str_list temp; | 8358 | str_list temp; |
8292 | auto& item = _continueVars.top(); | 8359 | auto& item = _continueVars.top(); |
8293 | if (item.condAssign) { | 8360 | if (item.condAssign) { |
@@ -8308,7 +8375,7 @@ private: | |||
8308 | 8375 | ||
8309 | void transformLabel(Label_t* label, str_list& out) { | 8376 | void transformLabel(Label_t* label, str_list& out) { |
8310 | if (getLuaTarget(label) < 502) { | 8377 | if (getLuaTarget(label) < 502) { |
8311 | throw std::logic_error(_info.errorMessage("label statement is not available when not targeting Lua version 5.2 or higher"sv, label)); | 8378 | throw CompileError("label statement is not available when not targeting Lua version 5.2 or higher"sv, label); |
8312 | } | 8379 | } |
8313 | auto labelStr = _parser.toString(label->label); | 8380 | auto labelStr = _parser.toString(label->label); |
8314 | int currentScope = _gotoScopes.top(); | 8381 | int currentScope = _gotoScopes.top(); |
@@ -8321,7 +8388,7 @@ private: | |||
8321 | } | 8388 | } |
8322 | auto& scope = _labels[currentScope].value(); | 8389 | auto& scope = _labels[currentScope].value(); |
8323 | if (auto it = scope.find(labelStr); it != scope.end()) { | 8390 | if (auto it = scope.find(labelStr); it != scope.end()) { |
8324 | throw std::logic_error(_info.errorMessage("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label)); | 8391 | throw CompileError("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label); |
8325 | } | 8392 | } |
8326 | scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())}; | 8393 | scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())}; |
8327 | out.push_back(indent() + "::"s + labelStr + "::"s + nll(label)); | 8394 | out.push_back(indent() + "::"s + labelStr + "::"s + nll(label)); |
@@ -8329,7 +8396,7 @@ private: | |||
8329 | 8396 | ||
8330 | void transformGoto(Goto_t* gotoNode, str_list& out) { | 8397 | void transformGoto(Goto_t* gotoNode, str_list& out) { |
8331 | if (getLuaTarget(gotoNode) < 502) { | 8398 | if (getLuaTarget(gotoNode) < 502) { |
8332 | throw std::logic_error(_info.errorMessage("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode)); | 8399 | throw CompileError("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode); |
8333 | } | 8400 | } |
8334 | auto labelStr = _parser.toString(gotoNode->label); | 8401 | auto labelStr = _parser.toString(gotoNode->label); |
8335 | gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())}); | 8402 | gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())}); |
@@ -8338,7 +8405,7 @@ private: | |||
8338 | 8405 | ||
8339 | void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { | 8406 | void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { |
8340 | if (_withVars.empty()) { | 8407 | if (_withVars.empty()) { |
8341 | throw std::logic_error(_info.errorMessage("short table appending syntax must be called within a with block"sv, tab)); | 8408 | throw CompileError("short table appending syntax must be called within a with block"sv, tab); |
8342 | } | 8409 | } |
8343 | auto assignment = toAst<ExpListAssign_t>(_withVars.top() + "[]=nil"s, tab); | 8410 | auto assignment = toAst<ExpListAssign_t>(_withVars.top() + "[]=nil"s, tab); |
8344 | assignment->action.set(tab->assign); | 8411 | assignment->action.set(tab->assign); |
@@ -8349,7 +8416,7 @@ private: | |||
8349 | auto x = chainAssign; | 8416 | auto x = chainAssign; |
8350 | auto value = chainAssign->assign->values.front(); | 8417 | auto value = chainAssign->assign->values.front(); |
8351 | if (chainAssign->assign->values.size() != 1) { | 8418 | if (chainAssign->assign->values.size() != 1) { |
8352 | throw std::logic_error(_info.errorMessage("only one right value expected"sv, value)); | 8419 | throw CompileError("only one right value expected"sv, value); |
8353 | } | 8420 | } |
8354 | str_list temp; | 8421 | str_list temp; |
8355 | bool constVal = false; | 8422 | bool constVal = false; |
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h index a5d33cc..860ddfb 100644 --- a/src/yuescript/yue_compiler.h +++ b/src/yuescript/yue_compiler.h | |||
@@ -11,6 +11,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
11 | #include <functional> | 11 | #include <functional> |
12 | #include <list> | 12 | #include <list> |
13 | #include <memory> | 13 | #include <memory> |
14 | #include <optional> | ||
14 | #include <string> | 15 | #include <string> |
15 | #include <string_view> | 16 | #include <string_view> |
16 | #include <tuple> | 17 | #include <tuple> |
@@ -30,7 +31,7 @@ struct YueConfig { | |||
30 | bool reserveLineNumber = true; | 31 | bool reserveLineNumber = true; |
31 | bool useSpaceOverTab = false; | 32 | bool useSpaceOverTab = false; |
32 | bool reserveComment = false; | 33 | bool reserveComment = false; |
33 | 34 | // internal options | |
34 | bool exporting = false; | 35 | bool exporting = false; |
35 | bool profiling = false; | 36 | bool profiling = false; |
36 | int lineOffset = 0; | 37 | int lineOffset = 0; |
@@ -48,11 +49,28 @@ using GlobalVars = std::vector<GlobalVar>; | |||
48 | 49 | ||
49 | struct CompileInfo { | 50 | struct CompileInfo { |
50 | std::string codes; | 51 | std::string codes; |
51 | std::string error; | 52 | struct Error { |
53 | std::string msg; | ||
54 | int line; | ||
55 | int col; | ||
56 | std::string displayMessage; | ||
57 | }; | ||
58 | std::optional<Error> error; | ||
52 | std::unique_ptr<GlobalVars> globals; | 59 | std::unique_ptr<GlobalVars> globals; |
53 | std::unique_ptr<Options> options; | 60 | std::unique_ptr<Options> options; |
54 | double parseTime; | 61 | double parseTime; |
55 | double compileTime; | 62 | double compileTime; |
63 | |||
64 | CompileInfo() { } | ||
65 | CompileInfo( | ||
66 | std::string&& codes, | ||
67 | std::optional<Error>&& error, | ||
68 | std::unique_ptr<GlobalVars>&& globals, | ||
69 | std::unique_ptr<Options>&& options, | ||
70 | double parseTime, | ||
71 | double compileTime); | ||
72 | CompileInfo(CompileInfo&& other); | ||
73 | void operator=(CompileInfo&& other); | ||
56 | }; | 74 | }; |
57 | 75 | ||
58 | class YueCompilerImpl; | 76 | class YueCompilerImpl; |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index d8fdc28..f215ee4 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -30,6 +30,17 @@ std::unordered_set<std::string> Keywords = { | |||
30 | "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords | 30 | "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords |
31 | }; | 31 | }; |
32 | 32 | ||
33 | class ParserError : public std::logic_error { | ||
34 | public: | ||
35 | explicit ParserError(std::string_view msg, const pos* begin) | ||
36 | : std::logic_error(std::string(msg)) | ||
37 | , line(begin->m_line) | ||
38 | , col(begin->m_col) { } | ||
39 | |||
40 | int line; | ||
41 | int col; | ||
42 | }; | ||
43 | |||
33 | // clang-format off | 44 | // clang-format off |
34 | YueParser::YueParser() { | 45 | YueParser::YueParser() { |
35 | plain_space = *set(" \t"); | 46 | plain_space = *set(" \t"); |
@@ -78,7 +89,7 @@ YueParser::YueParser() { | |||
78 | Seperator = true_(); | 89 | Seperator = true_(); |
79 | 90 | ||
80 | empty_block_error = pl::user(true_(), [](const item_t& item) { | 91 | empty_block_error = pl::user(true_(), [](const item_t& item) { |
81 | throw ParserError("must be followed by a statement or an indented block", *item.begin, *item.end); | 92 | throw ParserError("must be followed by a statement or an indented block"sv, item.begin); |
82 | return false; | 93 | return false; |
83 | }); | 94 | }); |
84 | 95 | ||
@@ -489,7 +500,7 @@ YueParser::YueParser() { | |||
489 | st->expLevel++; | 500 | st->expLevel++; |
490 | const int max_exp_level = 100; | 501 | const int max_exp_level = 100; |
491 | if (st->expLevel > max_exp_level) { | 502 | if (st->expLevel > max_exp_level) { |
492 | throw ParserError("nesting expressions exceeds 100 levels", *item.begin, *item.end); | 503 | throw ParserError("nesting expressions exceeds 100 levels"sv, item.begin); |
493 | } | 504 | } |
494 | return true; | 505 | return true; |
495 | }); | 506 | }); |
@@ -658,10 +669,10 @@ YueParser::YueParser() { | |||
658 | }) >> (pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { | 669 | }) >> (pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { |
659 | State* st = reinterpret_cast<State*>(item.user_data); | 670 | State* st = reinterpret_cast<State*>(item.user_data); |
660 | if (st->exportDefault) { | 671 | if (st->exportDefault) { |
661 | throw ParserError("export default has already been declared", *item.begin, *item.end); | 672 | throw ParserError("export default has already been declared"sv, item.begin); |
662 | } | 673 | } |
663 | if (st->exportCount > 1) { | 674 | if (st->exportCount > 1) { |
664 | throw ParserError("there are items already being exported", *item.begin, *item.end); | 675 | throw ParserError("there are items already being exported"sv, item.begin); |
665 | } | 676 | } |
666 | st->exportDefault = true; | 677 | st->exportDefault = true; |
667 | return true; | 678 | return true; |
@@ -669,7 +680,7 @@ YueParser::YueParser() { | |||
669 | | (not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { | 680 | | (not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { |
670 | State* st = reinterpret_cast<State*>(item.user_data); | 681 | State* st = reinterpret_cast<State*>(item.user_data); |
671 | if (st->exportDefault && st->exportCount > 1) { | 682 | if (st->exportDefault && st->exportCount > 1) { |
672 | throw ParserError("can not export any more items when 'export default' is declared", *item.begin, *item.end); | 683 | throw ParserError("can not export any more items when 'export default' is declared"sv, item.begin); |
673 | } | 684 | } |
674 | return true; | 685 | return true; |
675 | }) >> space >> ExpList >> -(space >> Assign)) | 686 | }) >> space >> ExpList >> -(space >> Assign)) |
@@ -762,7 +773,7 @@ YueParser::YueParser() { | |||
762 | ) | arg_table_block; | 773 | ) | arg_table_block; |
763 | 774 | ||
764 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { | 775 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { |
765 | throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses", *item.begin, *item.end); | 776 | throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses"sv, item.begin); |
766 | return false; | 777 | return false; |
767 | }); | 778 | }); |
768 | 779 | ||
@@ -776,12 +787,12 @@ YueParser::YueParser() { | |||
776 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; | 787 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; |
777 | 788 | ||
778 | braces_expression_error = pl::user(true_(), [](const item_t& item) { | 789 | braces_expression_error = pl::user(true_(), [](const item_t& item) { |
779 | throw ParserError("syntax error in brace expression", *item.begin, *item.end); | 790 | throw ParserError("syntax error in brace expression"sv, item.begin); |
780 | return false; | 791 | return false; |
781 | }); | 792 | }); |
782 | 793 | ||
783 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { | 794 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { |
784 | throw ParserError("syntax error in bracket expression", *item.begin, *item.end); | 795 | throw ParserError("syntax error in bracket expression"sv, item.begin); |
785 | return false; | 796 | return false; |
786 | }); | 797 | }); |
787 | 798 | ||
@@ -846,7 +857,7 @@ YueParser::YueParser() { | |||
846 | ) >> and_(line_break); | 857 | ) >> and_(line_break); |
847 | 858 | ||
848 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { | 859 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { |
849 | throw ParserError("unexpected indent", *item.begin, *item.end); | 860 | throw ParserError("unexpected indent"sv, item.begin); |
850 | return false; | 861 | return false; |
851 | }); | 862 | }); |
852 | 863 | ||
@@ -875,7 +886,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
875 | res.codes = std::make_unique<input>(); | 886 | res.codes = std::make_unique<input>(); |
876 | } | 887 | } |
877 | } catch (const std::range_error&) { | 888 | } catch (const std::range_error&) { |
878 | res.error = "invalid text encoding"sv; | 889 | res.error = {"invalid text encoding"s, 1, 1}; |
879 | return res; | 890 | return res; |
880 | } | 891 | } |
881 | error_list errors; | 892 | error_list errors; |
@@ -888,26 +899,22 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
888 | res.exportMacro = state.exportMacro; | 899 | res.exportMacro = state.exportMacro; |
889 | } | 900 | } |
890 | } catch (const ParserError& err) { | 901 | } catch (const ParserError& err) { |
891 | res.error = res.errorMessage(err.what(), &err.loc); | 902 | res.error = {err.what(), err.line, err.col}; |
892 | return res; | 903 | return res; |
893 | } catch (const std::logic_error& err) { | 904 | } catch (const std::logic_error& err) { |
894 | res.error = err.what(); | 905 | res.error = {err.what(), 1, 1}; |
895 | return res; | 906 | return res; |
896 | } | 907 | } |
897 | if (!errors.empty()) { | 908 | if (!errors.empty()) { |
898 | std::ostringstream buf; | 909 | const error& err = errors.front(); |
899 | for (error_list::iterator it = errors.begin(); it != errors.end(); ++it) { | 910 | switch (err.m_type) { |
900 | const error& err = *it; | 911 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: |
901 | switch (err.m_type) { | 912 | res.error = {"syntax error"s, err.m_begin.m_line, err.m_begin.m_col}; |
902 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: | 913 | break; |
903 | buf << res.errorMessage("syntax error"sv, &err); | 914 | case ERROR_TYPE::ERROR_INVALID_EOF: |
904 | break; | 915 | res.error = {"invalid EOF"s, err.m_begin.m_line, err.m_begin.m_col}; |
905 | case ERROR_TYPE::ERROR_INVALID_EOF: | 916 | break; |
906 | buf << res.errorMessage("invalid EOF"sv, &err); | ||
907 | break; | ||
908 | } | ||
909 | } | 917 | } |
910 | res.error = buf.str(); | ||
911 | } | 918 | } |
912 | return res; | 919 | return res; |
913 | } | 920 | } |
@@ -944,9 +951,9 @@ void trim(std::string& str) { | |||
944 | } | 951 | } |
945 | } // namespace Utils | 952 | } // namespace Utils |
946 | 953 | ||
947 | std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { | 954 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol) const { |
948 | const int ASCII = 255; | 955 | const int ASCII = 255; |
949 | int length = loc->m_begin.m_line; | 956 | int length = errLine; |
950 | auto begin = codes->begin(); | 957 | auto begin = codes->begin(); |
951 | auto end = codes->end(); | 958 | auto end = codes->end(); |
952 | int count = 0; | 959 | int count = 0; |
@@ -961,7 +968,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
961 | count++; | 968 | count++; |
962 | } | 969 | } |
963 | } | 970 | } |
964 | int oldCol = loc->m_begin.m_col; | 971 | int oldCol = errCol; |
965 | int col = std::max(0, oldCol - 1); | 972 | int col = std::max(0, oldCol - 1); |
966 | auto it = begin; | 973 | auto it = begin; |
967 | for (int i = 0; i < oldCol && it != end; ++i) { | 974 | for (int i = 0; i < oldCol && it != end; ++i) { |
@@ -977,7 +984,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
977 | } | 984 | } |
978 | Utils::replace(line, "\t"sv, " "sv); | 985 | Utils::replace(line, "\t"sv, " "sv); |
979 | std::ostringstream buf; | 986 | std::ostringstream buf; |
980 | buf << loc->m_begin.m_line << ": "sv << msg << '\n' | 987 | buf << errLine << ": "sv << msg << '\n' |
981 | << line << '\n' | 988 | << line << '\n' |
982 | << std::string(col, ' ') << "^"sv; | 989 | << std::string(col, ' ') << "^"sv; |
983 | return buf.str(); | 990 | return buf.str(); |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index cce6741..31134e1 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -11,6 +11,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
11 | #include <algorithm> | 11 | #include <algorithm> |
12 | #include <list> | 12 | #include <list> |
13 | #include <memory> | 13 | #include <memory> |
14 | #include <optional> | ||
14 | #include <sstream> | 15 | #include <sstream> |
15 | #include <stack> | 16 | #include <stack> |
16 | #include <string> | 17 | #include <string> |
@@ -26,25 +27,18 @@ using namespace std::string_literals; | |||
26 | using namespace parserlib; | 27 | using namespace parserlib; |
27 | 28 | ||
28 | struct ParseInfo { | 29 | struct ParseInfo { |
30 | struct Error { | ||
31 | std::string msg; | ||
32 | int line; | ||
33 | int col; | ||
34 | }; | ||
29 | ast_ptr<false, ast_node> node; | 35 | ast_ptr<false, ast_node> node; |
30 | std::string error; | 36 | std::optional<Error> error; |
31 | std::unique_ptr<input> codes; | 37 | std::unique_ptr<input> codes; |
32 | bool exportDefault = false; | 38 | bool exportDefault = false; |
33 | bool exportMacro = false; | 39 | bool exportMacro = false; |
34 | std::string moduleName; | 40 | std::string moduleName; |
35 | std::string errorMessage(std::string_view msg, const input_range* loc) const; | 41 | std::string errorMessage(std::string_view msg, int errLine, int errCol) const; |
36 | }; | ||
37 | |||
38 | class ParserError : public std::logic_error { | ||
39 | public: | ||
40 | explicit ParserError(const std::string& msg, const pos& begin, const pos& end) | ||
41 | : std::logic_error(msg) | ||
42 | , loc(begin, end) { } | ||
43 | |||
44 | explicit ParserError(const char* msg, const pos& begin, const pos& end) | ||
45 | : std::logic_error(msg) | ||
46 | , loc(begin, end) { } | ||
47 | input_range loc; | ||
48 | }; | 42 | }; |
49 | 43 | ||
50 | template <typename T> | 44 | template <typename T> |
@@ -53,21 +47,21 @@ struct identity { | |||
53 | }; | 47 | }; |
54 | 48 | ||
55 | #ifdef NDEBUG | 49 | #ifdef NDEBUG |
56 | #define NONE_AST_RULE(type) \ | 50 | #define NONE_AST_RULE(type) \ |
57 | rule type; | 51 | rule type; |
58 | 52 | ||
59 | #define AST_RULE(type) \ | 53 | #define AST_RULE(type) \ |
60 | rule type; \ | 54 | rule type; \ |
61 | ast<type##_t> type##_impl = type; \ | 55 | ast<type##_t> type##_impl = type; \ |
62 | inline rule& getRule(identity<type##_t>) { return type; } | 56 | inline rule& getRule(identity<type##_t>) { return type; } |
63 | #else // NDEBUG | 57 | #else // NDEBUG |
64 | #define NONE_AST_RULE(type) \ | 58 | #define NONE_AST_RULE(type) \ |
65 | rule type{#type, rule::initTag{}}; | 59 | rule type{#type, rule::initTag{}}; |
66 | 60 | ||
67 | #define AST_RULE(type) \ | 61 | #define AST_RULE(type) \ |
68 | rule type{#type, rule::initTag{}}; \ | 62 | rule type{#type, rule::initTag{}}; \ |
69 | ast<type##_t> type##_impl = type; \ | 63 | ast<type##_t> type##_impl = type; \ |
70 | inline rule& getRule(identity<type##_t>) { return type; } | 64 | inline rule& getRule(identity<type##_t>) { return type; } |
71 | #endif // NDEBUG | 65 | #endif // NDEBUG |
72 | 66 | ||
73 | extern std::unordered_set<std::string> LuaKeywords; | 67 | extern std::unordered_set<std::string> LuaKeywords; |
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp index b5043e0..ef427ad 100644 --- a/src/yuescript/yuescript.cpp +++ b/src/yuescript/yuescript.cpp | |||
@@ -62,43 +62,55 @@ static int init_stacktraceplus(lua_State* L) { | |||
62 | return 1; | 62 | return 1; |
63 | } | 63 | } |
64 | 64 | ||
65 | static yue::YueConfig get_config(lua_State* L) { | ||
66 | yue::YueConfig config; | ||
67 | lua_pushliteral(L, "lint_global"); | ||
68 | lua_gettable(L, -2); | ||
69 | if (lua_isboolean(L, -1) != 0) { | ||
70 | config.lintGlobalVariable = lua_toboolean(L, -1) != 0; | ||
71 | } | ||
72 | lua_pop(L, 1); | ||
73 | lua_pushliteral(L, "implicit_return_root"); | ||
74 | lua_gettable(L, -2); | ||
75 | if (lua_isboolean(L, -1) != 0) { | ||
76 | config.implicitReturnRoot = lua_toboolean(L, -1) != 0; | ||
77 | } | ||
78 | lua_pop(L, 1); | ||
79 | lua_pushliteral(L, "reserve_line_number"); | ||
80 | lua_gettable(L, -2); | ||
81 | if (lua_isboolean(L, -1) != 0) { | ||
82 | config.reserveLineNumber = lua_toboolean(L, -1) != 0; | ||
83 | } | ||
84 | lua_pop(L, 1); | ||
85 | lua_pushliteral(L, "reserve_comment"); | ||
86 | lua_gettable(L, -2); | ||
87 | if (lua_isboolean(L, -1) != 0) { | ||
88 | config.reserveComment = lua_toboolean(L, -1) != 0; | ||
89 | } | ||
90 | lua_pop(L, 1); | ||
91 | lua_pushliteral(L, "space_over_tab"); | ||
92 | lua_gettable(L, -2); | ||
93 | if (lua_isboolean(L, -1) != 0) { | ||
94 | config.useSpaceOverTab = lua_toboolean(L, -1) != 0; | ||
95 | } | ||
96 | lua_pop(L, 1); | ||
97 | lua_pushliteral(L, "target"); | ||
98 | lua_gettable(L, -2); | ||
99 | if (lua_isstring(L, -1) != 0) { | ||
100 | config.options["target"] = lua_tostring(L, -1); | ||
101 | } | ||
102 | lua_pop(L, 1); | ||
103 | return config; | ||
104 | } | ||
105 | |||
65 | static int yuetolua(lua_State* L) { | 106 | static int yuetolua(lua_State* L) { |
66 | size_t size = 0; | 107 | size_t len = 0; |
67 | const char* input = luaL_checklstring(L, 1, &size); | 108 | std::string codes(luaL_checklstring(L, 1, &len), len); |
68 | yue::YueConfig config; | 109 | yue::YueConfig config; |
69 | bool sameModule = false; | 110 | bool sameModule = false; |
70 | if (lua_gettop(L) == 2) { | 111 | if (lua_gettop(L) == 2) { |
71 | luaL_checktype(L, 2, LUA_TTABLE); | 112 | luaL_checktype(L, 2, LUA_TTABLE); |
72 | lua_pushliteral(L, "lint_global"); | 113 | config = get_config(L); |
73 | lua_gettable(L, -2); | ||
74 | if (lua_isboolean(L, -1) != 0) { | ||
75 | config.lintGlobalVariable = lua_toboolean(L, -1) != 0; | ||
76 | } | ||
77 | lua_pop(L, 1); | ||
78 | lua_pushliteral(L, "implicit_return_root"); | ||
79 | lua_gettable(L, -2); | ||
80 | if (lua_isboolean(L, -1) != 0) { | ||
81 | config.implicitReturnRoot = lua_toboolean(L, -1) != 0; | ||
82 | } | ||
83 | lua_pop(L, 1); | ||
84 | lua_pushliteral(L, "reserve_line_number"); | ||
85 | lua_gettable(L, -2); | ||
86 | if (lua_isboolean(L, -1) != 0) { | ||
87 | config.reserveLineNumber = lua_toboolean(L, -1) != 0; | ||
88 | } | ||
89 | lua_pop(L, 1); | ||
90 | lua_pushliteral(L, "reserve_comment"); | ||
91 | lua_gettable(L, -2); | ||
92 | if (lua_isboolean(L, -1) != 0) { | ||
93 | config.reserveComment = lua_toboolean(L, -1) != 0; | ||
94 | } | ||
95 | lua_pop(L, 1); | ||
96 | lua_pushliteral(L, "space_over_tab"); | ||
97 | lua_gettable(L, -2); | ||
98 | if (lua_isboolean(L, -1) != 0) { | ||
99 | config.useSpaceOverTab = lua_toboolean(L, -1) != 0; | ||
100 | } | ||
101 | lua_pop(L, 1); | ||
102 | lua_pushliteral(L, "same_module"); | 114 | lua_pushliteral(L, "same_module"); |
103 | lua_gettable(L, -2); | 115 | lua_gettable(L, -2); |
104 | if (lua_isboolean(L, -1) != 0) { | 116 | if (lua_isboolean(L, -1) != 0) { |
@@ -117,24 +129,18 @@ static int yuetolua(lua_State* L) { | |||
117 | config.module = lua_tostring(L, -1); | 129 | config.module = lua_tostring(L, -1); |
118 | } | 130 | } |
119 | lua_pop(L, 1); | 131 | lua_pop(L, 1); |
120 | lua_pushliteral(L, "target"); | ||
121 | lua_gettable(L, -2); | ||
122 | if (lua_isstring(L, -1) != 0) { | ||
123 | config.options["target"] = lua_tostring(L, -1); | ||
124 | } | ||
125 | lua_pop(L, 1); | ||
126 | } | 132 | } |
127 | std::string s(input, size); | 133 | auto result = yue::YueCompiler(L, nullptr, sameModule).compile(codes, config); |
128 | auto result = yue::YueCompiler(L, nullptr, sameModule).compile(s, config); | 134 | if (result.error) { |
129 | if (result.codes.empty() && !result.error.empty()) { | ||
130 | lua_pushnil(L); | 135 | lua_pushnil(L); |
131 | } else { | 136 | } else { |
132 | lua_pushlstring(L, result.codes.c_str(), result.codes.size()); | 137 | lua_pushlstring(L, result.codes.c_str(), result.codes.size()); |
133 | } | 138 | } |
134 | if (result.error.empty()) { | 139 | if (result.error) { |
135 | lua_pushnil(L); | 140 | const auto& msg = result.error.value().displayMessage; |
141 | lua_pushlstring(L, msg.c_str(), msg.size()); | ||
136 | } else { | 142 | } else { |
137 | lua_pushlstring(L, result.error.c_str(), result.error.size()); | 143 | lua_pushnil(L); |
138 | } | 144 | } |
139 | if (result.globals) { | 145 | if (result.globals) { |
140 | lua_createtable(L, static_cast<int>(result.globals->size()), 0); | 146 | lua_createtable(L, static_cast<int>(result.globals->size()), 0); |
@@ -156,6 +162,57 @@ static int yuetolua(lua_State* L) { | |||
156 | return 3; | 162 | return 3; |
157 | } | 163 | } |
158 | 164 | ||
165 | static int yuecheck(lua_State* L) { | ||
166 | size_t len = 0; | ||
167 | std::string codes{luaL_checklstring(L, 1, &len), len}; | ||
168 | yue::YueConfig config; | ||
169 | config.lintGlobalVariable = true; | ||
170 | if (lua_gettop(L) == 2) { | ||
171 | luaL_checktype(L, 2, LUA_TTABLE); | ||
172 | config = get_config(L); | ||
173 | } | ||
174 | auto result = yue::YueCompiler(L).compile(codes, config); | ||
175 | lua_createtable(L, 0, 0); | ||
176 | int i = 0; | ||
177 | if (result.error) { | ||
178 | const auto& error = result.error.value(); | ||
179 | lua_createtable(L, 4, 0); | ||
180 | lua_pushliteral(L, "error"); | ||
181 | lua_rawseti(L, -2, 1); | ||
182 | lua_pushlstring(L, error.msg.c_str(), error.msg.length()); | ||
183 | lua_rawseti(L, -2, 2); | ||
184 | lua_pushinteger(L, error.line); | ||
185 | lua_rawseti(L, -2, 3); | ||
186 | lua_pushinteger(L, error.col); | ||
187 | lua_rawseti(L, -2, 4); | ||
188 | lua_rawseti(L, -2, ++i); | ||
189 | } | ||
190 | if (result.globals) { | ||
191 | for (const auto& global : *result.globals) { | ||
192 | lua_createtable(L, 4, 0); | ||
193 | lua_pushliteral(L, "global"); | ||
194 | lua_rawseti(L, -2, 1); | ||
195 | lua_pushlstring(L, global.name.c_str(), global.name.length()); | ||
196 | lua_rawseti(L, -2, 2); | ||
197 | lua_pushinteger(L, global.line); | ||
198 | lua_rawseti(L, -2, 3); | ||
199 | lua_pushinteger(L, global.col); | ||
200 | lua_rawseti(L, -2, 4); | ||
201 | lua_rawseti(L, -2, ++i); | ||
202 | } | ||
203 | } | ||
204 | if (result.error) { | ||
205 | lua_pushboolean(L, 0); | ||
206 | lua_insert(L, -2); | ||
207 | return 2; | ||
208 | } else { | ||
209 | lua_pushboolean(L, 1); | ||
210 | lua_insert(L, -2); | ||
211 | lua_pushlstring(L, result.codes.c_str(), result.codes.length()); | ||
212 | return 3; | ||
213 | } | ||
214 | } | ||
215 | |||
159 | struct yue_stack { | 216 | struct yue_stack { |
160 | int continuation; | 217 | int continuation; |
161 | yue::ast_node* node; | 218 | yue::ast_node* node; |
@@ -174,7 +231,7 @@ static int yuetoast(lua_State* L) { | |||
174 | } | 231 | } |
175 | yue::YueParser parser; | 232 | yue::YueParser parser; |
176 | auto info = parser.parse<yue::File_t>({input, size}); | 233 | auto info = parser.parse<yue::File_t>({input, size}); |
177 | if (info.node) { | 234 | if (!info.error) { |
178 | lua_createtable(L, 0, 0); | 235 | lua_createtable(L, 0, 0); |
179 | int tableIndex = lua_gettop(L); | 236 | int tableIndex = lua_gettop(L); |
180 | lua_createtable(L, 0, 0); | 237 | lua_createtable(L, 0, 0); |
@@ -300,7 +357,8 @@ static int yuetoast(lua_State* L) { | |||
300 | return 1; | 357 | return 1; |
301 | } else { | 358 | } else { |
302 | lua_pushnil(L); | 359 | lua_pushnil(L); |
303 | lua_pushlstring(L, info.error.c_str(), info.error.length()); | 360 | const auto& msg = info.error.value().msg; |
361 | lua_pushlstring(L, msg.c_str(), msg.length()); | ||
304 | return 2; | 362 | return 2; |
305 | } | 363 | } |
306 | } | 364 | } |
@@ -308,6 +366,7 @@ static int yuetoast(lua_State* L) { | |||
308 | static const luaL_Reg yuelib[] = { | 366 | static const luaL_Reg yuelib[] = { |
309 | {"to_lua", yuetolua}, | 367 | {"to_lua", yuetolua}, |
310 | {"to_ast", yuetoast}, | 368 | {"to_ast", yuetoast}, |
369 | {"check", yuecheck}, | ||
311 | {"version", nullptr}, | 370 | {"version", nullptr}, |
312 | {"options", nullptr}, | 371 | {"options", nullptr}, |
313 | {"load_stacktraceplus", nullptr}, | 372 | {"load_stacktraceplus", nullptr}, |
diff --git a/src/yuescript/yuescript.h b/src/yuescript/yuescript.h index 2d2d660..51622f8 100644 --- a/src/yuescript/yuescript.h +++ b/src/yuescript/yuescript.h | |||
@@ -56,7 +56,12 @@ end | |||
56 | local function find_modulepath(name) | 56 | local function find_modulepath(name) |
57 | local suffix = "." .. yue.options.extension | 57 | local suffix = "." .. yue.options.extension |
58 | local dirsep = yue.options.dirsep | 58 | local dirsep = yue.options.dirsep |
59 | local name_path = name:match("[\\/]") and name or name:gsub("%.", dirsep) | 59 | local name_path |
60 | if name:match("[\\/]") then | ||
61 | name_path = name:gsub("%" .. suffix .. "$", "") | ||
62 | else | ||
63 | name_path = name:gsub("%.", dirsep) | ||
64 | end | ||
60 | local file_exist, file_path | 65 | local file_exist, file_path |
61 | local tried = {} | 66 | local tried = {} |
62 | local paths = {package.path, yue.options.path} | 67 | local paths = {package.path, yue.options.path} |