diff options
author | Li Jin <dragon-fly@qq.com> | 2022-07-24 22:13:08 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-07-24 22:13:08 +0800 |
commit | 303834e1b1e6cd9cae64b66c2ae44dcd7185238f (patch) | |
tree | 519f6a1debcc5791d35e06dc5cbb1ce22f9cfd31 | |
parent | eb367126bf3a4f5b0e51ccef93b7c7136bea170e (diff) | |
download | yuescript-303834e1b1e6cd9cae64b66c2ae44dcd7185238f.tar.gz yuescript-303834e1b1e6cd9cae64b66c2ae44dcd7185238f.tar.bz2 yuescript-303834e1b1e6cd9cae64b66c2ae44dcd7185238f.zip |
add option --target=5.1 to generate Lua 5.1 compatible codes. add const destructure. make import item const by default.
-rw-r--r-- | makefile | 4 | ||||
-rw-r--r-- | spec/inputs/destructure.yue | 5 | ||||
-rw-r--r-- | spec/inputs/export.yue | 4 | ||||
-rw-r--r-- | spec/inputs/import.yue | 2 | ||||
-rw-r--r-- | spec/inputs/macro.yue | 2 | ||||
-rw-r--r-- | spec/inputs/metatable.yue | 2 | ||||
-rw-r--r-- | spec/inputs/syntax.yue | 10 | ||||
-rw-r--r-- | spec/inputs/tables.yue | 8 | ||||
-rw-r--r-- | spec/inputs/with.yue | 2 | ||||
-rw-r--r-- | spec/outputs/destructure.lua | 25 | ||||
-rw-r--r-- | spec/outputs/export.lua | 10 | ||||
-rw-r--r-- | spec/outputs/import.lua | 2 | ||||
-rw-r--r-- | spec/outputs/macro.lua | 3 | ||||
-rw-r--r-- | spec/outputs/metatable.lua | 1 | ||||
-rw-r--r-- | spec/outputs/syntax.lua | 10 | ||||
-rw-r--r-- | spec/outputs/tables.lua | 8 | ||||
-rw-r--r-- | spec/outputs/with.lua | 2 | ||||
-rw-r--r-- | src/yue.cpp | 39 | ||||
-rwxr-xr-x | src/yuescript/yue_ast.h | 24 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 232 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.cpp | 42 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.h | 8 | ||||
-rw-r--r-- | src/yuescript/yuescript.cpp | 10 |
23 files changed, 321 insertions, 134 deletions
@@ -266,7 +266,7 @@ test: release | |||
266 | @mkdir -p $(TEST_OUTPUT) | 266 | @mkdir -p $(TEST_OUTPUT) |
267 | @echo "Compiling Yuescript codes..." | 267 | @echo "Compiling Yuescript codes..." |
268 | @$(START_TIME) | 268 | @$(START_TIME) |
269 | @./$(BIN_NAME) $(TEST_INPUT) -t $(TEST_OUTPUT) -tl_enabled | 269 | @./$(BIN_NAME) $(TEST_INPUT) -t $(TEST_OUTPUT) --tl_enabled |
270 | @./$(BIN_NAME) $(TEST_INPUT)/teal-lang.yue -o $(TEST_OUTPUT)/teal-lang.lua | 270 | @./$(BIN_NAME) $(TEST_INPUT)/teal-lang.yue -o $(TEST_OUTPUT)/teal-lang.lua |
271 | @echo -en "Compile time: " | 271 | @echo -en "Compile time: " |
272 | @$(END_TIME) | 272 | @$(END_TIME) |
@@ -279,7 +279,7 @@ test: release | |||
279 | gen: release | 279 | gen: release |
280 | @echo "Compiling Yuescript codes..." | 280 | @echo "Compiling Yuescript codes..." |
281 | @$(START_TIME) | 281 | @$(START_TIME) |
282 | @./$(BIN_NAME) $(TEST_INPUT) -t $(GEN_OUTPUT) -tl_enabled | 282 | @./$(BIN_NAME) $(TEST_INPUT) -t $(GEN_OUTPUT) --tl_enabled |
283 | @./$(BIN_NAME) $(TEST_INPUT)/teal-lang.yue -o $(GEN_OUTPUT)/teal-lang.lua | 283 | @./$(BIN_NAME) $(TEST_INPUT)/teal-lang.yue -o $(GEN_OUTPUT)/teal-lang.lua |
284 | @echo -en "Compile time: " | 284 | @echo -en "Compile time: " |
285 | @$(END_TIME) | 285 | @$(END_TIME) |
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 3007adf..24282c0 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
@@ -11,7 +11,7 @@ do | |||
11 | 11 | ||
12 | {:a,:b,:c,:d} = yeah | 12 | {:a,:b,:c,:d} = yeah |
13 | 13 | ||
14 | {a} = one, two | 14 | {a}, b = one, two |
15 | {b}, c = one | 15 | {b}, c = one |
16 | {d}, e = one, two | 16 | {d}, e = one, two |
17 | 17 | ||
@@ -184,3 +184,6 @@ do | |||
184 | do | 184 | do |
185 | {x: a.b = 1, y: a.c = 2} = x.x.x | 185 | {x: a.b = 1, y: a.c = 2} = x.x.x |
186 | 186 | ||
187 | do | ||
188 | const :width, :height = View.size | ||
189 | const {:x = 0.0, :y = 0.0} = point | ||
diff --git a/spec/inputs/export.yue b/spec/inputs/export.yue index 9113508..15ffbcb 100644 --- a/spec/inputs/export.yue +++ b/spec/inputs/export.yue | |||
@@ -55,7 +55,7 @@ f switch a | |||
55 | f [i for i = 1,10] | 55 | f [i for i = 1,10] |
56 | f for i = 1,10 do i | 56 | f for i = 1,10 do i |
57 | f {k,v for k,v in pairs tb} | 57 | f {k,v for k,v in pairs tb} |
58 | f for k,v in pairs tb do k,v | 58 | f for k,v in pairs tb do {k,v} |
59 | f while a do true | 59 | f while a do true |
60 | f with a | 60 | f with a |
61 | .b = 123 | 61 | .b = 123 |
@@ -70,7 +70,7 @@ _ = "#{switch a | |||
70 | _ = "#{[i for i = 1,10]}" | 70 | _ = "#{[i for i = 1,10]}" |
71 | _ = "#{for i = 1,10 do i}" | 71 | _ = "#{for i = 1,10 do i}" |
72 | _ = "#{{k,v for k,v in pairs tb}}" | 72 | _ = "#{{k,v for k,v in pairs tb}}" |
73 | _ = "#{for k,v in pairs tb do k,v}" | 73 | _ = "#{for k,v in pairs tb do {k,v}}" |
74 | _ = "#{while a do true}" | 74 | _ = "#{while a do true}" |
75 | _ = "#{with a | 75 | _ = "#{with a |
76 | .b = 123}" | 76 | .b = 123}" |
diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index 8e82a01..e206d04 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue | |||
@@ -70,7 +70,7 @@ do | |||
70 | 70 | ||
71 | do | 71 | do |
72 | import "m" as {a#: b} | 72 | import "m" as {a#: b} |
73 | import "m" as {e: f, a#: b} | 73 | import "m" as {e: f, a#: c} |
74 | import "m" as {c: d} | 74 | import "m" as {c: d} |
75 | import "m" as {g, {h#: i}} | 75 | import "m" as {g, {h#: i}} |
76 | 76 | ||
diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 7bbb06d..3c89c1c 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue | |||
@@ -279,7 +279,7 @@ do | |||
279 | 279 | ||
280 | macro skip = -> "while false do break" | 280 | macro skip = -> "while false do break" |
281 | 281 | ||
282 | _ = -> | 282 | _1 = -> |
283 | print 1 | 283 | print 1 |
284 | <- $skip | 284 | <- $skip |
285 | print 2 | 285 | print 2 |
diff --git a/spec/inputs/metatable.yue b/spec/inputs/metatable.yue index ed68a17..7e9b4f2 100644 --- a/spec/inputs/metatable.yue +++ b/spec/inputs/metatable.yue | |||
@@ -23,7 +23,7 @@ do | |||
23 | = 123, a.b.c, func! | 23 | = 123, a.b.c, func! |
24 | 24 | ||
25 | x.abc, a.b.# = 123, {} | 25 | x.abc, a.b.# = 123, {} |
26 | func!.# = mt, extra | 26 | func!.# = mt --, extra |
27 | a, b.c.#, d, e = 1, mt, "abc" | 27 | a, b.c.#, d, e = 1, mt, "abc" |
28 | 28 | ||
29 | is_same = a.#.__index == a.index# | 29 | is_same = a.#.__index == a.index# |
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index f212bec..d18bd0e 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
@@ -71,10 +71,10 @@ _ = something[======[hey]======] * 2 | |||
71 | _ = something[ [======[hey]======] ] * 2 | 71 | _ = something[ [======[hey]======] ] * 2 |
72 | 72 | ||
73 | 73 | ||
74 | _ = something'else', 2 | 74 | _, _ = something'else', 2 |
75 | _ = something"else", 2 | 75 | _, _ = something"else", 2 |
76 | _ = something[[else]], 2 | 76 | _, _ = something[[else]], 2 |
77 | _ = something[ [[else]] ], 2 | 77 | _, _ = something[ [[else]] ], 2 |
78 | 78 | ||
79 | something 'else', 2 | 79 | something 'else', 2 |
80 | something "else", 2 | 80 | something "else", 2 |
@@ -157,7 +157,7 @@ y = #"hello" | |||
157 | 157 | ||
158 | x = #{#{},#{1},#{1,2}} | 158 | x = #{#{},#{1},#{1,2}} |
159 | 159 | ||
160 | _ = hello, world | 160 | _, _ = hello, world |
161 | 161 | ||
162 | something\hello(what) a,b | 162 | something\hello(what) a,b |
163 | something\hello what | 163 | something\hello what |
diff --git a/spec/inputs/tables.yue b/spec/inputs/tables.yue index e1b9e1d..0b5af46 100644 --- a/spec/inputs/tables.yue +++ b/spec/inputs/tables.yue | |||
@@ -152,12 +152,12 @@ k = { "hello": 'world', "hat": "zat" } | |||
152 | please "hello": "world" | 152 | please "hello": "world" |
153 | k = "hello": "world", "one": "zone" | 153 | k = "hello": "world", "one": "zone" |
154 | 154 | ||
155 | f = "one", "two": three, "four" | 155 | f1, f2, f3 = "one", "two": three, "four" |
156 | f = "two": three, "four" | 156 | f1, f2 = "two": three, "four" |
157 | f = { "one", "two": three, "four" } | 157 | f1 = { "one", "two": three, "four" } |
158 | 158 | ||
159 | 159 | ||
160 | j = "one", "two": three, "four": five, 6, 7 | 160 | j1, j2, j3, j4 = "one", "two": three, "four": five, 6, 7 |
161 | 161 | ||
162 | heroine = | 162 | heroine = |
163 | name: "Christina" | 163 | name: "Christina" |
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue index 6f3e3ba..5da0980 100644 --- a/spec/inputs/with.yue +++ b/spec/inputs/with.yue | |||
@@ -45,7 +45,7 @@ do | |||
45 | -- | 45 | -- |
46 | 46 | ||
47 | do | 47 | do |
48 | with a, b -- b is lost | 48 | with a -- only one value allowed |
49 | print .world | 49 | print .world |
50 | 50 | ||
51 | mod = with _M = {} | 51 | mod = with _M = {} |
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 2fe4ba9..59ee358 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
@@ -26,7 +26,7 @@ do | |||
26 | local _obj_0 = yeah | 26 | local _obj_0 = yeah |
27 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0.c, _obj_0.d | 27 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0.c, _obj_0.d |
28 | end | 28 | end |
29 | local _ = two | 29 | b = two |
30 | a = one[1] | 30 | a = one[1] |
31 | c = nil | 31 | c = nil |
32 | b = one[1] | 32 | b = one[1] |
@@ -56,7 +56,10 @@ do | |||
56 | end | 56 | end |
57 | do | 57 | do |
58 | a = tbl | 58 | a = tbl |
59 | b, c = _.b, _.c | 59 | do |
60 | local _obj_0 = _ | ||
61 | b, c = _obj_0.b, _obj_0.c | ||
62 | end | ||
60 | end | 63 | end |
61 | do | 64 | do |
62 | b = _ | 65 | b = _ |
@@ -386,3 +389,21 @@ do | |||
386 | a.c = _tmp_1 | 389 | a.c = _tmp_1 |
387 | end | 390 | end |
388 | end | 391 | end |
392 | do | ||
393 | local width, height | ||
394 | do | ||
395 | local _obj_0 = View.size | ||
396 | width, height = _obj_0.width, _obj_0.height | ||
397 | end | ||
398 | local x, y | ||
399 | do | ||
400 | local _obj_0 = point | ||
401 | x, y = _obj_0.x, _obj_0.y | ||
402 | if x == nil then | ||
403 | x = 0.0 | ||
404 | end | ||
405 | if y == nil then | ||
406 | y = 0.0 | ||
407 | end | ||
408 | end | ||
409 | end | ||
diff --git a/spec/outputs/export.lua b/spec/outputs/export.lua index 84e5424..962f18c 100644 --- a/spec/outputs/export.lua +++ b/spec/outputs/export.lua | |||
@@ -134,7 +134,10 @@ f((function() | |||
134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
135 | local _len_0 = 1 | 135 | local _len_0 = 1 |
136 | for k, v in pairs(tb) do | 136 | for k, v in pairs(tb) do |
137 | _accum_0[_len_0] = k, v | 137 | _accum_0[_len_0] = { |
138 | k, | ||
139 | v | ||
140 | } | ||
138 | _len_0 = _len_0 + 1 | 141 | _len_0 = _len_0 + 1 |
139 | end | 142 | end |
140 | return _accum_0 | 143 | return _accum_0 |
@@ -232,7 +235,10 @@ _ = tostring((function() | |||
232 | local _accum_0 = { } | 235 | local _accum_0 = { } |
233 | local _len_0 = 1 | 236 | local _len_0 = 1 |
234 | for k, v in pairs(tb) do | 237 | for k, v in pairs(tb) do |
235 | _accum_0[_len_0] = k, v | 238 | _accum_0[_len_0] = { |
239 | k, | ||
240 | v | ||
241 | } | ||
236 | _len_0 = _len_0 + 1 | 242 | _len_0 = _len_0 + 1 |
237 | end | 243 | end |
238 | return _accum_0 | 244 | return _accum_0 |
diff --git a/spec/outputs/import.lua b/spec/outputs/import.lua index 65e703f..6979e47 100644 --- a/spec/outputs/import.lua +++ b/spec/outputs/import.lua | |||
@@ -94,7 +94,7 @@ do | |||
94 | b = getmetatable(require("m")).__a | 94 | b = getmetatable(require("m")).__a |
95 | local _obj_0 = require("m") | 95 | local _obj_0 = require("m") |
96 | local f = _obj_0.e | 96 | local f = _obj_0.e |
97 | b = getmetatable(_obj_0).__a | 97 | c = getmetatable(_obj_0).__a |
98 | local d = require("m").c | 98 | local d = require("m").c |
99 | local g, i | 99 | local g, i |
100 | do | 100 | do |
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index c19b2d7..fbc1d48 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua | |||
@@ -282,7 +282,8 @@ print("current line: " .. tostring(268)); | |||
282 | do | 282 | do |
283 | print(1) | 283 | print(1) |
284 | end | 284 | end |
285 | _ = function() | 285 | local _1 |
286 | _1 = function() | ||
286 | print(1) | 287 | print(1) |
287 | local _accum_0 = { } | 288 | local _accum_0 = { } |
288 | local _len_0 = 1 | 289 | local _len_0 = 1 |
diff --git a/spec/outputs/metatable.lua b/spec/outputs/metatable.lua index 935202c..2d72e1d 100644 --- a/spec/outputs/metatable.lua +++ b/spec/outputs/metatable.lua | |||
@@ -65,7 +65,6 @@ end | |||
65 | setmetatable(a.b, { }) | 65 | setmetatable(a.b, { }) |
66 | x.abc = 123 | 66 | x.abc = 123 |
67 | setmetatable(func(), mt) | 67 | setmetatable(func(), mt) |
68 | local _ = extra | ||
69 | setmetatable(b.c, mt) | 68 | setmetatable(b.c, mt) |
70 | a, d, e = 1, "abc" | 69 | a, d, e = 1, "abc" |
71 | local is_same = getmetatable(a).__index == getmetatable(a).__index | 70 | local is_same = getmetatable(a).__index == getmetatable(a).__index |
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index 24b78c6..a4cb8e2 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua | |||
@@ -56,10 +56,10 @@ something("else") | |||
56 | _ = something([[hey]]) * 2 | 56 | _ = something([[hey]]) * 2 |
57 | _ = something([======[hey]======]) * 2 | 57 | _ = something([======[hey]======]) * 2 |
58 | _ = something[ [======[hey]======]] * 2 | 58 | _ = something[ [======[hey]======]] * 2 |
59 | _ = something('else'), 2 | 59 | _, _ = something('else'), 2 |
60 | _ = something("else"), 2 | 60 | _, _ = something("else"), 2 |
61 | _ = something([[else]]), 2 | 61 | _, _ = something([[else]]), 2 |
62 | _ = something[ [[else]]], 2 | 62 | _, _ = something[ [[else]]], 2 |
63 | something('else', 2) | 63 | something('else', 2) |
64 | something("else", 2) | 64 | something("else", 2) |
65 | something([[else]], 2) | 65 | something([[else]], 2) |
@@ -165,7 +165,7 @@ x = #{ | |||
165 | 2 | 165 | 2 |
166 | } | 166 | } |
167 | } | 167 | } |
168 | _ = hello, world | 168 | _, _ = hello, world |
169 | something:hello(what)(a, b) | 169 | something:hello(what)(a, b) |
170 | something:hello(what) | 170 | something:hello(what) |
171 | something.hello:world(a, b) | 171 | something.hello:world(a, b) |
diff --git a/spec/outputs/tables.lua b/spec/outputs/tables.lua index 1d28a43..e9df1c4 100644 --- a/spec/outputs/tables.lua +++ b/spec/outputs/tables.lua | |||
@@ -187,18 +187,18 @@ k = { | |||
187 | ["hello"] = "world", | 187 | ["hello"] = "world", |
188 | ["one"] = "zone" | 188 | ["one"] = "zone" |
189 | } | 189 | } |
190 | local f = "one", { | 190 | local f1, f2, f3 = "one", { |
191 | ["two"] = three | 191 | ["two"] = three |
192 | }, "four" | 192 | }, "four" |
193 | f = { | 193 | f1, f2 = { |
194 | ["two"] = three | 194 | ["two"] = three |
195 | }, "four" | 195 | }, "four" |
196 | f = { | 196 | f1 = { |
197 | "one", | 197 | "one", |
198 | ["two"] = three, | 198 | ["two"] = three, |
199 | "four" | 199 | "four" |
200 | } | 200 | } |
201 | local j = "one", { | 201 | local j1, j2, j3, j4 = "one", { |
202 | ["two"] = three, | 202 | ["two"] = three, |
203 | ["four"] = five | 203 | ["four"] = five |
204 | }, 6, 7 | 204 | }, 6, 7 |
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua index 9dcaca3..304d26e 100644 --- a/spec/outputs/with.lua +++ b/spec/outputs/with.lua | |||
@@ -54,7 +54,7 @@ do | |||
54 | end | 54 | end |
55 | do | 55 | do |
56 | do | 56 | do |
57 | local _with_0 = a, b | 57 | local _with_0 = a |
58 | print(_with_0.world) | 58 | print(_with_0.world) |
59 | end | 59 | end |
60 | local mod | 60 | local mod |
diff --git a/src/yue.cpp b/src/yue.cpp index 3e30c70..cb27db8 100644 --- a/src/yue.cpp +++ b/src/yue.cpp | |||
@@ -21,6 +21,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
21 | #include <string_view> | 21 | #include <string_view> |
22 | #include <memory> | 22 | #include <memory> |
23 | using namespace std::string_view_literals; | 23 | using namespace std::string_view_literals; |
24 | using namespace std::string_literals; | ||
24 | #include "ghc/fs_std.hpp" | 25 | #include "ghc/fs_std.hpp" |
25 | #include "linenoise.hpp" | 26 | #include "linenoise.hpp" |
26 | 27 | ||
@@ -91,10 +92,10 @@ static const char luaminifyCodes[] = | |||
91 | 92 | ||
92 | static void pushLuaminify(lua_State* L) { | 93 | static void pushLuaminify(lua_State* L) { |
93 | if (luaL_loadbuffer(L, luaminifyCodes, sizeof(luaminifyCodes) / sizeof(luaminifyCodes[0]) - 1, "=(luaminify)") != 0) { | 94 | if (luaL_loadbuffer(L, luaminifyCodes, sizeof(luaminifyCodes) / sizeof(luaminifyCodes[0]) - 1, "=(luaminify)") != 0) { |
94 | std::string err = std::string("failed to load luaminify module.\n") + lua_tostring(L, -1); | 95 | std::string err = "failed to load luaminify module.\n"s + lua_tostring(L, -1); |
95 | luaL_error(L, err.c_str()); | 96 | luaL_error(L, err.c_str()); |
96 | } else if (lua_pcall(L, 0, 1, 0) != 0) { | 97 | } else if (lua_pcall(L, 0, 1, 0) != 0) { |
97 | std::string err = std::string("failed to init luaminify module.\n") + lua_tostring(L, -1); | 98 | std::string err = "failed to init luaminify module.\n"s + lua_tostring(L, -1); |
98 | luaL_error(L, err.c_str()); | 99 | luaL_error(L, err.c_str()); |
99 | } | 100 | } |
100 | } | 101 | } |
@@ -209,7 +210,7 @@ int main(int narg, const char** args) { | |||
209 | DEFER(lua_settop(L, top)); | 210 | DEFER(lua_settop(L, top)); |
210 | pushYue(L, "loadstring"sv); | 211 | pushYue(L, "loadstring"sv); |
211 | lua_pushlstring(L, codes.c_str(), codes.size()); | 212 | lua_pushlstring(L, codes.c_str(), codes.size()); |
212 | lua_pushstring(L, (std::string("=(repl ") + std::to_string(count) + ')').c_str()); | 213 | lua_pushstring(L, ("=(repl "s + std::to_string(count) + ')').c_str()); |
213 | pushOptions(L, -1); | 214 | pushOptions(L, -1); |
214 | const std::string_view Err = "\033[35m"sv, Val = "\033[33m"sv, Stop = "\033[0m\n"sv; | 215 | const std::string_view Err = "\033[35m"sv, Val = "\033[33m"sv, Stop = "\033[0m\n"sv; |
215 | if (lua_pcall(L, 3, 2, 0) != 0) { | 216 | if (lua_pcall(L, 3, 2, 0) != 0) { |
@@ -218,7 +219,7 @@ int main(int narg, const char** args) { | |||
218 | } | 219 | } |
219 | if (lua_isnil(L, -2) != 0) { | 220 | if (lua_isnil(L, -2) != 0) { |
220 | std::string err = lua_tostring(L, -1); | 221 | std::string err = lua_tostring(L, -1); |
221 | auto modName = std::string("(repl "sv) + std::to_string(count) + "):"; | 222 | auto modName = "(repl "s + std::to_string(count) + "):"s; |
222 | if (err.substr(0, modName.size()) == modName) { | 223 | if (err.substr(0, modName.size()) == modName) { |
223 | err = err.substr(modName.size()); | 224 | err = err.substr(modName.size()); |
224 | } | 225 | } |
@@ -409,8 +410,8 @@ int main(int narg, const char** args) { | |||
409 | std::cout << help; | 410 | std::cout << help; |
410 | return 1; | 411 | return 1; |
411 | } | 412 | } |
412 | } else if (arg.size() > 1 && arg.substr(0, 1) == "-"sv && arg.substr(1, 1) != "-"sv) { | 413 | } else if (arg.size() > 2 && arg.substr(0, 2) == "--"sv && arg.substr(2, 1) != "-"sv) { |
413 | auto argStr = arg.substr(1); | 414 | auto argStr = arg.substr(2); |
414 | yue::Utils::trim(argStr); | 415 | yue::Utils::trim(argStr); |
415 | size_t idx = argStr.find('='); | 416 | size_t idx = argStr.find('='); |
416 | if (idx != std::string::npos) { | 417 | if (idx != std::string::npos) { |
@@ -420,7 +421,7 @@ int main(int narg, const char** args) { | |||
420 | yue::Utils::trim(value); | 421 | yue::Utils::trim(value); |
421 | config.options[key] = value; | 422 | config.options[key] = value; |
422 | } else { | 423 | } else { |
423 | config.options[argStr] = ""; | 424 | config.options[argStr] = std::string(); |
424 | } | 425 | } |
425 | } else { | 426 | } else { |
426 | if (fs::is_directory(arg)) { | 427 | if (fs::is_directory(arg)) { |
@@ -459,7 +460,13 @@ int main(int narg, const char** args) { | |||
459 | auto conf = config; | 460 | auto conf = config; |
460 | conf.module = file.first; | 461 | conf.module = file.first; |
461 | if (!workPath.empty()) { | 462 | if (!workPath.empty()) { |
462 | conf.options["path"] = (fs::path(workPath) / "?.lua").string(); | 463 | auto it = conf.options.find("path"); |
464 | if (it != conf.options.end()) { | ||
465 | it->second += ';'; | ||
466 | it->second += (fs::path(workPath) / "?.lua"sv).string(); | ||
467 | } else { | ||
468 | conf.options["path"] = (fs::path(workPath) / "?.lua"sv).string(); | ||
469 | } | ||
463 | } | 470 | } |
464 | if (dumpCompileTime) { | 471 | if (dumpCompileTime) { |
465 | auto start = std::chrono::high_resolution_clock::now(); | 472 | auto start = std::chrono::high_resolution_clock::now(); |
@@ -499,7 +506,7 @@ int main(int narg, const char** args) { | |||
499 | } else { | 506 | } else { |
500 | std::string targetExtension("lua"sv); | 507 | std::string targetExtension("lua"sv); |
501 | if (result.options) { | 508 | if (result.options) { |
502 | auto it = result.options->find("target_extension"); | 509 | auto it = result.options->find("target_extension"s); |
503 | if (it != result.options->end()) { | 510 | if (it != result.options->end()) { |
504 | targetExtension = it->second; | 511 | targetExtension = it->second; |
505 | } | 512 | } |
@@ -519,19 +526,19 @@ int main(int narg, const char** args) { | |||
519 | fs::create_directories(targetFile.parent_path()); | 526 | fs::create_directories(targetFile.parent_path()); |
520 | } | 527 | } |
521 | if (result.codes.empty()) { | 528 | if (result.codes.empty()) { |
522 | return std::tuple{0, targetFile.string(), std::string("Built "sv) + file.first + '\n'}; | 529 | return std::tuple{0, targetFile.string(), "Built "s + file.first + '\n'}; |
523 | } | 530 | } |
524 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); | 531 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); |
525 | if (output) { | 532 | if (output) { |
526 | const auto& codes = result.codes; | 533 | const auto& codes = result.codes; |
527 | if (config.reserveLineNumber) { | 534 | if (config.reserveLineNumber) { |
528 | auto head = std::string("-- [yue]: "sv) + file.first + '\n'; | 535 | auto head = "-- [yue]: "s + file.first + '\n'; |
529 | output.write(head.c_str(), head.size()); | 536 | output.write(head.c_str(), head.size()); |
530 | } | 537 | } |
531 | output.write(codes.c_str(), codes.size()); | 538 | output.write(codes.c_str(), codes.size()); |
532 | return std::tuple{0, targetFile.string(), std::string("Built "sv) + file.first + '\n'}; | 539 | return std::tuple{0, targetFile.string(), "Built "s + file.first + '\n'}; |
533 | } else { | 540 | } else { |
534 | return std::tuple{1, std::string(), std::string("Failed to write file: "sv) + targetFile.string() + '\n'}; | 541 | return std::tuple{1, std::string(), "Failed to write file: "s + targetFile.string() + '\n'}; |
535 | } | 542 | } |
536 | } | 543 | } |
537 | } else { | 544 | } else { |
@@ -541,7 +548,7 @@ int main(int narg, const char** args) { | |||
541 | return std::tuple{1, std::string(), buf.str()}; | 548 | return std::tuple{1, std::string(), buf.str()}; |
542 | } | 549 | } |
543 | } else { | 550 | } else { |
544 | return std::tuple{1, std::string(), std::string("Failed to read file: "sv) + file.first + ".\n"}; | 551 | return std::tuple{1, std::string(), "Failed to read file: "s + file.first + ".\n"}; |
545 | } | 552 | } |
546 | }); | 553 | }); |
547 | results.push_back(std::move(task)); | 554 | results.push_back(std::move(task)); |
@@ -588,7 +595,7 @@ int main(int narg, const char** args) { | |||
588 | if (lua_pcall(L, 1, 1, 0) != 0) { | 595 | if (lua_pcall(L, 1, 1, 0) != 0) { |
589 | ret = 2; | 596 | ret = 2; |
590 | std::string err = lua_tostring(L, -1); | 597 | std::string err = lua_tostring(L, -1); |
591 | errs.push_back(std::string("Failed to minify: "sv) + file + '\n' + err + '\n'); | 598 | errs.push_back("Failed to minify: "s + file + '\n' + err + '\n'); |
592 | } else { | 599 | } else { |
593 | size_t size = 0; | 600 | size_t size = 0; |
594 | const char* minifiedCodes = lua_tolstring(L, -1, &size); | 601 | const char* minifiedCodes = lua_tolstring(L, -1, &size); |
@@ -603,7 +610,7 @@ int main(int narg, const char** args) { | |||
603 | } | 610 | } |
604 | } else { | 611 | } else { |
605 | ret = 2; | 612 | ret = 2; |
606 | errs.push_back(std::string("Failed to minify: "sv) + file + '\n'); | 613 | errs.push_back("Failed to minify: "s + file + '\n'); |
607 | } | 614 | } |
608 | } else { | 615 | } else { |
609 | std::cout << msg; | 616 | std::cout << msg; |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 05ac5ef..620dfcc 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -118,16 +118,22 @@ AST_NODE(Local) | |||
118 | AST_MEMBER(Local, &item) | 118 | AST_MEMBER(Local, &item) |
119 | AST_END(Local, "local"sv) | 119 | AST_END(Local, "local"sv) |
120 | 120 | ||
121 | class Assign_t; | 121 | AST_LEAF(const_attrib) |
122 | AST_END(const_attrib, "const"sv) | ||
123 | |||
124 | AST_LEAF(close_attrib) | ||
125 | AST_END(close_attrib, "close"sv) | ||
122 | 126 | ||
123 | AST_LEAF(Attrib) | 127 | class simple_table_t; |
124 | AST_END(Attrib, "attrib"sv) | 128 | class TableLit_t; |
129 | class Assign_t; | ||
125 | 130 | ||
126 | AST_NODE(LocalAttrib) | 131 | AST_NODE(LocalAttrib) |
127 | ast_ptr<true, Attrib_t> attrib; | 132 | ast_sel<true, const_attrib_t, close_attrib_t> attrib; |
128 | ast_ptr<true, NameList_t> nameList; | 133 | ast_ptr<true, Seperator_t> sep; |
134 | ast_sel_list<true, Variable_t, simple_table_t, TableLit_t> leftList; | ||
129 | ast_ptr<true, Assign_t> assign; | 135 | ast_ptr<true, Assign_t> assign; |
130 | AST_MEMBER(LocalAttrib, &attrib, &nameList, &assign) | 136 | AST_MEMBER(LocalAttrib, &attrib, &sep, &leftList, &assign) |
131 | AST_END(LocalAttrib, "local_attrib"sv) | 137 | AST_END(LocalAttrib, "local_attrib"sv) |
132 | 138 | ||
133 | AST_NODE(colon_import_name) | 139 | AST_NODE(colon_import_name) |
@@ -135,9 +141,6 @@ AST_NODE(colon_import_name) | |||
135 | AST_MEMBER(colon_import_name, &name) | 141 | AST_MEMBER(colon_import_name, &name) |
136 | AST_END(colon_import_name, "colon_import_name"sv) | 142 | AST_END(colon_import_name, "colon_import_name"sv) |
137 | 143 | ||
138 | class Exp_t; | ||
139 | class TableLit_t; | ||
140 | |||
141 | AST_LEAF(import_literal_inner) | 144 | AST_LEAF(import_literal_inner) |
142 | AST_END(import_literal_inner, "import_literal_inner"sv) | 145 | AST_END(import_literal_inner, "import_literal_inner"sv) |
143 | 146 | ||
@@ -147,6 +150,8 @@ AST_NODE(ImportLiteral) | |||
147 | AST_MEMBER(ImportLiteral, &sep, &inners) | 150 | AST_MEMBER(ImportLiteral, &sep, &inners) |
148 | AST_END(ImportLiteral, "import_literal"sv) | 151 | AST_END(ImportLiteral, "import_literal"sv) |
149 | 152 | ||
153 | class Exp_t; | ||
154 | |||
150 | AST_NODE(ImportFrom) | 155 | AST_NODE(ImportFrom) |
151 | ast_ptr<true, Seperator_t> sep; | 156 | ast_ptr<true, Seperator_t> sep; |
152 | ast_sel_list<true, colon_import_name_t, Variable_t> names; | 157 | ast_sel_list<true, colon_import_name_t, Variable_t> names; |
@@ -499,7 +504,6 @@ class String_t; | |||
499 | class const_value_t; | 504 | class const_value_t; |
500 | class ClassDecl_t; | 505 | class ClassDecl_t; |
501 | class unary_value_t; | 506 | class unary_value_t; |
502 | class TableLit_t; | ||
503 | class FunLit_t; | 507 | class FunLit_t; |
504 | 508 | ||
505 | AST_NODE(SimpleValue) | 509 | AST_NODE(SimpleValue) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 7bbf5e9..0d027a0 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
13 | #include <vector> | 13 | #include <vector> |
14 | #include <memory> | 14 | #include <memory> |
15 | #include <set> | 15 | #include <set> |
16 | #include <optional> | ||
16 | 17 | ||
17 | #include "yuescript/yue_parser.h" | 18 | #include "yuescript/yue_parser.h" |
18 | #include "yuescript/yue_compiler.h" | 19 | #include "yuescript/yue_compiler.h" |
@@ -37,9 +38,6 @@ extern "C" { | |||
37 | #endif // YUE_NO_MACRO | 38 | #endif // YUE_NO_MACRO |
38 | 39 | ||
39 | namespace yue { | 40 | namespace yue { |
40 | using namespace std::string_view_literals; | ||
41 | using namespace std::string_literals; | ||
42 | using namespace parserlib; | ||
43 | 41 | ||
44 | #define BLOCK_START do { | 42 | #define BLOCK_START do { |
45 | #define BLOCK_END } while (false); | 43 | #define BLOCK_END } while (false); |
@@ -56,7 +54,7 @@ using namespace parserlib; | |||
56 | 54 | ||
57 | typedef std::list<std::string> str_list; | 55 | typedef std::list<std::string> str_list; |
58 | 56 | ||
59 | const std::string_view version = "0.13.6"sv; | 57 | const std::string_view version = "0.14.0"sv; |
60 | const std::string_view extension = "yue"sv; | 58 | const std::string_view extension = "yue"sv; |
61 | 59 | ||
62 | class YueCompilerImpl { | 60 | class YueCompilerImpl { |
@@ -1266,8 +1264,8 @@ private: | |||
1266 | 1264 | ||
1267 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1265 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
1268 | auto info = extractDestructureInfo(assignment, true, false); | 1266 | auto info = extractDestructureInfo(assignment, true, false); |
1269 | if (!info.first.empty()) { | 1267 | if (!info.destructures.empty()) { |
1270 | for (const auto& destruct : info.first) { | 1268 | for (const auto& destruct : info.destructures) { |
1271 | str_list defs; | 1269 | str_list defs; |
1272 | for (const auto& item : destruct.items) { | 1270 | for (const auto& item : destruct.items) { |
1273 | if (!item.targetVar.empty()) { | 1271 | if (!item.targetVar.empty()) { |
@@ -1319,11 +1317,30 @@ private: | |||
1319 | return assignment; | 1317 | return assignment; |
1320 | } | 1318 | } |
1321 | 1319 | ||
1320 | void markDestructureConst(ExpListAssign_t* assignment) { | ||
1321 | auto info = extractDestructureInfo(assignment, true, false); | ||
1322 | for (auto& destruct : info.destructures) { | ||
1323 | for (auto& item : destruct.items) { | ||
1324 | if (item.targetVar.empty()) { | ||
1325 | throw std::logic_error(_info.errorMessage("can only declare variable as const"sv, item.target)); | ||
1326 | } | ||
1327 | markVarConst(item.targetVar); | ||
1328 | } | ||
1329 | } | ||
1330 | } | ||
1331 | |||
1322 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 1332 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
1323 | checkAssignable(assignment->expList); | 1333 | checkAssignable(assignment->expList); |
1324 | BLOCK_START | 1334 | BLOCK_START |
1325 | auto assign = ast_cast<Assign_t>(assignment->action); | 1335 | auto assign = ast_cast<Assign_t>(assignment->action); |
1326 | BREAK_IF(!assign); | 1336 | BREAK_IF(!assign); |
1337 | if (assignment->expList->exprs.size() < assign->values.size()) { | ||
1338 | auto num = assignment->expList->exprs.size(); | ||
1339 | _buf << "no more than "sv << num << " right value"sv; | ||
1340 | if (num > 1) _buf << 's'; | ||
1341 | _buf << " required"sv; | ||
1342 | throw std::logic_error(_info.errorMessage(clearBuf(), assign->values.front())); | ||
1343 | } | ||
1327 | auto x = assignment; | 1344 | auto x = assignment; |
1328 | const auto& exprs = assignment->expList->exprs.objects(); | 1345 | const auto& exprs = assignment->expList->exprs.objects(); |
1329 | const auto& values = assign->values.objects(); | 1346 | const auto& values = assign->values.objects(); |
@@ -1554,15 +1571,15 @@ private: | |||
1554 | } | 1571 | } |
1555 | BLOCK_END | 1572 | BLOCK_END |
1556 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); | 1573 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
1557 | if (info.first.empty()) { | 1574 | if (info.destructures.empty()) { |
1558 | transformAssignmentCommon(assignment, out); | 1575 | transformAssignmentCommon(assignment, out); |
1559 | } else { | 1576 | } else { |
1560 | str_list temp; | 1577 | str_list temp; |
1561 | if (info.second) { | 1578 | if (info.assignment) { |
1562 | transformAssignmentCommon(info.second, temp); | 1579 | transformAssignmentCommon(info.assignment, temp); |
1563 | } | 1580 | } |
1564 | auto x = assignment; | 1581 | auto x = assignment; |
1565 | for (auto& destruct : info.first) { | 1582 | for (auto& destruct : info.destructures) { |
1566 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; | 1583 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; |
1567 | bool extraScope = false; | 1584 | bool extraScope = false; |
1568 | if (destruct.items.size() == 1) { | 1585 | if (destruct.items.size() == 1) { |
@@ -2030,24 +2047,22 @@ private: | |||
2030 | return pairs; | 2047 | return pairs; |
2031 | } | 2048 | } |
2032 | 2049 | ||
2033 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 2050 | struct DestructureInfo { |
2034 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | 2051 | std::list<Destructure> destructures; |
2052 | ast_ptr<false, ExpListAssign_t> assignment; | ||
2053 | }; | ||
2054 | |||
2055 | DestructureInfo extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | ||
2035 | auto x = assignment; | 2056 | auto x = assignment; |
2036 | std::list<Destructure> destructs; | 2057 | std::list<Destructure> destructs; |
2037 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; | 2058 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; |
2038 | auto exprs = assignment->expList->exprs.objects(); | 2059 | auto exprs = assignment->expList->exprs.objects(); |
2039 | auto values = assignment->action.to<Assign_t>()->values.objects(); | 2060 | auto values = assignment->action.to<Assign_t>()->values.objects(); |
2040 | size_t size = std::max(exprs.size(), values.size()); | 2061 | size_t size = std::max(exprs.size(), values.size()); |
2041 | ast_list<false, ast_node> cache; | 2062 | ast_ptr<false, Exp_t> nil; |
2042 | if (exprs.size() < size) { | ||
2043 | auto var = toAst<Exp_t>("_"sv, x); | ||
2044 | cache.push_back(var); | ||
2045 | while (exprs.size() < size) exprs.emplace_back(var); | ||
2046 | } | ||
2047 | ast_ptr<false, Exp_t> nullNode; | ||
2048 | if (values.size() < size) { | 2063 | if (values.size() < size) { |
2049 | nullNode = toAst<Exp_t>("nil"sv, x); | 2064 | nil = toAst<Exp_t>("nil"sv, x); |
2050 | while (values.size() < size) values.emplace_back(nullNode); | 2065 | while (values.size() < size) values.emplace_back(nil); |
2051 | } | 2066 | } |
2052 | using iter = node_container::iterator; | 2067 | using iter = node_container::iterator; |
2053 | std::vector<std::pair<iter, iter>> destructPairs; | 2068 | std::vector<std::pair<iter, iter>> destructPairs; |
@@ -2059,11 +2074,11 @@ private: | |||
2059 | auto value = singleValueFrom(expr); | 2074 | auto value = singleValueFrom(expr); |
2060 | ast_node* destructNode = value->getByPath<SimpleValue_t, TableLit_t>(); | 2075 | ast_node* destructNode = value->getByPath<SimpleValue_t, TableLit_t>(); |
2061 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { | 2076 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { |
2062 | if (*j != nullNode) { | 2077 | if (*j != nil) { |
2063 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 2078 | if (auto ssVal = simpleSingleValueFrom(*j)) { |
2064 | switch (ssVal->value->getId()) { | 2079 | switch (ssVal->value->getId()) { |
2065 | case id<const_value_t>(): | 2080 | case id<const_value_t>(): |
2066 | throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); | 2081 | throw std::logic_error(_info.errorMessage("can not destructure a constant"sv, ssVal->value)); |
2067 | break; | 2082 | break; |
2068 | case id<Num_t>(): | 2083 | case id<Num_t>(): |
2069 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); | 2084 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); |
@@ -2074,7 +2089,7 @@ private: | |||
2074 | } | 2089 | } |
2075 | } | 2090 | } |
2076 | } else { | 2091 | } else { |
2077 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); | 2092 | throw std::logic_error(_info.errorMessage("an explicit destructure target required"sv, destructNode)); |
2078 | } | 2093 | } |
2079 | destructPairs.push_back({i, j}); | 2094 | destructPairs.push_back({i, j}); |
2080 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); | 2095 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); |
@@ -2173,7 +2188,7 @@ private: | |||
2173 | } | 2188 | } |
2174 | destruct.items = std::move(pairs); | 2189 | destruct.items = std::move(pairs); |
2175 | if (!varDefOnly) { | 2190 | if (!varDefOnly) { |
2176 | if (*j == nullNode) { | 2191 | if (*j == nil) { |
2177 | for (auto& item : destruct.items) { | 2192 | for (auto& item : destruct.items) { |
2178 | item.structure.clear(); | 2193 | item.structure.clear(); |
2179 | } | 2194 | } |
@@ -3104,8 +3119,8 @@ private: | |||
3104 | } | 3119 | } |
3105 | } | 3120 | } |
3106 | auto info = extractDestructureInfo(assignment, true, false); | 3121 | auto info = extractDestructureInfo(assignment, true, false); |
3107 | if (!info.first.empty()) { | 3122 | if (!info.destructures.empty()) { |
3108 | for (const auto& destruct : info.first) | 3123 | for (const auto& destruct : info.destructures) |
3109 | for (const auto& item : destruct.items) | 3124 | for (const auto& item : destruct.items) |
3110 | if (!item.targetVar.empty()) { | 3125 | if (!item.targetVar.empty()) { |
3111 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); | 3126 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); |
@@ -3114,8 +3129,8 @@ private: | |||
3114 | } | 3129 | } |
3115 | } | 3130 | } |
3116 | } | 3131 | } |
3117 | if (info.second) { | 3132 | if (info.assignment) { |
3118 | auto defs = transformAssignDefs(info.second->expList, DefOp::Get); | 3133 | auto defs = transformAssignDefs(info.assignment->expList, DefOp::Get); |
3119 | for (const auto& def : defs) { | 3134 | for (const auto& def : defs) { |
3120 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); | 3135 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); |
3121 | } else if (any) { | 3136 | } else if (any) { |
@@ -3236,6 +3251,49 @@ private: | |||
3236 | } | 3251 | } |
3237 | } | 3252 | } |
3238 | 3253 | ||
3254 | std::optional<std::string> getOption(std::string_view key) { | ||
3255 | #ifndef YUE_NO_MACRO | ||
3256 | if (L) { | ||
3257 | int top = lua_gettop(L); | ||
3258 | DEFER(lua_settop(L, top)); | ||
3259 | pushYue("options"sv); // options | ||
3260 | lua_pushlstring(L, &key.front(), key.size()); | ||
3261 | lua_gettable(L, -2); | ||
3262 | if (lua_isstring(L, -1) != 0) { | ||
3263 | size_t size = 0; | ||
3264 | const char* str = lua_tolstring(L, -1, &size); | ||
3265 | return std::string(str, size); | ||
3266 | } | ||
3267 | } | ||
3268 | #endif // YUE_NO_MACRO | ||
3269 | auto it = _config.options.find(std::string(key)); | ||
3270 | if (it != _config.options.end()) { | ||
3271 | return it->second; | ||
3272 | } | ||
3273 | return std::nullopt; | ||
3274 | } | ||
3275 | |||
3276 | int getLuaTarget(ast_node* x) { | ||
3277 | if (auto target = getOption("target")) { | ||
3278 | if (target.value() == "5.1"sv) { | ||
3279 | return 501; | ||
3280 | } else if (target.value() == "5.2"sv) { | ||
3281 | return 502; | ||
3282 | } else if (target.value() == "5.3"sv) { | ||
3283 | return 503; | ||
3284 | } else if (target.value() == "5.4"sv) { | ||
3285 | return 504; | ||
3286 | } else { | ||
3287 | 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)); | ||
3288 | } | ||
3289 | } | ||
3290 | #ifndef YUE_NO_MACRO | ||
3291 | return LUA_VERSION_NUM; | ||
3292 | #else | ||
3293 | return 504; | ||
3294 | #endif // YUE_NO_MACRO | ||
3295 | } | ||
3296 | |||
3239 | #ifndef YUE_NO_MACRO | 3297 | #ifndef YUE_NO_MACRO |
3240 | void passOptions() { | 3298 | void passOptions() { |
3241 | if (!_config.options.empty()) { | 3299 | if (!_config.options.empty()) { |
@@ -5898,8 +5956,8 @@ private: | |||
5898 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 5956 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
5899 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 5957 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
5900 | auto info = extractDestructureInfo(assignment, true, false); | 5958 | auto info = extractDestructureInfo(assignment, true, false); |
5901 | if (!info.first.empty()) { | 5959 | if (!info.destructures.empty()) { |
5902 | for (const auto& destruct : info.first) | 5960 | for (const auto& destruct : info.destructures) |
5903 | for (const auto& item : destruct.items) | 5961 | for (const auto& item : destruct.items) |
5904 | if (!item.targetVar.empty() && addToScope(item.targetVar)) | 5962 | if (!item.targetVar.empty() && addToScope(item.targetVar)) |
5905 | varDefs.push_back(item.targetVar); | 5963 | varDefs.push_back(item.targetVar); |
@@ -6329,8 +6387,8 @@ private: | |||
6329 | return traversal::Stop; | 6387 | return traversal::Stop; |
6330 | } | 6388 | } |
6331 | auto info = extractDestructureInfo(assignment, true, false); | 6389 | auto info = extractDestructureInfo(assignment, true, false); |
6332 | if (!info.first.empty()) { | 6390 | if (!info.destructures.empty()) { |
6333 | for (const auto& destruct : info.first) | 6391 | for (const auto& destruct : info.destructures) |
6334 | for (const auto& item : destruct.items) | 6392 | for (const auto& item : destruct.items) |
6335 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) | 6393 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) |
6336 | return traversal::Stop; | 6394 | return traversal::Stop; |
@@ -6481,8 +6539,8 @@ private: | |||
6481 | transformAssignment(assignment, out); | 6539 | transformAssignment(assignment, out); |
6482 | str_list names = transformAssignDefs(expList, DefOp::Get); | 6540 | str_list names = transformAssignDefs(expList, DefOp::Get); |
6483 | auto info = extractDestructureInfo(assignment, true, false); | 6541 | auto info = extractDestructureInfo(assignment, true, false); |
6484 | if (!info.first.empty()) { | 6542 | if (!info.destructures.empty()) { |
6485 | for (const auto& destruct : info.first) | 6543 | for (const auto& destruct : info.destructures) |
6486 | for (const auto& item : destruct.items) | 6544 | for (const auto& item : destruct.items) |
6487 | if (!item.targetVar.empty()) | 6545 | if (!item.targetVar.empty()) |
6488 | names.push_back(item.targetVar); | 6546 | names.push_back(item.targetVar); |
@@ -6848,6 +6906,7 @@ private: | |||
6848 | temp.push_back(indent() + "end"s + nlr(import)); | 6906 | temp.push_back(indent() + "end"s + nlr(import)); |
6849 | } | 6907 | } |
6850 | out.push_back(join(temp)); | 6908 | out.push_back(join(temp)); |
6909 | markDestructureConst(assignment); | ||
6851 | } | 6910 | } |
6852 | 6911 | ||
6853 | std::string moduleNameFrom(ImportLiteral_t* literal) { | 6912 | std::string moduleNameFrom(ImportLiteral_t* literal) { |
@@ -7013,6 +7072,12 @@ private: | |||
7013 | assignment->expList.set(assignList); | 7072 | assignment->expList.set(assignList); |
7014 | assignment->action.set(assign); | 7073 | assignment->action.set(assign); |
7015 | transformAssignment(assignment, out); | 7074 | transformAssignment(assignment, out); |
7075 | if (auto var = ast_cast<Variable_t>(target)) { | ||
7076 | auto moduleName = _parser.toString(var); | ||
7077 | markVarConst(moduleName); | ||
7078 | } else { | ||
7079 | markDestructureConst(assignment); | ||
7080 | } | ||
7016 | } | 7081 | } |
7017 | 7082 | ||
7018 | void transformImport(Import_t* import, str_list& out) { | 7083 | void transformImport(Import_t* import, str_list& out) { |
@@ -7191,7 +7256,7 @@ private: | |||
7191 | auto info = extractDestructureInfo(assignment, true, false); | 7256 | auto info = extractDestructureInfo(assignment, true, false); |
7192 | transformAssignment(assignment, temp, true); | 7257 | transformAssignment(assignment, temp, true); |
7193 | str_list conds; | 7258 | str_list conds; |
7194 | for (const auto& destruct : info.first) { | 7259 | for (const auto& destruct : info.destructures) { |
7195 | for (const auto& item : destruct.items) { | 7260 | for (const auto& item : destruct.items) { |
7196 | if (!item.defVal) { | 7261 | if (!item.defVal) { |
7197 | transformExp(item.target, conds, ExpUsage::Closure); | 7262 | transformExp(item.target, conds, ExpUsage::Closure); |
@@ -7334,23 +7399,84 @@ private: | |||
7334 | 7399 | ||
7335 | void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { | 7400 | void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { |
7336 | auto x = localAttrib; | 7401 | auto x = localAttrib; |
7337 | auto attrib = _parser.toString(localAttrib->attrib); | 7402 | if (x->leftList.size() < x->assign->values.size()) { |
7338 | str_list vars; | 7403 | throw std::logic_error(_info.errorMessage("number of right values should not be greater than left values"sv, x->assign->values.front())); |
7339 | for (auto name : localAttrib->nameList->names.objects()) { | 7404 | } |
7340 | auto var = _parser.toString(name); | 7405 | auto listA = x->new_ptr<NameList_t>(); |
7341 | forceAddToScope(var); | 7406 | auto assignA = x->new_ptr<Assign_t>(); |
7342 | vars.push_back(var); | 7407 | auto listB = x->new_ptr<ExpList_t>(); |
7408 | auto assignB = x->new_ptr<Assign_t>(); | ||
7409 | auto i = x->leftList.objects().begin(); | ||
7410 | auto ie = x->leftList.objects().end(); | ||
7411 | auto j = x->assign->values.objects().begin(); | ||
7412 | auto je = x->assign->values.objects().end(); | ||
7413 | while (i != ie) { | ||
7414 | if (ast_is<Variable_t>(*i)) { | ||
7415 | listA->names.push_back(*i); | ||
7416 | if (j != je) assignA->values.push_back(*j); | ||
7417 | } else { | ||
7418 | auto item = *i; | ||
7419 | auto value = item->new_ptr<Value_t>(); | ||
7420 | switch (item->getId()) { | ||
7421 | case id<simple_table_t>(): | ||
7422 | value->item.set(item); | ||
7423 | break; | ||
7424 | case id<TableLit_t>(): { | ||
7425 | auto simpleValue = item->new_ptr<SimpleValue_t>(); | ||
7426 | simpleValue->value.set(item); | ||
7427 | value->item.set(simpleValue); | ||
7428 | break; | ||
7429 | } | ||
7430 | default: YUEE("AST node mismatch", item); break; | ||
7431 | } | ||
7432 | auto exp = newExp(value, item); | ||
7433 | listB->exprs.push_back(exp); | ||
7434 | if (j != je) assignB->values.push_back(*j); | ||
7435 | } | ||
7436 | ++i; | ||
7437 | if (j != je) ++j; | ||
7343 | } | 7438 | } |
7344 | attrib = " <"s + attrib + '>'; | 7439 | if (!listA->names.empty()) { |
7345 | for (auto& var : vars) { | 7440 | str_list vars; |
7346 | markVarConst(var); | 7441 | for (auto name : listA->names.objects()) { |
7347 | var.append(attrib); | 7442 | auto var = _parser.toString(name); |
7443 | forceAddToScope(var); | ||
7444 | vars.push_back(var); | ||
7445 | } | ||
7446 | if (getLuaTarget(x) >= 504) { | ||
7447 | std::string attrib; | ||
7448 | if (localAttrib->attrib.is<const_attrib_t>()) { | ||
7449 | attrib = " <const>"s; | ||
7450 | } else if (localAttrib->attrib.is<close_attrib_t>()) { | ||
7451 | attrib = " <close>"s; | ||
7452 | } else { | ||
7453 | YUEE("AST node mismatch", localAttrib->attrib); | ||
7454 | } | ||
7455 | for (auto& var : vars) { | ||
7456 | markVarConst(var); | ||
7457 | var.append(attrib); | ||
7458 | } | ||
7459 | } else { | ||
7460 | if (localAttrib->attrib.is<close_attrib_t>()) { | ||
7461 | throw std::logic_error(_info.errorMessage("close attribute is not available when not targeting Lua 5.4 or higher version"sv, x)); | ||
7462 | } | ||
7463 | for (auto& var : vars) { | ||
7464 | markVarConst(var); | ||
7465 | } | ||
7466 | } | ||
7467 | str_list temp; | ||
7468 | for (auto item : assignA->values.objects()) { | ||
7469 | transformAssignItem(item, temp); | ||
7470 | } | ||
7471 | out.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(temp, ", "sv) + nll(x)); | ||
7348 | } | 7472 | } |
7349 | str_list temp; | 7473 | if (!listB->exprs.empty()) { |
7350 | for (auto item : localAttrib->assign->values.objects()) { | 7474 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
7351 | transformAssignItem(item, temp); | 7475 | assignment->expList.set(listB); |
7476 | assignment->action.set(assignB); | ||
7477 | transformAssignment(assignment, out); | ||
7478 | markDestructureConst(assignment); | ||
7352 | } | 7479 | } |
7353 | out.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(temp, ", "sv) + nll(x)); | ||
7354 | } | 7480 | } |
7355 | 7481 | ||
7356 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 7482 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
@@ -7372,10 +7498,16 @@ private: | |||
7372 | } | 7498 | } |
7373 | 7499 | ||
7374 | void transformLabel(Label_t* label, str_list& out) { | 7500 | void transformLabel(Label_t* label, str_list& out) { |
7501 | if (getLuaTarget(label) < 502) { | ||
7502 | throw std::logic_error(_info.errorMessage("label statement is not available when not targeting Lua 5.2 or higher version"sv, label)); | ||
7503 | } | ||
7375 | out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); | 7504 | out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); |
7376 | } | 7505 | } |
7377 | 7506 | ||
7378 | void transformGoto(Goto_t* gotoNode, str_list& out) { | 7507 | void transformGoto(Goto_t* gotoNode, str_list& out) { |
7508 | if (getLuaTarget(gotoNode) < 502) { | ||
7509 | throw std::logic_error(_info.errorMessage("goto statement is not available when not targeting Lua 5.2 or higher version"sv, gotoNode)); | ||
7510 | } | ||
7379 | out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); | 7511 | out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); |
7380 | } | 7512 | } |
7381 | 7513 | ||
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 66043d3..94ce550 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -11,25 +11,24 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
11 | namespace pl = parserlib; | 11 | namespace pl = parserlib; |
12 | 12 | ||
13 | namespace yue { | 13 | namespace yue { |
14 | using namespace std::string_view_literals; | ||
15 | 14 | ||
16 | std::unordered_set<std::string> LuaKeywords = { | 15 | std::unordered_set<std::string> LuaKeywords = { |
17 | "and", "break", "do", "else", "elseif", | 16 | "and"s, "break"s, "do"s, "else"s, "elseif"s, |
18 | "end", "false", "for", "function", "goto", | 17 | "end"s, "false"s, "for"s, "function"s, "goto"s, |
19 | "if", "in", "local", "nil", "not", | 18 | "if"s, "in"s, "local"s, "nil"s, "not"s, |
20 | "or", "repeat", "return", "then", "true", | 19 | "or"s, "repeat"s, "return"s, "then"s, "true"s, |
21 | "until", "while" | 20 | "until"s, "while"s |
22 | }; | 21 | }; |
23 | 22 | ||
24 | std::unordered_set<std::string> Keywords = { | 23 | std::unordered_set<std::string> Keywords = { |
25 | "and", "break", "do", "else", "elseif", | 24 | "and"s, "break"s, "do"s, "else"s, "elseif"s, |
26 | "end", "false", "for", "function", "goto", | 25 | "end"s, "false"s, "for"s, "function"s, "goto"s, |
27 | "if", "in", "local", "nil", "not", | 26 | "if"s, "in"s, "local"s, "nil"s, "not"s, |
28 | "or", "repeat", "return", "then", "true", | 27 | "or"s, "repeat"s, "return"s, "then"s, "true"s, |
29 | "until", "while", // Lua keywords | 28 | "until"s, "while"s, // Lua keywords |
30 | "as", "class", "continue", "export", "extends", | 29 | "as"s, "class"s, "continue"s, "export"s, "extends"s, |
31 | "from", "global", "import", "macro", "switch", | 30 | "from"s, "global"s, "import"s, "macro"s, "switch"s, |
32 | "try", "unless", "using", "when", "with" // Yue keywords | 31 | "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords |
33 | }; | 32 | }; |
34 | 33 | ||
35 | YueParser::YueParser() { | 34 | YueParser::YueParser() { |
@@ -86,7 +85,7 @@ YueParser::YueParser() { | |||
86 | if (isValid) { | 85 | if (isValid) { |
87 | if (st->buffer == st->moduleName) { | 86 | if (st->buffer == st->moduleName) { |
88 | st->moduleFix++; | 87 | st->moduleFix++; |
89 | st->moduleName = std::string("_module_"sv) + std::to_string(st->moduleFix); | 88 | st->moduleName = "_module_"s + std::to_string(st->moduleFix); |
90 | } | 89 | } |
91 | } | 90 | } |
92 | st->buffer.clear(); | 91 | st->buffer.clear(); |
@@ -179,10 +178,15 @@ YueParser::YueParser() { | |||
179 | 178 | ||
180 | local_flag = expr('*') | expr('^'); | 179 | local_flag = expr('*') | expr('^'); |
181 | local_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); | 180 | local_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); |
182 | Attrib = (expr("const") | expr("close")) >> not_(AlphaNum); | ||
183 | Local = key("local") >> (Space >> local_flag | local_values); | 181 | Local = key("local") >> (Space >> local_flag | local_values); |
184 | 182 | ||
185 | LocalAttrib = Attrib >> NameList >> Assign; | 183 | const_attrib = key("const"); |
184 | close_attrib = key("close"); | ||
185 | local_const_item = (Space >> Variable | simple_table | TableLit); | ||
186 | LocalAttrib = ( | ||
187 | const_attrib >> Seperator >> local_const_item >> *(sym(',') >> local_const_item) | | ||
188 | close_attrib >> Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable) | ||
189 | ) >> Assign; | ||
186 | 190 | ||
187 | colon_import_name = sym('\\') >> Space >> Variable; | 191 | colon_import_name = sym('\\') >> Space >> Variable; |
188 | ImportName = colon_import_name | Space >> Variable; | 192 | ImportName = colon_import_name | Space >> Variable; |
@@ -754,6 +758,10 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
754 | ++it; | 758 | ++it; |
755 | } | 759 | } |
756 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | 760 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); |
761 | while (col < static_cast<int>(line.size()) | ||
762 | && (line[col] == ' ' || line[col] == '\t')) { | ||
763 | col++; | ||
764 | } | ||
757 | Utils::replace(line, "\t"sv, " "sv); | 765 | Utils::replace(line, "\t"sv, " "sv); |
758 | std::ostringstream buf; | 766 | std::ostringstream buf; |
759 | buf << loc->m_begin.m_line << ": "sv << msg << | 767 | buf << loc->m_begin.m_line << ": "sv << msg << |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index b71a67c..b363ad7 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -21,6 +21,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
21 | #include "yuescript/yue_ast.h" | 21 | #include "yuescript/yue_ast.h" |
22 | 22 | ||
23 | namespace yue { | 23 | namespace yue { |
24 | using namespace std::string_view_literals; | ||
25 | using namespace std::string_literals; | ||
24 | using namespace parserlib; | 26 | using namespace parserlib; |
25 | 27 | ||
26 | struct ParseInfo { | 28 | struct ParseInfo { |
@@ -77,7 +79,7 @@ protected: | |||
77 | int exportCount = 0; | 79 | int exportCount = 0; |
78 | int moduleFix = 0; | 80 | int moduleFix = 0; |
79 | size_t stringOpen = 0; | 81 | size_t stringOpen = 0; |
80 | std::string moduleName = "_module_0"; | 82 | std::string moduleName = "_module_0"s; |
81 | std::string buffer; | 83 | std::string buffer; |
82 | std::stack<int> indents; | 84 | std::stack<int> indents; |
83 | std::stack<bool> noDoStack; | 85 | std::stack<bool> noDoStack; |
@@ -189,6 +191,7 @@ private: | |||
189 | rule expo_value; | 191 | rule expo_value; |
190 | rule expo_exp; | 192 | rule expo_exp; |
191 | rule exp_not_tab; | 193 | rule exp_not_tab; |
194 | rule local_const_item; | ||
192 | rule empty_line_stop; | 195 | rule empty_line_stop; |
193 | rule Line; | 196 | rule Line; |
194 | rule Shebang; | 197 | rule Shebang; |
@@ -209,8 +212,9 @@ private: | |||
209 | AST_RULE(NameList) | 212 | AST_RULE(NameList) |
210 | AST_RULE(local_flag) | 213 | AST_RULE(local_flag) |
211 | AST_RULE(local_values) | 214 | AST_RULE(local_values) |
212 | AST_RULE(Attrib) | ||
213 | AST_RULE(Local) | 215 | AST_RULE(Local) |
216 | AST_RULE(const_attrib) | ||
217 | AST_RULE(close_attrib) | ||
214 | AST_RULE(LocalAttrib); | 218 | AST_RULE(LocalAttrib); |
215 | AST_RULE(colon_import_name) | 219 | AST_RULE(colon_import_name) |
216 | AST_RULE(import_literal_inner) | 220 | AST_RULE(import_literal_inner) |
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp index 2e96f16..98e214f 100644 --- a/src/yuescript/yuescript.cpp +++ b/src/yuescript/yuescript.cpp | |||
@@ -9,6 +9,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
9 | #include "yuescript/yue_compiler.h" | 9 | #include "yuescript/yue_compiler.h" |
10 | #include "yuescript/yue_parser.h" | 10 | #include "yuescript/yue_parser.h" |
11 | 11 | ||
12 | using namespace std::string_literals; | ||
13 | |||
12 | #if defined(YUE_BUILD_AS_DLL) | 14 | #if defined(YUE_BUILD_AS_DLL) |
13 | #define YUE_API __declspec(dllexport) | 15 | #define YUE_API __declspec(dllexport) |
14 | #else | 16 | #else |
@@ -25,12 +27,12 @@ static const char yuescriptCodes[] = | |||
25 | 27 | ||
26 | static void init_yuescript(lua_State* L) { | 28 | static void init_yuescript(lua_State* L) { |
27 | if (luaL_loadbuffer(L, yuescriptCodes, sizeof(yuescriptCodes) / sizeof(yuescriptCodes[0]) - 1, "=(yuescript)") != 0) { | 29 | if (luaL_loadbuffer(L, yuescriptCodes, sizeof(yuescriptCodes) / sizeof(yuescriptCodes[0]) - 1, "=(yuescript)") != 0) { |
28 | std::string err = std::string("failed to load yuescript module.\n") + lua_tostring(L, -1); | 30 | std::string err = "failed to load yuescript module.\n"s + lua_tostring(L, -1); |
29 | luaL_error(L, err.c_str()); | 31 | luaL_error(L, err.c_str()); |
30 | } else { | 32 | } else { |
31 | lua_insert(L, -2); | 33 | lua_insert(L, -2); |
32 | if (lua_pcall(L, 1, 0, 0) != 0) { | 34 | if (lua_pcall(L, 1, 0, 0) != 0) { |
33 | std::string err = std::string("failed to init yuescript module.\n") + lua_tostring(L, -1); | 35 | std::string err = "failed to init yuescript module.\n"s + lua_tostring(L, -1); |
34 | luaL_error(L, err.c_str()); | 36 | luaL_error(L, err.c_str()); |
35 | } | 37 | } |
36 | } | 38 | } |
@@ -41,10 +43,10 @@ static const char stpCodes[] = | |||
41 | 43 | ||
42 | static int init_stacktraceplus(lua_State* L) { | 44 | static int init_stacktraceplus(lua_State* L) { |
43 | if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) { | 45 | if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) { |
44 | std::string err = std::string("failed to load stacktraceplus module.\n") + lua_tostring(L, -1); | 46 | std::string err = "failed to load stacktraceplus module.\n"s + lua_tostring(L, -1); |
45 | luaL_error(L, err.c_str()); | 47 | luaL_error(L, err.c_str()); |
46 | } else if (lua_pcall(L, 0, 1, 0) != 0) { | 48 | } else if (lua_pcall(L, 0, 1, 0) != 0) { |
47 | std::string err = std::string("failed to init stacktraceplus module.\n") + lua_tostring(L, -1); | 49 | std::string err = "failed to init stacktraceplus module.\n"s + lua_tostring(L, -1); |
48 | luaL_error(L, err.c_str()); | 50 | luaL_error(L, err.c_str()); |
49 | } | 51 | } |
50 | return 1; | 52 | return 1; |