diff options
| author | Li Jin <dragon-fly@qq.com> | 2022-07-12 17:41:19 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2022-07-12 17:41:19 +0800 |
| commit | 68e167e9f0b90968ea67b7f21fdc50a48d129173 (patch) | |
| tree | 64612476c7cc5636d7a9eea68ea1e5b449bb9732 | |
| parent | 1a7c8e3c38fcf0af94ca799a3cd9fa7c4ef1bf08 (diff) | |
| download | yuescript-68e167e9f0b90968ea67b7f21fdc50a48d129173.tar.gz yuescript-68e167e9f0b90968ea67b7f21fdc50a48d129173.tar.bz2 yuescript-68e167e9f0b90968ea67b7f21fdc50a48d129173.zip | |
add table pattern matching syntax and fix issue #93, remove a confusing default value syntax for destructuring.
Diffstat (limited to '')
| -rw-r--r-- | spec/inputs/destructure.yue | 3 | ||||
| -rw-r--r-- | spec/inputs/switch.yue | 86 | ||||
| -rw-r--r-- | spec/outputs/destructure.lua | 121 | ||||
| -rw-r--r-- | spec/outputs/switch.lua | 264 | ||||
| -rwxr-xr-x | src/yuescript/yue_ast.h | 8 | ||||
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 615 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.cpp | 9 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.h | 2 |
8 files changed, 790 insertions, 318 deletions
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index a235abd..3007adf 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
| @@ -181,3 +181,6 @@ do | |||
| 181 | do | 181 | do |
| 182 | {_, a, _, b} = tb -- list placeholder | 182 | {_, a, _, b} = tb -- list placeholder |
| 183 | 183 | ||
| 184 | do | ||
| 185 | {x: a.b = 1, y: a.c = 2} = x.x.x | ||
| 186 | |||
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index ac3dbea..36f9be6 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue | |||
| @@ -58,7 +58,91 @@ switch hi | |||
| 58 | 58 | ||
| 59 | switch hi | 59 | switch hi |
| 60 | when 3+1, hello!, (-> 4)! | 60 | when 3+1, hello!, (-> 4)! |
| 61 | yello | 61 | _ = yello |
| 62 | else | 62 | else |
| 63 | print "cool" | 63 | print "cool" |
| 64 | 64 | ||
| 65 | do | ||
| 66 | dict = { | ||
| 67 | {} | ||
| 68 | {1, 2, 3} | ||
| 69 | a: b: c: 1 | ||
| 70 | x: y: z: 1 | ||
| 71 | } | ||
| 72 | |||
| 73 | switch dict | ||
| 74 | when { | ||
| 75 | first | ||
| 76 | {one, two, three} | ||
| 77 | a: b: :c | ||
| 78 | x: y: :z | ||
| 79 | } | ||
| 80 | print first, one, two, three, c, z | ||
| 81 | |||
| 82 | do | ||
| 83 | items = | ||
| 84 | * x: 100 | ||
| 85 | y: 200 | ||
| 86 | * width: 300 | ||
| 87 | height: 400 | ||
| 88 | * false | ||
| 89 | |||
| 90 | for item in *items | ||
| 91 | switch item | ||
| 92 | when :x, :y | ||
| 93 | print "Vec2 #{x}, #{y}" | ||
| 94 | when :width, :height | ||
| 95 | print "Size #{width}, #{height}" | ||
| 96 | when false | ||
| 97 | print "None" | ||
| 98 | when __class: cls | ||
| 99 | switch cls | ||
| 100 | when ClassA | ||
| 101 | print "Object A" | ||
| 102 | when ClassB | ||
| 103 | print "Object B" | ||
| 104 | when #: mt | ||
| 105 | print "A table with metatable" | ||
| 106 | else | ||
| 107 | print "item not accepted!" | ||
| 108 | |||
| 109 | do | ||
| 110 | tb = {} | ||
| 111 | switch tb | ||
| 112 | when {:a = 1, :b = 2} | ||
| 113 | print a, b | ||
| 114 | |||
| 115 | do | ||
| 116 | tb = x: "abc" | ||
| 117 | switch tb | ||
| 118 | when :x, :y | ||
| 119 | print "x: #{x} with y: #{y}" | ||
| 120 | when :x | ||
| 121 | print "x: #{x} only" | ||
| 122 | |||
| 123 | do | ||
| 124 | matched = switch tb | ||
| 125 | when 1 | ||
| 126 | "1" | ||
| 127 | when :x | ||
| 128 | x | ||
| 129 | when false | ||
| 130 | "false" | ||
| 131 | else | ||
| 132 | nil | ||
| 133 | |||
| 134 | do | ||
| 135 | return switch tb | ||
| 136 | when nil | ||
| 137 | "invalid" | ||
| 138 | when :a, :b | ||
| 139 | "#{a + b}" | ||
| 140 | when 1, 2, 3, 4, 5 | ||
| 141 | "number 1 - 5" | ||
| 142 | when {:alwaysMatch = "fallback"} | ||
| 143 | alwaysMatch | ||
| 144 | else | ||
| 145 | "should not reach here" | ||
| 146 | |||
| 147 | nil | ||
| 148 | |||
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 9b16181..2fe4ba9 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
| @@ -229,12 +229,12 @@ do | |||
| 229 | do | 229 | do |
| 230 | local _obj_0 = person | 230 | local _obj_0 = person |
| 231 | name, job = _obj_0.name, _obj_0.job | 231 | name, job = _obj_0.name, _obj_0.job |
| 232 | end | 232 | if name == nil then |
| 233 | if name == nil then | 233 | name = "nameless" |
| 234 | name = "nameless" | 234 | end |
| 235 | end | 235 | if job == nil then |
| 236 | if job == nil then | 236 | job = "jobless" |
| 237 | job = "jobless" | 237 | end |
| 238 | end | 238 | end |
| 239 | local request | 239 | local request |
| 240 | request = function(url, options) | 240 | request = function(url, options) |
| @@ -261,29 +261,29 @@ do | |||
| 261 | do | 261 | do |
| 262 | local _obj_0 = tb | 262 | local _obj_0 = tb |
| 263 | value1, key3 = _obj_0.key1.key2, _obj_0.key3 | 263 | value1, key3 = _obj_0.key1.key2, _obj_0.key3 |
| 264 | end | 264 | if value1 == nil then |
| 265 | if value1 == nil then | 265 | value1 = 123 |
| 266 | value1 = 123 | 266 | end |
| 267 | end | 267 | if key3 == nil then |
| 268 | if key3 == nil then | 268 | key3 = "abc" |
| 269 | key3 = "abc" | 269 | end |
| 270 | end | 270 | end |
| 271 | local mt, call, add | 271 | local mt, call, add |
| 272 | do | 272 | do |
| 273 | local _obj_0 = getmetatable(tb) | 273 | local _obj_0 = getmetatable(tb) |
| 274 | mt, call, add = _obj_0, getmetatable(_obj_0).__call, getmetatable(_obj_0).__add | 274 | mt, call, add = _obj_0, getmetatable(_obj_0).__call, getmetatable(_obj_0).__add |
| 275 | end | 275 | if mt == nil then |
| 276 | if mt == nil then | 276 | mt = { |
| 277 | mt = { | 277 | __index = { |
| 278 | __index = { | 278 | abc = 123 |
| 279 | abc = 123 | 279 | } |
| 280 | } | 280 | } |
| 281 | } | 281 | end |
| 282 | end | 282 | if call == nil then |
| 283 | if call == nil then | 283 | call = (function() |
| 284 | call = (function() | 284 | return { } |
| 285 | return { } | 285 | end) |
| 286 | end) | 286 | end |
| 287 | end | 287 | end |
| 288 | local _obj_0 = tb | 288 | local _obj_0 = tb |
| 289 | local mtx, y, zItem = getmetatable(_obj_0.x), _obj_0.y, _obj_0.z | 289 | local mtx, y, zItem = getmetatable(_obj_0.x), _obj_0.y, _obj_0.z |
| @@ -296,27 +296,33 @@ do | |||
| 296 | return nil | 296 | return nil |
| 297 | end | 297 | end |
| 298 | end | 298 | end |
| 299 | local _obj_1 = getmetatable(tb).func | 299 | do |
| 300 | if _obj_1 == nil then | 300 | local _tmp_0 |
| 301 | do | 301 | do |
| 302 | local _obj_2 = item | 302 | local _obj_1 = getmetatable(tb) |
| 303 | if _obj_2 ~= nil then | 303 | _tmp_0 = _obj_1.func |
| 304 | _obj_1 = _obj_2.defVal | 304 | end |
| 305 | if _tmp_0 == nil then | ||
| 306 | do | ||
| 307 | local _obj_1 = item | ||
| 308 | if _obj_1 ~= nil then | ||
| 309 | _tmp_0 = _obj_1.defVal | ||
| 310 | end | ||
| 305 | end | 311 | end |
| 306 | end | 312 | end |
| 307 | end | 313 | a.b(function() |
| 308 | a.b(function() | ||
| 309 | return 123 | 314 | return 123 |
| 310 | end).c = _obj_1 | 315 | end).c = _tmp_0 |
| 316 | end | ||
| 311 | end | 317 | end |
| 312 | do | 318 | do |
| 313 | local mt, subFunc | 319 | local mt, subFunc |
| 314 | do | 320 | do |
| 315 | local _obj_0 = getmetatable(tb.x) | 321 | local _obj_0 = getmetatable(tb.x) |
| 316 | mt, subFunc = _obj_0, _obj_0.__sub | 322 | mt, subFunc = _obj_0, _obj_0.__sub |
| 317 | end | 323 | if mt == nil then |
| 318 | if mt == nil then | 324 | mt = { } |
| 319 | mt = { } | 325 | end |
| 320 | end | 326 | end |
| 321 | end | 327 | end |
| 322 | do | 328 | do |
| @@ -324,27 +330,28 @@ do | |||
| 324 | do | 330 | do |
| 325 | local _obj_0 = tb | 331 | local _obj_0 = tb |
| 326 | mt, subFunc = getmetatable(_obj_0.x), getmetatable(_obj_0.x).__sub | 332 | mt, subFunc = getmetatable(_obj_0.x), getmetatable(_obj_0.x).__sub |
| 327 | end | 333 | if mt == nil then |
| 328 | if mt == nil then | 334 | mt = { } |
| 329 | mt = { } | 335 | end |
| 330 | end | 336 | end |
| 331 | end | 337 | end |
| 332 | do | 338 | do |
| 333 | local a, b, _obj_0 | 339 | local a, b |
| 334 | do | 340 | do |
| 335 | local _obj_1 = tb | 341 | local _obj_0 = tb |
| 336 | a, b, _obj_0 = _obj_1[1], _obj_1[2], _obj_1.c[1] | 342 | local _tmp_0 |
| 337 | end | 343 | a, b, _tmp_0 = _obj_0[1], _obj_0[2], _obj_0.c[1] |
| 338 | if a == nil then | 344 | if a == nil then |
| 339 | a = 1 | 345 | a = 1 |
| 340 | end | 346 | end |
| 341 | if b == nil then | 347 | if b == nil then |
| 342 | b = 2 | 348 | b = 2 |
| 343 | end | 349 | end |
| 344 | if _obj_0 == nil then | 350 | if _tmp_0 == nil then |
| 345 | _obj_0 = 3 | 351 | _tmp_0 = 3 |
| 352 | end | ||
| 353 | d.e = _tmp_0 | ||
| 346 | end | 354 | end |
| 347 | d.e = _obj_0 | ||
| 348 | local _list_0 = tuples | 355 | local _list_0 = tuples |
| 349 | for _index_0 = 1, #_list_0 do | 356 | for _index_0 = 1, #_list_0 do |
| 350 | local _des_0 = _list_0[_index_0] | 357 | local _des_0 = _list_0[_index_0] |
| @@ -365,3 +372,17 @@ do | |||
| 365 | a, b = _obj_0[2], _obj_0[4] | 372 | a, b = _obj_0[2], _obj_0[4] |
| 366 | end | 373 | end |
| 367 | end | 374 | end |
| 375 | do | ||
| 376 | do | ||
| 377 | local _obj_0 = x.x.x | ||
| 378 | local _tmp_0, _tmp_1 = _obj_0.x, _obj_0.y | ||
| 379 | if _tmp_0 == nil then | ||
| 380 | _tmp_0 = 1 | ||
| 381 | end | ||
| 382 | if _tmp_1 == nil then | ||
| 383 | _tmp_1 = 2 | ||
| 384 | end | ||
| 385 | a.b = _tmp_0 | ||
| 386 | a.c = _tmp_1 | ||
| 387 | end | ||
| 388 | end | ||
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index 81f6d5a..03a0d37 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua | |||
| @@ -77,11 +77,261 @@ do | |||
| 77 | local _ = no | 77 | local _ = no |
| 78 | end | 78 | end |
| 79 | end | 79 | end |
| 80 | local _exp_0 = hi | 80 | do |
| 81 | if (3 + 1) == _exp_0 or hello() == _exp_0 or (function() | 81 | local _exp_0 = hi |
| 82 | return 4 | 82 | if (3 + 1) == _exp_0 or hello() == _exp_0 or (function() |
| 83 | end)() == _exp_0 then | 83 | return 4 |
| 84 | return yello | 84 | end)() == _exp_0 then |
| 85 | else | 85 | local _ = yello |
| 86 | return print("cool") | 86 | else |
| 87 | print("cool") | ||
| 88 | end | ||
| 89 | end | ||
| 90 | do | ||
| 91 | local dict = { | ||
| 92 | { }, | ||
| 93 | { | ||
| 94 | 1, | ||
| 95 | 2, | ||
| 96 | 3 | ||
| 97 | }, | ||
| 98 | a = { | ||
| 99 | b = { | ||
| 100 | c = 1 | ||
| 101 | } | ||
| 102 | }, | ||
| 103 | x = { | ||
| 104 | y = { | ||
| 105 | z = 1 | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| 109 | do | ||
| 110 | local _tab_0 = "table" == type(dict) | ||
| 111 | if _tab_0 then | ||
| 112 | local first = dict[1] | ||
| 113 | local one | ||
| 114 | do | ||
| 115 | local _obj_0 = dict[2] | ||
| 116 | if _obj_0 ~= nil then | ||
| 117 | one = _obj_0[1] | ||
| 118 | end | ||
| 119 | end | ||
| 120 | local two | ||
| 121 | do | ||
| 122 | local _obj_0 = dict[2] | ||
| 123 | if _obj_0 ~= nil then | ||
| 124 | two = _obj_0[2] | ||
| 125 | end | ||
| 126 | end | ||
| 127 | local three | ||
| 128 | do | ||
| 129 | local _obj_0 = dict[2] | ||
| 130 | if _obj_0 ~= nil then | ||
| 131 | three = _obj_0[3] | ||
| 132 | end | ||
| 133 | end | ||
| 134 | local c | ||
| 135 | do | ||
| 136 | local _obj_0 = dict.a | ||
| 137 | if _obj_0 ~= nil then | ||
| 138 | do | ||
| 139 | local _obj_1 = _obj_0.b | ||
| 140 | if _obj_1 ~= nil then | ||
| 141 | c = _obj_1.c | ||
| 142 | end | ||
| 143 | end | ||
| 144 | end | ||
| 145 | end | ||
| 146 | local z | ||
| 147 | do | ||
| 148 | local _obj_0 = dict.x | ||
| 149 | if _obj_0 ~= nil then | ||
| 150 | do | ||
| 151 | local _obj_1 = _obj_0.y | ||
| 152 | if _obj_1 ~= nil then | ||
| 153 | z = _obj_1.z | ||
| 154 | end | ||
| 155 | end | ||
| 156 | end | ||
| 157 | end | ||
| 158 | if first ~= nil and one ~= nil and two ~= nil and three ~= nil and c ~= nil and z ~= nil then | ||
| 159 | print(first, one, two, three, c, z) | ||
| 160 | end | ||
| 161 | end | ||
| 162 | end | ||
| 163 | end | ||
| 164 | do | ||
| 165 | local items = { | ||
| 166 | { | ||
| 167 | x = 100, | ||
| 168 | y = 200 | ||
| 169 | }, | ||
| 170 | { | ||
| 171 | width = 300, | ||
| 172 | height = 400 | ||
| 173 | }, | ||
| 174 | false | ||
| 175 | } | ||
| 176 | for _index_0 = 1, #items do | ||
| 177 | local item = items[_index_0] | ||
| 178 | do | ||
| 179 | local _tab_0 = "table" == type(item) | ||
| 180 | local _match_0 = false | ||
| 181 | if _tab_0 then | ||
| 182 | local x = item.x | ||
| 183 | local y = item.y | ||
| 184 | if x ~= nil and y ~= nil then | ||
| 185 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | ||
| 186 | _match_0 = true | ||
| 187 | end | ||
| 188 | end | ||
| 189 | if not _match_0 then | ||
| 190 | local _match_1 = false | ||
| 191 | if _tab_0 then | ||
| 192 | local width = item.width | ||
| 193 | local height = item.height | ||
| 194 | if width ~= nil and height ~= nil then | ||
| 195 | print("Size " .. tostring(width) .. ", " .. tostring(height)) | ||
| 196 | _match_1 = true | ||
| 197 | end | ||
| 198 | end | ||
| 199 | if not _match_1 then | ||
| 200 | if false == item then | ||
| 201 | print("None") | ||
| 202 | else | ||
| 203 | local _match_2 = false | ||
| 204 | if _tab_0 then | ||
| 205 | local cls = item.__class | ||
| 206 | if cls ~= nil then | ||
| 207 | if ClassA == cls then | ||
| 208 | print("Object A") | ||
| 209 | elseif ClassB == cls then | ||
| 210 | print("Object B") | ||
| 211 | end | ||
| 212 | _match_2 = true | ||
| 213 | end | ||
| 214 | end | ||
| 215 | if not _match_2 then | ||
| 216 | if _tab_0 then | ||
| 217 | local mt = getmetatable(item) | ||
| 218 | if mt ~= nil then | ||
| 219 | print("A table with metatable") | ||
| 220 | end | ||
| 221 | else | ||
| 222 | print("item not accepted!") | ||
| 223 | end | ||
| 224 | end | ||
| 225 | end | ||
| 226 | end | ||
| 227 | end | ||
| 228 | end | ||
| 229 | end | ||
| 230 | end | ||
| 231 | do | ||
| 232 | local tb = { } | ||
| 233 | do | ||
| 234 | local _tab_0 = "table" == type(tb) | ||
| 235 | if _tab_0 then | ||
| 236 | local a = tb.a | ||
| 237 | local b = tb.b | ||
| 238 | if a == nil then | ||
| 239 | a = 1 | ||
| 240 | end | ||
| 241 | if b == nil then | ||
| 242 | b = 2 | ||
| 243 | end | ||
| 244 | if a ~= nil and b ~= nil then | ||
| 245 | print(a, b) | ||
| 246 | end | ||
| 247 | end | ||
| 248 | end | ||
| 249 | end | ||
| 250 | do | ||
| 251 | local tb = { | ||
| 252 | x = "abc" | ||
| 253 | } | ||
| 254 | do | ||
| 255 | local _tab_0 = "table" == type(tb) | ||
| 256 | local _match_0 = false | ||
| 257 | if _tab_0 then | ||
| 258 | local x = tb.x | ||
| 259 | local y = tb.y | ||
| 260 | if x ~= nil and y ~= nil then | ||
| 261 | print("x: " .. tostring(x) .. " with y: " .. tostring(y)) | ||
| 262 | _match_0 = true | ||
| 263 | end | ||
| 264 | end | ||
| 265 | if not _match_0 then | ||
| 266 | if _tab_0 then | ||
| 267 | local x = tb.x | ||
| 268 | if x ~= nil then | ||
| 269 | print("x: " .. tostring(x) .. " only") | ||
| 270 | end | ||
| 271 | end | ||
| 272 | end | ||
| 273 | end | ||
| 274 | end | ||
| 275 | do | ||
| 276 | local matched | ||
| 277 | do | ||
| 278 | local _exp_0 = tb | ||
| 279 | if 1 == _exp_0 then | ||
| 280 | matched = "1" | ||
| 281 | else | ||
| 282 | local _tab_0 = "table" == type(_exp_0) | ||
| 283 | local _match_0 = false | ||
| 284 | if _tab_0 then | ||
| 285 | local x = _exp_0.x | ||
| 286 | if x ~= nil then | ||
| 287 | matched = x | ||
| 288 | _match_0 = true | ||
| 289 | end | ||
| 290 | end | ||
| 291 | if not _match_0 then | ||
| 292 | if false == _exp_0 then | ||
| 293 | matched = "false" | ||
| 294 | else | ||
| 295 | matched = nil | ||
| 296 | end | ||
| 297 | end | ||
| 298 | end | ||
| 299 | end | ||
| 300 | end | ||
| 301 | do | ||
| 302 | local _exp_0 = tb | ||
| 303 | if nil == _exp_0 then | ||
| 304 | return "invalid" | ||
| 305 | else | ||
| 306 | do | ||
| 307 | local _tab_0 = "table" == type(_exp_0) | ||
| 308 | local _match_0 = false | ||
| 309 | if _tab_0 then | ||
| 310 | local a = _exp_0.a | ||
| 311 | local b = _exp_0.b | ||
| 312 | if a ~= nil and b ~= nil then | ||
| 313 | return tostring(a + b) | ||
| 314 | _match_0 = true | ||
| 315 | end | ||
| 316 | end | ||
| 317 | if not _match_0 then | ||
| 318 | if 1 == _exp_0 or 2 == _exp_0 or 3 == _exp_0 or 4 == _exp_0 or 5 == _exp_0 then | ||
| 319 | return "number 1 - 5" | ||
| 320 | else | ||
| 321 | if _tab_0 then | ||
| 322 | local alwaysMatch = _exp_0.alwaysMatch | ||
| 323 | if alwaysMatch == nil then | ||
| 324 | alwaysMatch = "fallback" | ||
| 325 | end | ||
| 326 | if alwaysMatch ~= nil then | ||
| 327 | return alwaysMatch | ||
| 328 | end | ||
| 329 | else | ||
| 330 | return "should not reach here" | ||
| 331 | end | ||
| 332 | end | ||
| 333 | end | ||
| 334 | end | ||
| 335 | end | ||
| 87 | end | 336 | end |
| 337 | return nil | ||
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 571c18e..05ac5ef 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -249,8 +249,14 @@ AST_NODE(With) | |||
| 249 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 249 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) |
| 250 | AST_END(With, "with"sv) | 250 | AST_END(With, "with"sv) |
| 251 | 251 | ||
| 252 | AST_NODE(SwitchList) | ||
| 253 | ast_ptr<true, Seperator_t> sep; | ||
| 254 | ast_list<true, Exp_t> exprs; | ||
| 255 | AST_MEMBER(SwitchList, &sep, &exprs) | ||
| 256 | AST_END(SwitchList, "switch_list"sv) | ||
| 257 | |||
| 252 | AST_NODE(SwitchCase) | 258 | AST_NODE(SwitchCase) |
| 253 | ast_ptr<true, ExpList_t> valueList; | 259 | ast_ptr<true, SwitchList_t> valueList; |
| 254 | ast_sel<true, Block_t, Statement_t> body; | 260 | ast_sel<true, Block_t, Statement_t> body; |
| 255 | AST_MEMBER(SwitchCase, &valueList, &body) | 261 | AST_MEMBER(SwitchCase, &valueList, &body) |
| 256 | AST_END(SwitchCase, "switch_case"sv) | 262 | AST_END(SwitchCase, "switch_case"sv) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 84cbf37..468dc23 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -56,7 +56,7 @@ using namespace parserlib; | |||
| 56 | 56 | ||
| 57 | typedef std::list<std::string> str_list; | 57 | typedef std::list<std::string> str_list; |
| 58 | 58 | ||
| 59 | const std::string_view version = "0.12.0"sv; | 59 | const std::string_view version = "0.13.0"sv; |
| 60 | const std::string_view extension = "yue"sv; | 60 | const std::string_view extension = "yue"sv; |
| 61 | 61 | ||
| 62 | class YueCompilerImpl { | 62 | class YueCompilerImpl { |
| @@ -283,15 +283,15 @@ private: | |||
| 283 | }; | 283 | }; |
| 284 | 284 | ||
| 285 | struct DestructItem { | 285 | struct DestructItem { |
| 286 | bool isVariable = false; | 286 | ast_ptr<true, Exp_t> target; |
| 287 | std::string name; | 287 | std::string targetVar; |
| 288 | std::string structure; | 288 | std::string structure; |
| 289 | ast_ptr<true, Exp_t> defVal; | 289 | ast_ptr<true, Exp_t> defVal; |
| 290 | bool isMetatable = false; | ||
| 291 | }; | 290 | }; |
| 292 | 291 | ||
| 293 | struct Destructure { | 292 | struct Destructure { |
| 294 | std::string value; | 293 | ast_ptr<true, ast_node> value; |
| 294 | std::string valueVar; | ||
| 295 | std::list<DestructItem> items; | 295 | std::list<DestructItem> items; |
| 296 | }; | 296 | }; |
| 297 | 297 | ||
| @@ -562,6 +562,13 @@ private: | |||
| 562 | } | 562 | } |
| 563 | break; | 563 | break; |
| 564 | } | 564 | } |
| 565 | case id<SwitchList_t>(): { | ||
| 566 | auto expList = static_cast<SwitchList_t*>(item); | ||
| 567 | if (expList->exprs.size() == 1) { | ||
| 568 | exp = static_cast<Exp_t*>(expList->exprs.front()); | ||
| 569 | } | ||
| 570 | break; | ||
| 571 | } | ||
| 565 | case id<unary_exp_t>(): { | 572 | case id<unary_exp_t>(): { |
| 566 | auto unary = static_cast<unary_exp_t*>(item); | 573 | auto unary = static_cast<unary_exp_t*>(item); |
| 567 | if (unary->expos.size() == 1) { | 574 | if (unary->expos.size() == 1) { |
| @@ -800,7 +807,7 @@ private: | |||
| 800 | return Empty; | 807 | return Empty; |
| 801 | } | 808 | } |
| 802 | 809 | ||
| 803 | std::string singleVariableFrom(ast_node* expList) { | 810 | std::string singleVariableFrom(ast_node* expList, bool accessing) { |
| 804 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; | 811 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; |
| 805 | BLOCK_START | 812 | BLOCK_START |
| 806 | auto value = singleValueFrom(expList); | 813 | auto value = singleValueFrom(expList); |
| @@ -809,9 +816,16 @@ private: | |||
| 809 | BREAK_IF(!chainValue); | 816 | BREAK_IF(!chainValue); |
| 810 | BREAK_IF(chainValue->items.size() != 1); | 817 | BREAK_IF(chainValue->items.size() != 1); |
| 811 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | 818 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); |
| 812 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); | 819 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t, self_t>())); |
| 813 | str_list tmp; | 820 | str_list tmp; |
| 814 | transformCallable(callable, tmp); | 821 | if (accessing) { |
| 822 | transformCallable(callable, tmp); | ||
| 823 | } else { | ||
| 824 | bool lintGlobal = _config.lintGlobalVariable; | ||
| 825 | _config.lintGlobalVariable = false; | ||
| 826 | transformCallable(callable, tmp); | ||
| 827 | _config.lintGlobalVariable = lintGlobal; | ||
| 828 | } | ||
| 815 | return tmp.back(); | 829 | return tmp.back(); |
| 816 | BLOCK_END | 830 | BLOCK_END |
| 817 | return Empty; | 831 | return Empty; |
| @@ -1173,7 +1187,7 @@ private: | |||
| 1173 | _config.lintGlobalVariable = false; | 1187 | _config.lintGlobalVariable = false; |
| 1174 | if (!assignment->action.is<Assign_t>()) return vars; | 1188 | if (!assignment->action.is<Assign_t>()) return vars; |
| 1175 | for (auto exp : assignment->expList->exprs.objects()) { | 1189 | for (auto exp : assignment->expList->exprs.objects()) { |
| 1176 | auto var = singleVariableFrom(exp); | 1190 | auto var = singleVariableFrom(exp, true); |
| 1177 | vars.push_back(var.empty() ? Empty : var); | 1191 | vars.push_back(var.empty() ? Empty : var); |
| 1178 | } | 1192 | } |
| 1179 | _config.lintGlobalVariable = lintGlobal; | 1193 | _config.lintGlobalVariable = lintGlobal; |
| @@ -1185,7 +1199,7 @@ private: | |||
| 1185 | bool lintGlobal = _config.lintGlobalVariable; | 1199 | bool lintGlobal = _config.lintGlobalVariable; |
| 1186 | _config.lintGlobalVariable = false; | 1200 | _config.lintGlobalVariable = false; |
| 1187 | for (auto exp : with->valueList->exprs.objects()) { | 1201 | for (auto exp : with->valueList->exprs.objects()) { |
| 1188 | auto var = singleVariableFrom(exp); | 1202 | auto var = singleVariableFrom(exp, true); |
| 1189 | vars.push_back(var.empty() ? Empty : var); | 1203 | vars.push_back(var.empty() ? Empty : var); |
| 1190 | } | 1204 | } |
| 1191 | _config.lintGlobalVariable = lintGlobal; | 1205 | _config.lintGlobalVariable = lintGlobal; |
| @@ -1241,13 +1255,15 @@ private: | |||
| 1241 | } | 1255 | } |
| 1242 | 1256 | ||
| 1243 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1257 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
| 1244 | auto info = extractDestructureInfo(assignment, true); | 1258 | auto info = extractDestructureInfo(assignment, true, false); |
| 1245 | if (!info.first.empty()) { | 1259 | if (!info.first.empty()) { |
| 1246 | for (const auto& destruct : info.first) { | 1260 | for (const auto& destruct : info.first) { |
| 1247 | str_list defs; | 1261 | str_list defs; |
| 1248 | for (const auto& item : destruct.items) { | 1262 | for (const auto& item : destruct.items) { |
| 1249 | if (item.isVariable && addToScope(item.name)) { | 1263 | if (!item.targetVar.empty()) { |
| 1250 | defs.push_back(item.name); | 1264 | if (addToScope(item.targetVar)) { |
| 1265 | defs.push_back(item.targetVar); | ||
| 1266 | } | ||
| 1251 | } | 1267 | } |
| 1252 | } | 1268 | } |
| 1253 | if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv); | 1269 | if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv); |
| @@ -1282,7 +1298,18 @@ private: | |||
| 1282 | return nullptr; | 1298 | return nullptr; |
| 1283 | } | 1299 | } |
| 1284 | 1300 | ||
| 1285 | void transformAssignment(ExpListAssign_t* assignment, str_list& out) { | 1301 | ast_ptr<false, ExpListAssign_t> assignmentFrom(Exp_t* target, ast_node* value, ast_node* x) { |
| 1302 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 1303 | auto assignList = x->new_ptr<ExpList_t>(); | ||
| 1304 | assignList->exprs.push_back(target); | ||
| 1305 | assignment->expList.set(assignList); | ||
| 1306 | auto assign = x->new_ptr<Assign_t>(); | ||
| 1307 | assign->values.push_back(value); | ||
| 1308 | assignment->action.set(assign); | ||
| 1309 | return assignment; | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | ||
| 1286 | checkAssignable(assignment->expList); | 1313 | checkAssignable(assignment->expList); |
| 1287 | BLOCK_START | 1314 | BLOCK_START |
| 1288 | auto assign = ast_cast<Assign_t>(assignment->action); | 1315 | auto assign = ast_cast<Assign_t>(assignment->action); |
| @@ -1516,7 +1543,7 @@ private: | |||
| 1516 | } | 1543 | } |
| 1517 | } | 1544 | } |
| 1518 | BLOCK_END | 1545 | BLOCK_END |
| 1519 | auto info = extractDestructureInfo(assignment, false); | 1546 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
| 1520 | if (info.first.empty()) { | 1547 | if (info.first.empty()) { |
| 1521 | transformAssignmentCommon(assignment, out); | 1548 | transformAssignmentCommon(assignment, out); |
| 1522 | } else { | 1549 | } else { |
| @@ -1524,126 +1551,165 @@ private: | |||
| 1524 | if (info.second) { | 1551 | if (info.second) { |
| 1525 | transformAssignmentCommon(info.second, temp); | 1552 | transformAssignmentCommon(info.second, temp); |
| 1526 | } | 1553 | } |
| 1554 | auto x = assignment; | ||
| 1527 | for (auto& destruct : info.first) { | 1555 | for (auto& destruct : info.first) { |
| 1528 | std::list<std::pair<std::string, std::string>> leftPairs; | 1556 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; |
| 1557 | bool extraScope = false; | ||
| 1529 | if (destruct.items.size() == 1) { | 1558 | if (destruct.items.size() == 1) { |
| 1530 | auto& pair = destruct.items.front(); | 1559 | auto& pair = destruct.items.front(); |
| 1531 | if (!pair.isVariable && pair.defVal) { | 1560 | if (pair.targetVar.empty() && pair.defVal) { |
| 1532 | auto objVar = getUnusedName("_obj_"sv); | 1561 | extraScope = true; |
| 1533 | leftPairs.push_back({pair.name, objVar}); | 1562 | auto objVar = getUnusedName("_tmp_"sv); |
| 1534 | pair.name = objVar; | 1563 | auto objExp = toAst<Exp_t>(objVar, pair.target); |
| 1535 | pair.isVariable = true; | 1564 | leftPairs.push_back({pair.target, objExp.get()}); |
| 1536 | } | 1565 | pair.target.set(objExp); |
| 1537 | if (pair.isMetatable) { | 1566 | pair.targetVar = objVar; |
| 1538 | if (pair.isVariable) { | 1567 | } else if (auto val = singleValueFrom(destruct.value); val->item.is<ChainValue_t>()) { |
| 1539 | checkConst(pair.name, assignment); | 1568 | auto chainValue = static_cast<ChainValue_t*>(val->item.get()); |
| 1540 | if (addToScope(pair.name)) { | 1569 | int added = 0; |
| 1541 | _buf << indent() << "local "sv << pair.name << nll(assignment); | 1570 | if (!pair.structure.empty()) { |
| 1571 | auto appendChain = toAst<ChainValue_t>("x"s + pair.structure, x); | ||
| 1572 | appendChain->items.pop_front(); | ||
| 1573 | for (auto item : appendChain->items.objects()) { | ||
| 1574 | chainValue->items.push_back(item); | ||
| 1575 | added++; | ||
| 1542 | } | 1576 | } |
| 1543 | } | 1577 | } |
| 1544 | bool isLocalValue = isLocal(destruct.value); | 1578 | auto newAssignment = assignmentFrom(pair.target, destruct.value, x); |
| 1545 | std::string objVar; | 1579 | transformAssignment(newAssignment, temp); |
| 1546 | if (isLocalValue) { | 1580 | while (added > 0) { |
| 1547 | objVar = destruct.value; | 1581 | chainValue->items.pop_back(); |
| 1548 | } else { | 1582 | added--; |
| 1549 | _buf << indent() << "do"sv << nll(assignment); | ||
| 1550 | pushScope(); | ||
| 1551 | objVar = getUnusedName("_obj_"sv); | ||
| 1552 | addToScope(objVar); | ||
| 1553 | _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment); | ||
| 1554 | temp.push_back(clearBuf()); | ||
| 1555 | } | 1583 | } |
| 1556 | auto valueExp = toAst<Exp_t>(objVar + pair.structure, assignment); | 1584 | if (pair.defVal) { |
| 1557 | transformExp(valueExp, temp, ExpUsage::Closure); | 1585 | auto stmt = toAst<Statement_t>(pair.targetVar + "=nil if "s + pair.targetVar + "==nil", pair.defVal); |
| 1558 | _buf << indent() << pair.name << " = "sv << temp.back() << nll(assignment); | 1586 | auto defAssign = stmt->content.as<ExpListAssign_t>(); |
| 1559 | if (!isLocalValue) { | 1587 | auto assign = defAssign->action.as<Assign_t>(); |
| 1560 | popScope(); | 1588 | assign->values.clear(); |
| 1561 | _buf << indent() << "end"sv << nlr(assignment); | 1589 | assign->values.push_back(pair.defVal); |
| 1590 | transformStatement(stmt, temp); | ||
| 1562 | } | 1591 | } |
| 1563 | temp.back() = clearBuf(); | 1592 | continue; |
| 1564 | } else { | ||
| 1565 | _buf << indent(); | ||
| 1566 | if (pair.isVariable) { | ||
| 1567 | checkConst(pair.name, assignment); | ||
| 1568 | if (addToScope(pair.name)) _buf << "local "sv; | ||
| 1569 | } | ||
| 1570 | _buf << pair.name << " = "sv << destruct.value << pair.structure << nll(assignment); | ||
| 1571 | temp.push_back(clearBuf()); | ||
| 1572 | } | 1593 | } |
| 1573 | } else if (_parser.match<Name_t>(destruct.value) && isLocal(destruct.value)) { | 1594 | if (extraScope) { |
| 1574 | str_list defs, names, values; | 1595 | temp.push_back(indent() + "do"s + nll(x)); |
| 1575 | bool isMetatable = false; | 1596 | pushScope(); |
| 1576 | for (auto& item : destruct.items) { | 1597 | } |
| 1577 | if (item.isVariable) { | 1598 | if (!pair.targetVar.empty()) { |
| 1578 | checkConst(item.name, assignment); | 1599 | checkConst(pair.targetVar, x); |
| 1579 | if (addToScope(item.name)) defs.push_back(item.name); | 1600 | if (addToScope(pair.targetVar)) { |
| 1580 | } else if (item.defVal) { | 1601 | _buf << indent() << "local "sv << pair.targetVar << nll(x); |
| 1581 | auto objVar = getUnusedName("_obj_"sv); | 1602 | temp.push_back(clearBuf()); |
| 1582 | addToScope(objVar); | ||
| 1583 | defs.push_back(objVar); | ||
| 1584 | leftPairs.push_back({item.name, objVar}); | ||
| 1585 | item.name = objVar; | ||
| 1586 | } | 1603 | } |
| 1587 | if (item.isMetatable) isMetatable = true; | ||
| 1588 | names.push_back(item.name); | ||
| 1589 | values.push_back(item.structure); | ||
| 1590 | } | 1604 | } |
| 1591 | for (auto& v : values) v.insert(0, destruct.value); | 1605 | bool isLocalValue = isLocal(destruct.valueVar); |
| 1592 | if (isMetatable) { | 1606 | std::string objVar; |
| 1593 | auto newExpList = toAst<ExpList_t>(join(values, ","sv), assignment); | 1607 | if (isLocalValue) { |
| 1594 | transformExpList(newExpList, temp); | 1608 | objVar = destruct.valueVar; |
| 1595 | } else { | 1609 | } else { |
| 1596 | temp.push_back(join(values, ", "sv)); | 1610 | temp.push_back(indent() + "do"s + nll(x)); |
| 1611 | pushScope(); | ||
| 1612 | objVar = getUnusedName("_obj_"sv); | ||
| 1613 | auto newAssignment = assignmentFrom(toAst<Exp_t>(objVar, x), destruct.value, x); | ||
| 1614 | transformAssignment(newAssignment, temp); | ||
| 1597 | } | 1615 | } |
| 1598 | if (defs.empty()) { | 1616 | auto valueExp = toAst<Exp_t>(objVar + pair.structure, x); |
| 1599 | _buf << indent() << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment); | 1617 | auto newAssignment = assignmentFrom(pair.target, valueExp, x); |
| 1600 | } else { | 1618 | transformAssignment(newAssignment, temp); |
| 1601 | _buf << indent() << "local "sv; | 1619 | if (!isLocalValue) { |
| 1602 | if (defs.size() != names.size()) { | 1620 | popScope(); |
| 1603 | _buf << join(defs, ", "sv) << nll(assignment) << indent(); | 1621 | _buf << indent() << "end"sv << nlr(x); |
| 1604 | } | 1622 | temp.push_back(clearBuf()); |
| 1605 | _buf << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment); | ||
| 1606 | } | 1623 | } |
| 1607 | temp.back() = clearBuf(); | ||
| 1608 | } else { | 1624 | } else { |
| 1609 | str_list defs, names, values; | 1625 | str_list values, defs; |
| 1610 | bool isMetatable = false; | 1626 | std::list<Exp_t*> names; |
| 1627 | pushScope(); | ||
| 1611 | for (auto& item : destruct.items) { | 1628 | for (auto& item : destruct.items) { |
| 1612 | if (item.isVariable) { | 1629 | if (!item.targetVar.empty()) { |
| 1613 | checkConst(item.name, assignment); | 1630 | if (!isDefined(item.targetVar)) { |
| 1614 | if (addToScope(item.name)) defs.push_back(item.name); | 1631 | defs.push_back(item.targetVar); |
| 1632 | } | ||
| 1615 | } else if (item.defVal) { | 1633 | } else if (item.defVal) { |
| 1616 | auto objVar = getUnusedName("_obj_"sv); | 1634 | extraScope = true; |
| 1635 | auto objVar = getUnusedName("_tmp_"sv); | ||
| 1617 | addToScope(objVar); | 1636 | addToScope(objVar); |
| 1618 | defs.push_back(objVar); | 1637 | auto objExp = toAst<Exp_t>(objVar, item.target); |
| 1619 | leftPairs.push_back({item.name, objVar}); | 1638 | leftPairs.push_back({item.target, objExp.get()}); |
| 1620 | item.name = objVar; | 1639 | item.target.set(objExp); |
| 1640 | item.targetVar = objVar; | ||
| 1621 | } | 1641 | } |
| 1622 | if (item.isMetatable) isMetatable = true; | 1642 | names.push_back(item.target); |
| 1623 | names.push_back(item.name); | ||
| 1624 | values.push_back(item.structure); | 1643 | values.push_back(item.structure); |
| 1625 | } | 1644 | } |
| 1626 | if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv) << nll(assignment); | 1645 | popScope(); |
| 1627 | _buf << indent() << "do"sv << nll(assignment); | 1646 | if (_parser.match<Name_t>(destruct.valueVar) && isLocal(destruct.valueVar)) { |
| 1628 | pushScope(); | 1647 | for (auto& v : values) { |
| 1629 | auto objVar = getUnusedName("_obj_"sv); | 1648 | v.insert(0, destruct.valueVar); |
| 1630 | addToScope(objVar); | 1649 | } |
| 1631 | for (auto& v : values) v.insert(0, objVar); | 1650 | if (extraScope) { |
| 1632 | if (isMetatable) { | 1651 | if (!defs.empty()) { |
| 1633 | auto newExpList = toAst<ExpList_t>(join(values, ","sv), assignment); | 1652 | for (const auto& def : defs) { |
| 1634 | transformExpList(newExpList, temp); | 1653 | checkConst(def, x); |
| 1654 | addToScope(def); | ||
| 1655 | } | ||
| 1656 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | ||
| 1657 | } | ||
| 1658 | temp.push_back(indent() + "do"s + nll(x)); | ||
| 1659 | pushScope(); | ||
| 1660 | } | ||
| 1635 | } else { | 1661 | } else { |
| 1636 | temp.push_back(join(values, ", "sv)); | 1662 | if (!defs.empty()) { |
| 1663 | for (const auto& def : defs) { | ||
| 1664 | checkConst(def, x); | ||
| 1665 | addToScope(def); | ||
| 1666 | } | ||
| 1667 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | ||
| 1668 | } | ||
| 1669 | extraScope = true; | ||
| 1670 | temp.push_back(indent() + "do"s + nll(x)); | ||
| 1671 | pushScope(); | ||
| 1672 | auto valVar = getUnusedName("_obj_"sv); | ||
| 1673 | auto targetVar = toAst<Exp_t>(valVar, destruct.value); | ||
| 1674 | auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value); | ||
| 1675 | transformAssignment(newAssignment, temp); | ||
| 1676 | for (auto& v : values) { | ||
| 1677 | v.insert(0, valVar); | ||
| 1678 | } | ||
| 1679 | } | ||
| 1680 | if (optionalDestruct) { | ||
| 1681 | while (!names.empty()) { | ||
| 1682 | auto name = names.front(); | ||
| 1683 | names.pop_front(); | ||
| 1684 | auto value = values.front(); | ||
| 1685 | values.pop_front(); | ||
| 1686 | auto valueList = toAst<ExpList_t>(value, x); | ||
| 1687 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 1688 | auto assignList = x->new_ptr<ExpList_t>(); | ||
| 1689 | assignList->exprs.push_back(name); | ||
| 1690 | newAssignment->expList.set(assignList); | ||
| 1691 | auto assign = x->new_ptr<Assign_t>(); | ||
| 1692 | assign->values.dup(valueList->exprs); | ||
| 1693 | newAssignment->action.set(assign); | ||
| 1694 | transformAssignment(newAssignment, temp); | ||
| 1695 | } | ||
| 1696 | } else { | ||
| 1697 | auto valueList = toAst<ExpList_t>(join(values, ","sv), x); | ||
| 1698 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 1699 | auto assignList = x->new_ptr<ExpList_t>(); | ||
| 1700 | for (auto name : names) { | ||
| 1701 | assignList->exprs.push_back(name); | ||
| 1702 | } | ||
| 1703 | newAssignment->expList.set(assignList); | ||
| 1704 | auto assign = x->new_ptr<Assign_t>(); | ||
| 1705 | assign->values.dup(valueList->exprs); | ||
| 1706 | newAssignment->action.set(assign); | ||
| 1707 | transformAssignment(newAssignment, temp); | ||
| 1637 | } | 1708 | } |
| 1638 | _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment); | ||
| 1639 | _buf << indent() << join(names, ", "sv) << " = "sv << temp.back() << nll(assignment); | ||
| 1640 | popScope(); | ||
| 1641 | _buf << indent() << "end"sv << nll(assignment); | ||
| 1642 | temp.back() = clearBuf(); | ||
| 1643 | } | 1709 | } |
| 1644 | for (const auto& item : destruct.items) { | 1710 | for (const auto& item : destruct.items) { |
| 1645 | if (item.defVal) { | 1711 | if (item.defVal) { |
| 1646 | auto stmt = toAst<Statement_t>(item.name + "=nil if "s + item.name + "==nil", item.defVal); | 1712 | auto stmt = toAst<Statement_t>(item.targetVar + "=nil if "s + item.targetVar + "==nil", item.defVal); |
| 1647 | auto defAssign = stmt->content.as<ExpListAssign_t>(); | 1713 | auto defAssign = stmt->content.as<ExpListAssign_t>(); |
| 1648 | auto assign = defAssign->action.as<Assign_t>(); | 1714 | auto assign = defAssign->action.as<Assign_t>(); |
| 1649 | assign->values.clear(); | 1715 | assign->values.clear(); |
| @@ -1652,9 +1718,14 @@ private: | |||
| 1652 | } | 1718 | } |
| 1653 | } | 1719 | } |
| 1654 | for (const auto& item : leftPairs) { | 1720 | for (const auto& item : leftPairs) { |
| 1655 | _buf << indent() << item.first << " = "sv << item.second << nll(assignment); | 1721 | auto newAssignment = assignmentFrom(item.first, item.second, x); |
| 1722 | transformAssignment(newAssignment, temp); | ||
| 1723 | } | ||
| 1724 | if (extraScope) { | ||
| 1725 | popScope(); | ||
| 1726 | _buf << indent() << "end"sv << nlr(x); | ||
| 1727 | temp.push_back(clearBuf()); | ||
| 1656 | } | 1728 | } |
| 1657 | temp.push_back(clearBuf()); | ||
| 1658 | } | 1729 | } |
| 1659 | out.push_back(join(temp)); | 1730 | out.push_back(join(temp)); |
| 1660 | } | 1731 | } |
| @@ -1671,8 +1742,9 @@ private: | |||
| 1671 | } | 1742 | } |
| 1672 | } | 1743 | } |
| 1673 | 1744 | ||
| 1674 | std::list<DestructItem> destructFromExp(ast_node* node) { | 1745 | std::list<DestructItem> destructFromExp(ast_node* node, bool optional) { |
| 1675 | const node_container* tableItems = nullptr; | 1746 | const node_container* tableItems = nullptr; |
| 1747 | auto sep = optional ? "?"s : Empty; | ||
| 1676 | switch (node->getId()) { | 1748 | switch (node->getId()) { |
| 1677 | case id<Exp_t>(): { | 1749 | case id<Exp_t>(): { |
| 1678 | auto item = singleValueFrom(node)->item.get(); | 1750 | auto item = singleValueFrom(node)->item.get(); |
| @@ -1713,27 +1785,18 @@ private: | |||
| 1713 | auto item = value->item.get(); | 1785 | auto item = value->item.get(); |
| 1714 | if (ast_is<simple_table_t>(item) || | 1786 | if (ast_is<simple_table_t>(item) || |
| 1715 | item->getByPath<TableLit_t>()) { | 1787 | item->getByPath<TableLit_t>()) { |
| 1716 | auto subPairs = destructFromExp(pair); | 1788 | auto subPairs = destructFromExp(pair, optional); |
| 1717 | for (auto& p : subPairs) { | 1789 | for (auto& p : subPairs) { |
| 1718 | pairs.push_back({p.isVariable, p.name, | 1790 | pairs.push_back({p.target, p.targetVar, |
| 1719 | '[' + std::to_string(index) + ']' + p.structure, | 1791 | '[' + std::to_string(index) + ']' + sep + p.structure, |
| 1720 | p.defVal, p.isMetatable}); | 1792 | p.defVal}); |
| 1721 | } | 1793 | } |
| 1722 | } else { | 1794 | } else { |
| 1723 | bool lintGlobal = _config.lintGlobalVariable; | ||
| 1724 | _config.lintGlobalVariable = false; | ||
| 1725 | auto exp = static_cast<Exp_t*>(pair); | 1795 | auto exp = static_cast<Exp_t*>(pair); |
| 1726 | auto varName = singleVariableFrom(exp); | 1796 | auto varName = singleVariableFrom(exp, false); |
| 1727 | if (varName == "_"sv) break; | 1797 | if (varName == "_"sv) break; |
| 1728 | bool isVariable = !varName.empty(); | ||
| 1729 | if (!isVariable) { | ||
| 1730 | str_list temp; | ||
| 1731 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1732 | varName = std::move(temp.back()); | ||
| 1733 | } | ||
| 1734 | _config.lintGlobalVariable = lintGlobal; | ||
| 1735 | pairs.push_back({ | 1798 | pairs.push_back({ |
| 1736 | isVariable, | 1799 | exp, |
| 1737 | varName, | 1800 | varName, |
| 1738 | '[' + std::to_string(index) + ']', | 1801 | '[' + std::to_string(index) + ']', |
| 1739 | nullptr | 1802 | nullptr |
| @@ -1744,11 +1807,7 @@ private: | |||
| 1744 | case id<variable_pair_t>(): { | 1807 | case id<variable_pair_t>(): { |
| 1745 | auto vp = static_cast<variable_pair_t*>(pair); | 1808 | auto vp = static_cast<variable_pair_t*>(pair); |
| 1746 | auto name = _parser.toString(vp->name); | 1809 | auto name = _parser.toString(vp->name); |
| 1747 | if (LuaKeywords.find(name) != LuaKeywords.end()) { | 1810 | pairs.push_back({toAst<Exp_t>(name, vp).get(), name, '.' + name, nullptr}); |
| 1748 | pairs.push_back({true, name, "[\""s + name + "\"]"s, nullptr}); | ||
| 1749 | } else { | ||
| 1750 | pairs.push_back({true, name, '.' + name, nullptr}); | ||
| 1751 | } | ||
| 1752 | break; | 1811 | break; |
| 1753 | } | 1812 | } |
| 1754 | case id<normal_pair_t>(): { | 1813 | case id<normal_pair_t>(): { |
| @@ -1769,29 +1828,19 @@ private: | |||
| 1769 | auto item = singleValueFrom(exp)->item.get(); | 1828 | auto item = singleValueFrom(exp)->item.get(); |
| 1770 | if (ast_is<simple_table_t>(item) || | 1829 | if (ast_is<simple_table_t>(item) || |
| 1771 | item->getByPath<TableLit_t>()) { | 1830 | item->getByPath<TableLit_t>()) { |
| 1772 | auto subPairs = destructFromExp(exp); | 1831 | auto subPairs = destructFromExp(exp, optional); |
| 1773 | for (auto& p : subPairs) { | 1832 | for (auto& p : subPairs) { |
| 1774 | pairs.push_back({ | 1833 | pairs.push_back({ |
| 1775 | p.isVariable, | 1834 | p.target, |
| 1776 | p.name, | 1835 | p.targetVar, |
| 1777 | keyName + p.structure, | 1836 | keyName + sep + p.structure, |
| 1778 | p.defVal, | 1837 | p.defVal |
| 1779 | p.isMetatable | ||
| 1780 | }); | 1838 | }); |
| 1781 | } | 1839 | } |
| 1782 | } else { | 1840 | } else { |
| 1783 | bool lintGlobal = _config.lintGlobalVariable; | 1841 | auto varName = singleVariableFrom(exp, false); |
| 1784 | _config.lintGlobalVariable = false; | ||
| 1785 | auto varName = singleVariableFrom(exp); | ||
| 1786 | bool isVariable = !varName.empty(); | ||
| 1787 | if (!isVariable) { | ||
| 1788 | str_list temp; | ||
| 1789 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1790 | varName = std::move(temp.back()); | ||
| 1791 | } | ||
| 1792 | _config.lintGlobalVariable = lintGlobal; | ||
| 1793 | pairs.push_back({ | 1842 | pairs.push_back({ |
| 1794 | isVariable, | 1843 | exp, |
| 1795 | varName, | 1844 | varName, |
| 1796 | keyName, | 1845 | keyName, |
| 1797 | nullptr | 1846 | nullptr |
| @@ -1800,14 +1849,13 @@ private: | |||
| 1800 | break; | 1849 | break; |
| 1801 | } | 1850 | } |
| 1802 | if (np->value.is<TableBlock_t>()) { | 1851 | if (np->value.is<TableBlock_t>()) { |
| 1803 | auto subPairs = destructFromExp(np->value); | 1852 | auto subPairs = destructFromExp(np->value, optional); |
| 1804 | for (auto& p : subPairs) { | 1853 | for (auto& p : subPairs) { |
| 1805 | pairs.push_back({ | 1854 | pairs.push_back({ |
| 1806 | p.isVariable, | 1855 | p.target, |
| 1807 | p.name, | 1856 | p.targetVar, |
| 1808 | keyName + p.structure, | 1857 | keyName + sep + p.structure, |
| 1809 | p.defVal, | 1858 | p.defVal |
| 1810 | p.isMetatable | ||
| 1811 | }); | 1859 | }); |
| 1812 | } | 1860 | } |
| 1813 | } | 1861 | } |
| @@ -1816,14 +1864,13 @@ private: | |||
| 1816 | case id<TableBlockIndent_t>(): { | 1864 | case id<TableBlockIndent_t>(): { |
| 1817 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 1865 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
| 1818 | ++index; | 1866 | ++index; |
| 1819 | auto subPairs = destructFromExp(tb); | 1867 | auto subPairs = destructFromExp(tb, optional); |
| 1820 | for (auto& p : subPairs) { | 1868 | for (auto& p : subPairs) { |
| 1821 | pairs.push_back({ | 1869 | pairs.push_back({ |
| 1822 | p.isVariable, | 1870 | p.target, |
| 1823 | p.name, | 1871 | p.targetVar, |
| 1824 | '[' + std::to_string(index) + ']' + p.structure, | 1872 | '[' + std::to_string(index) + ']' + sep + p.structure, |
| 1825 | p.defVal, | 1873 | p.defVal |
| 1826 | p.isMetatable | ||
| 1827 | }); | 1874 | }); |
| 1828 | } | 1875 | } |
| 1829 | break; | 1876 | break; |
| @@ -1841,18 +1888,9 @@ private: | |||
| 1841 | item->getByPath<TableLit_t>()) { | 1888 | item->getByPath<TableLit_t>()) { |
| 1842 | throw std::logic_error(_info.errorMessage("invalid use of default value"sv, dp->defVal)); | 1889 | throw std::logic_error(_info.errorMessage("invalid use of default value"sv, dp->defVal)); |
| 1843 | } else { | 1890 | } else { |
| 1844 | bool lintGlobal = _config.lintGlobalVariable; | 1891 | auto varName = singleVariableFrom(exp, false); |
| 1845 | _config.lintGlobalVariable = false; | ||
| 1846 | auto varName = singleVariableFrom(exp); | ||
| 1847 | bool isVariable = !varName.empty(); | ||
| 1848 | if (!isVariable) { | ||
| 1849 | str_list temp; | ||
| 1850 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1851 | varName = std::move(temp.back()); | ||
| 1852 | } | ||
| 1853 | _config.lintGlobalVariable = lintGlobal; | ||
| 1854 | pairs.push_back({ | 1892 | pairs.push_back({ |
| 1855 | isVariable, | 1893 | exp, |
| 1856 | varName, | 1894 | varName, |
| 1857 | '[' + std::to_string(index) + ']', | 1895 | '[' + std::to_string(index) + ']', |
| 1858 | dp->defVal | 1896 | dp->defVal |
| @@ -1872,27 +1910,18 @@ private: | |||
| 1872 | keyName = "."s + keyName; | 1910 | keyName = "."s + keyName; |
| 1873 | } | 1911 | } |
| 1874 | } | 1912 | } |
| 1875 | if (auto exp = dp->value.as<Exp_t>()) { | 1913 | if (auto exp = dp->value.get()) { |
| 1876 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); | 1914 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); |
| 1877 | bool lintGlobal = _config.lintGlobalVariable; | 1915 | auto varName = singleVariableFrom(exp, false); |
| 1878 | _config.lintGlobalVariable = false; | ||
| 1879 | auto varName = singleVariableFrom(exp); | ||
| 1880 | bool isVariable = !varName.empty(); | ||
| 1881 | if (!isVariable) { | ||
| 1882 | str_list temp; | ||
| 1883 | transformExp(exp, temp, ExpUsage::Closure); | ||
| 1884 | varName = std::move(temp.back()); | ||
| 1885 | } | ||
| 1886 | _config.lintGlobalVariable = lintGlobal; | ||
| 1887 | pairs.push_back({ | 1916 | pairs.push_back({ |
| 1888 | isVariable, | 1917 | exp, |
| 1889 | varName, | 1918 | varName, |
| 1890 | keyName, | 1919 | keyName, |
| 1891 | dp->defVal | 1920 | dp->defVal |
| 1892 | }); | 1921 | }); |
| 1893 | } else { | 1922 | } else { |
| 1894 | pairs.push_back({ | 1923 | pairs.push_back({ |
| 1895 | true, | 1924 | toAst<Exp_t>(valueStr, dp).get(), |
| 1896 | valueStr, | 1925 | valueStr, |
| 1897 | keyName, | 1926 | keyName, |
| 1898 | dp->defVal | 1927 | dp->defVal |
| @@ -1910,8 +1939,7 @@ private: | |||
| 1910 | newPair->key.set(newKey); | 1939 | newPair->key.set(newKey); |
| 1911 | if (newPair->value) { | 1940 | if (newPair->value) { |
| 1912 | newPair->value.set(mp->value); | 1941 | newPair->value.set(mp->value); |
| 1913 | } | 1942 | } else { |
| 1914 | else { | ||
| 1915 | newPair->value.set(toAst<Exp_t>(key, mp->key)); | 1943 | newPair->value.set(toAst<Exp_t>(key, mp->key)); |
| 1916 | } | 1944 | } |
| 1917 | } else { | 1945 | } else { |
| @@ -1959,14 +1987,13 @@ private: | |||
| 1959 | simpleValue->value.set(subMetaDestruct); | 1987 | simpleValue->value.set(subMetaDestruct); |
| 1960 | auto value = subMetaDestruct->new_ptr<Value_t>(); | 1988 | auto value = subMetaDestruct->new_ptr<Value_t>(); |
| 1961 | value->item.set(simpleValue); | 1989 | value->item.set(simpleValue); |
| 1962 | auto subPairs = destructFromExp(newExp(value, subMetaDestruct)); | 1990 | auto subPairs = destructFromExp(newExp(value, subMetaDestruct), optional); |
| 1963 | for (const auto& p : subPairs) { | 1991 | for (const auto& p : subPairs) { |
| 1964 | pairs.push_back({ | 1992 | pairs.push_back({ |
| 1965 | p.isVariable, | 1993 | p.target, |
| 1966 | p.name, | 1994 | p.targetVar, |
| 1967 | ".#"s + p.structure, | 1995 | ".#"s + sep + p.structure, |
| 1968 | p.defVal, | 1996 | p.defVal |
| 1969 | true | ||
| 1970 | }); | 1997 | }); |
| 1971 | } | 1998 | } |
| 1972 | } | 1999 | } |
| @@ -1974,7 +2001,7 @@ private: | |||
| 1974 | } | 2001 | } |
| 1975 | 2002 | ||
| 1976 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 2003 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> |
| 1977 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly) { | 2004 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { |
| 1978 | auto x = assignment; | 2005 | auto x = assignment; |
| 1979 | std::list<Destructure> destructs; | 2006 | std::list<Destructure> destructs; |
| 1980 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; | 2007 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; |
| @@ -1993,10 +2020,10 @@ private: | |||
| 1993 | while (values.size() < size) values.emplace_back(nullNode); | 2020 | while (values.size() < size) values.emplace_back(nullNode); |
| 1994 | } | 2021 | } |
| 1995 | using iter = node_container::iterator; | 2022 | using iter = node_container::iterator; |
| 1996 | std::vector<std::pair<iter,iter>> destructPairs; | 2023 | std::vector<std::pair<iter, iter>> destructPairs; |
| 1997 | ast_list<false, ast_node> valueItems; | 2024 | ast_list<false, ast_node> valueItems; |
| 1998 | if (!varDefOnly) pushScope(); | ||
| 1999 | str_list temp; | 2025 | str_list temp; |
| 2026 | pushScope(); | ||
| 2000 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { | 2027 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { |
| 2001 | auto expr = *i; | 2028 | auto expr = *i; |
| 2002 | auto value = singleValueFrom(expr); | 2029 | auto value = singleValueFrom(expr); |
| @@ -2019,7 +2046,7 @@ private: | |||
| 2019 | } else { | 2046 | } else { |
| 2020 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); | 2047 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); |
| 2021 | } | 2048 | } |
| 2022 | destructPairs.push_back({i,j}); | 2049 | destructPairs.push_back({i, j}); |
| 2023 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); | 2050 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); |
| 2024 | auto subMetaDestruct = destructNode->new_ptr<TableLit_t>(); | 2051 | auto subMetaDestruct = destructNode->new_ptr<TableLit_t>(); |
| 2025 | const node_container* dlist = nullptr; | 2052 | const node_container* dlist = nullptr; |
| @@ -2103,15 +2130,14 @@ private: | |||
| 2103 | if (!tab->values.empty()) { | 2130 | if (!tab->values.empty()) { |
| 2104 | auto& destruct = destructs.emplace_back(); | 2131 | auto& destruct = destructs.emplace_back(); |
| 2105 | if (!varDefOnly) { | 2132 | if (!varDefOnly) { |
| 2106 | transformAssignItem(valueItems.back(), temp); | 2133 | destruct.value = valueItems.back(); |
| 2107 | destruct.value = std::move(temp.back()); | 2134 | destruct.valueVar = singleVariableFrom(destruct.value, false); |
| 2108 | temp.pop_back(); | ||
| 2109 | } | 2135 | } |
| 2110 | auto simpleValue = tab->new_ptr<SimpleValue_t>(); | 2136 | auto simpleValue = tab->new_ptr<SimpleValue_t>(); |
| 2111 | simpleValue->value.set(tab); | 2137 | simpleValue->value.set(tab); |
| 2112 | auto value = tab->new_ptr<Value_t>(); | 2138 | auto value = tab->new_ptr<Value_t>(); |
| 2113 | value->item.set(simpleValue); | 2139 | value->item.set(simpleValue); |
| 2114 | auto pairs = destructFromExp(newExp(value, expr)); | 2140 | auto pairs = destructFromExp(newExp(value, expr), optional); |
| 2115 | if (pairs.empty()) { | 2141 | if (pairs.empty()) { |
| 2116 | throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); | 2142 | throw std::logic_error(_info.errorMessage("expect items to be destructured"sv, tab)); |
| 2117 | } | 2143 | } |
| @@ -2122,18 +2148,34 @@ private: | |||
| 2122 | item.structure.clear(); | 2148 | item.structure.clear(); |
| 2123 | } | 2149 | } |
| 2124 | } else if (tab == subMetaDestruct.get()) { | 2150 | } else if (tab == subMetaDestruct.get()) { |
| 2125 | destruct.value.insert(0, globalVar("getmetatable"sv, tab) + '('); | 2151 | auto p = destruct.value.get(); |
| 2126 | destruct.value.append(")"sv); | 2152 | auto chainValue = toAst<ChainValue_t>("getmetatable()", p); |
| 2153 | static_cast<Invoke_t*>(chainValue->items.back())->args.push_back(destruct.value); | ||
| 2154 | auto value = p->new_ptr<Value_t>(); | ||
| 2155 | value->item.set(chainValue); | ||
| 2156 | auto exp = newExp(value, p); | ||
| 2157 | destruct.value.set(exp); | ||
| 2158 | destruct.valueVar.clear(); | ||
| 2127 | } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) { | 2159 | } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) { |
| 2128 | destruct.value.insert(0, "("sv); | 2160 | auto p = destruct.value.get(); |
| 2129 | destruct.value.append(")"sv); | 2161 | auto parens = p->new_ptr<Parens_t>(); |
| 2162 | parens->expr.set(p); | ||
| 2163 | auto callable = p->new_ptr<Callable_t>(); | ||
| 2164 | callable->item.set(parens); | ||
| 2165 | auto chainValue = p->new_ptr<ChainValue_t>(); | ||
| 2166 | chainValue->items.push_back(callable); | ||
| 2167 | auto value = p->new_ptr<Value_t>(); | ||
| 2168 | value->item.set(chainValue); | ||
| 2169 | auto exp = newExp(value, p); | ||
| 2170 | destruct.value.set(exp); | ||
| 2171 | destruct.valueVar.clear(); | ||
| 2130 | } | 2172 | } |
| 2131 | } | 2173 | } |
| 2132 | } | 2174 | } |
| 2133 | } | 2175 | } |
| 2134 | } | 2176 | } |
| 2135 | } | 2177 | } |
| 2136 | if (!varDefOnly) popScope(); | 2178 | popScope(); |
| 2137 | for (const auto& p : destructPairs) { | 2179 | for (const auto& p : destructPairs) { |
| 2138 | exprs.erase(p.first); | 2180 | exprs.erase(p.first); |
| 2139 | values.erase(p.second); | 2181 | values.erase(p.second); |
| @@ -2211,7 +2253,7 @@ private: | |||
| 2211 | BLOCK_START | 2253 | BLOCK_START |
| 2212 | auto exp = ast_cast<Exp_t>(item); | 2254 | auto exp = ast_cast<Exp_t>(item); |
| 2213 | BREAK_IF(!exp); | 2255 | BREAK_IF(!exp); |
| 2214 | auto var = singleVariableFrom(exp); | 2256 | auto var = singleVariableFrom(exp, true); |
| 2215 | BREAK_IF(!var.empty()); | 2257 | BREAK_IF(!var.empty()); |
| 2216 | auto upVar = getUnusedName("_update_"sv); | 2258 | auto upVar = getUnusedName("_update_"sv); |
| 2217 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2259 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -2373,15 +2415,12 @@ private: | |||
| 2373 | if (asmt) { | 2415 | if (asmt) { |
| 2374 | ast_ptr<false, ast_node> exp = asmt->expList->exprs.front(); | 2416 | ast_ptr<false, ast_node> exp = asmt->expList->exprs.front(); |
| 2375 | auto x = exp; | 2417 | auto x = exp; |
| 2376 | bool lintGlobal = _config.lintGlobalVariable; | 2418 | auto var = singleVariableFrom(exp, false); |
| 2377 | _config.lintGlobalVariable = false; | ||
| 2378 | auto var = singleVariableFrom(exp); | ||
| 2379 | _config.lintGlobalVariable = lintGlobal; | ||
| 2380 | if (var.empty() || isGlobal(var)) { | 2419 | if (var.empty() || isGlobal(var)) { |
| 2381 | storingValue = true; | 2420 | storingValue = true; |
| 2382 | auto desVar = getUnusedName("_des_"sv); | 2421 | auto desVar = getUnusedName("_des_"sv); |
| 2383 | if (asmt->assign->values.objects().size() == 1) { | 2422 | if (asmt->assign->values.objects().size() == 1) { |
| 2384 | auto var = singleVariableFrom(asmt->assign->values.objects().front()); | 2423 | auto var = singleVariableFrom(asmt->assign->values.objects().front(), true); |
| 2385 | if (!var.empty() && isLocal(var)) { | 2424 | if (!var.empty() && isLocal(var)) { |
| 2386 | desVar = var; | 2425 | desVar = var; |
| 2387 | storingValue = false; | 2426 | storingValue = false; |
| @@ -2524,10 +2563,7 @@ private: | |||
| 2524 | } | 2563 | } |
| 2525 | bool findPlaceHolder = false; | 2564 | bool findPlaceHolder = false; |
| 2526 | for (auto a : args->objects()) { | 2565 | for (auto a : args->objects()) { |
| 2527 | bool lintGlobal = _config.lintGlobalVariable; | 2566 | auto name = singleVariableFrom(a, false); |
| 2528 | _config.lintGlobalVariable = false; | ||
| 2529 | auto name = singleVariableFrom(a); | ||
| 2530 | _config.lintGlobalVariable = lintGlobal; | ||
| 2531 | if (name == "_"sv) { | 2567 | if (name == "_"sv) { |
| 2532 | if (!findPlaceHolder) { | 2568 | if (!findPlaceHolder) { |
| 2533 | args->swap(a, arg); | 2569 | args->swap(a, arg); |
| @@ -2643,7 +2679,7 @@ private: | |||
| 2643 | funcStart = &temp.emplace_back(); | 2679 | funcStart = &temp.emplace_back(); |
| 2644 | pushScope(); | 2680 | pushScope(); |
| 2645 | } | 2681 | } |
| 2646 | auto objVar = singleVariableFrom(left); | 2682 | auto objVar = singleVariableFrom(left, true); |
| 2647 | auto prepareValue = [&](bool forAssignment = false) { | 2683 | auto prepareValue = [&](bool forAssignment = false) { |
| 2648 | if (objVar.empty() || !isLocal(objVar)) { | 2684 | if (objVar.empty() || !isLocal(objVar)) { |
| 2649 | if (forAssignment) { | 2685 | if (forAssignment) { |
| @@ -2953,10 +2989,7 @@ private: | |||
| 2953 | } | 2989 | } |
| 2954 | bool findPlaceHolder = false; | 2990 | bool findPlaceHolder = false; |
| 2955 | for (auto a : args->objects()) { | 2991 | for (auto a : args->objects()) { |
| 2956 | bool lintGlobal = _config.lintGlobalVariable; | 2992 | auto name = singleVariableFrom(a, false); |
| 2957 | _config.lintGlobalVariable = false; | ||
| 2958 | auto name = singleVariableFrom(a); | ||
| 2959 | _config.lintGlobalVariable = lintGlobal; | ||
| 2960 | if (name == "_"sv) { | 2993 | if (name == "_"sv) { |
| 2961 | if (!findPlaceHolder) { | 2994 | if (!findPlaceHolder) { |
| 2962 | args->swap(a, arg); | 2995 | args->swap(a, arg); |
| @@ -3040,14 +3073,14 @@ private: | |||
| 3040 | any->decls.push_back(var); | 3073 | any->decls.push_back(var); |
| 3041 | } | 3074 | } |
| 3042 | } | 3075 | } |
| 3043 | auto info = extractDestructureInfo(assignment, true); | 3076 | auto info = extractDestructureInfo(assignment, true, false); |
| 3044 | if (!info.first.empty()) { | 3077 | if (!info.first.empty()) { |
| 3045 | for (const auto& destruct : info.first) | 3078 | for (const auto& destruct : info.first) |
| 3046 | for (const auto& item : destruct.items) | 3079 | for (const auto& item : destruct.items) |
| 3047 | if (item.isVariable) { | 3080 | if (!item.targetVar.empty()) { |
| 3048 | if (std::isupper(item.name[0]) && capital) { capital->decls.push_back(item.name); | 3081 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); |
| 3049 | } else if (any) { | 3082 | } else if (any) { |
| 3050 | any->decls.push_back(item.name); | 3083 | any->decls.push_back(item.targetVar); |
| 3051 | } | 3084 | } |
| 3052 | } | 3085 | } |
| 3053 | } | 3086 | } |
| @@ -4043,7 +4076,7 @@ private: | |||
| 4043 | auto value = x->new_ptr<Value_t>(); | 4076 | auto value = x->new_ptr<Value_t>(); |
| 4044 | value->item.set(chainValue); | 4077 | value->item.set(chainValue); |
| 4045 | auto exp = newExp(value, x); | 4078 | auto exp = newExp(value, x); |
| 4046 | callVar = singleVariableFrom(exp); | 4079 | callVar = singleVariableFrom(exp, true); |
| 4047 | if (callVar.empty()) { | 4080 | if (callVar.empty()) { |
| 4048 | callVar = getUnusedName("_call_"s); | 4081 | callVar = getUnusedName("_call_"s); |
| 4049 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4082 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -4672,7 +4705,7 @@ private: | |||
| 4672 | std::string indexVar = getUnusedName("_idx_"sv); | 4705 | std::string indexVar = getUnusedName("_idx_"sv); |
| 4673 | std::string keyVar = getUnusedName("_key_"sv); | 4706 | std::string keyVar = getUnusedName("_key_"sv); |
| 4674 | std::string valueVar = getUnusedName("_value_"sv); | 4707 | std::string valueVar = getUnusedName("_value_"sv); |
| 4675 | auto objVar = singleVariableFrom(spread->exp); | 4708 | auto objVar = singleVariableFrom(spread->exp, true); |
| 4676 | if (objVar.empty()) { | 4709 | if (objVar.empty()) { |
| 4677 | objVar = getUnusedName("_obj_"); | 4710 | objVar = getUnusedName("_obj_"); |
| 4678 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); | 4711 | auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); |
| @@ -5146,7 +5179,7 @@ private: | |||
| 5146 | switch (loopTarget->getId()) { | 5179 | switch (loopTarget->getId()) { |
| 5147 | case id<star_exp_t>(): { | 5180 | case id<star_exp_t>(): { |
| 5148 | auto star_exp = static_cast<star_exp_t*>(loopTarget); | 5181 | auto star_exp = static_cast<star_exp_t*>(loopTarget); |
| 5149 | auto listVar = singleVariableFrom(star_exp->value); | 5182 | auto listVar = singleVariableFrom(star_exp->value, true); |
| 5150 | if (!isLocal(listVar)) listVar.clear(); | 5183 | if (!isLocal(listVar)) listVar.clear(); |
| 5151 | auto indexVar = getUnusedName("_index_"sv); | 5184 | auto indexVar = getUnusedName("_index_"sv); |
| 5152 | varAfter.push_back(indexVar); | 5185 | varAfter.push_back(indexVar); |
| @@ -5816,7 +5849,7 @@ private: | |||
| 5816 | assignItem = std::move(temp.back()); | 5849 | assignItem = std::move(temp.back()); |
| 5817 | temp.pop_back(); | 5850 | temp.pop_back(); |
| 5818 | } else if (expList) { | 5851 | } else if (expList) { |
| 5819 | auto name = singleVariableFrom(expList); | 5852 | auto name = singleVariableFrom(expList, true); |
| 5820 | if (!name.empty()) { | 5853 | if (!name.empty()) { |
| 5821 | className = '\"' + name + '\"'; | 5854 | className = '\"' + name + '\"'; |
| 5822 | } | 5855 | } |
| @@ -5834,12 +5867,12 @@ private: | |||
| 5834 | if (auto assignment = assignmentFrom(statement)) { | 5867 | if (auto assignment = assignmentFrom(statement)) { |
| 5835 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 5868 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
| 5836 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 5869 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
| 5837 | auto info = extractDestructureInfo(assignment, true); | 5870 | auto info = extractDestructureInfo(assignment, true, false); |
| 5838 | if (!info.first.empty()) { | 5871 | if (!info.first.empty()) { |
| 5839 | for (const auto& destruct : info.first) | 5872 | for (const auto& destruct : info.first) |
| 5840 | for (const auto& item : destruct.items) | 5873 | for (const auto& item : destruct.items) |
| 5841 | if (item.isVariable && addToScope(item.name)) | 5874 | if (!item.targetVar.empty() && addToScope(item.targetVar)) |
| 5842 | varDefs.push_back(item.name); | 5875 | varDefs.push_back(item.targetVar); |
| 5843 | } | 5876 | } |
| 5844 | BLOCK_START | 5877 | BLOCK_START |
| 5845 | auto assign = assignment->action.as<Assign_t>(); | 5878 | auto assign = assignment->action.as<Assign_t>(); |
| @@ -6193,7 +6226,7 @@ private: | |||
| 6193 | auto vars = getAssignVars(with); | 6226 | auto vars = getAssignVars(with); |
| 6194 | if (vars.front().empty() || isGlobal(vars.front())) { | 6227 | if (vars.front().empty() || isGlobal(vars.front())) { |
| 6195 | if (with->assigns->values.objects().size() == 1) { | 6228 | if (with->assigns->values.objects().size() == 1) { |
| 6196 | auto var = singleVariableFrom(with->assigns->values.objects().front()); | 6229 | auto var = singleVariableFrom(with->assigns->values.objects().front(), true); |
| 6197 | if (!var.empty() && isLocal(var)) { | 6230 | if (!var.empty() && isLocal(var)) { |
| 6198 | withVar = var; | 6231 | withVar = var; |
| 6199 | } | 6232 | } |
| @@ -6239,7 +6272,7 @@ private: | |||
| 6239 | transformAssignment(assignment, temp); | 6272 | transformAssignment(assignment, temp); |
| 6240 | } | 6273 | } |
| 6241 | } else { | 6274 | } else { |
| 6242 | withVar = singleVariableFrom(with->valueList); | 6275 | withVar = singleVariableFrom(with->valueList, true); |
| 6243 | if (withVar.empty() || !isLocal(withVar)) { | 6276 | if (withVar.empty() || !isLocal(withVar)) { |
| 6244 | withVar = getUnusedName("_with_"sv); | 6277 | withVar = getUnusedName("_with_"sv); |
| 6245 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6278 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -6265,11 +6298,11 @@ private: | |||
| 6265 | if (!names.empty()) { | 6298 | if (!names.empty()) { |
| 6266 | return traversal::Stop; | 6299 | return traversal::Stop; |
| 6267 | } | 6300 | } |
| 6268 | auto info = extractDestructureInfo(assignment, true); | 6301 | auto info = extractDestructureInfo(assignment, true, false); |
| 6269 | if (!info.first.empty()) { | 6302 | if (!info.first.empty()) { |
| 6270 | for (const auto& destruct : info.first) | 6303 | for (const auto& destruct : info.first) |
| 6271 | for (const auto& item : destruct.items) | 6304 | for (const auto& item : destruct.items) |
| 6272 | if (item.isVariable && !isDefined(item.name)) | 6305 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) |
| 6273 | return traversal::Stop; | 6306 | return traversal::Stop; |
| 6274 | } | 6307 | } |
| 6275 | BLOCK_START | 6308 | BLOCK_START |
| @@ -6417,12 +6450,12 @@ private: | |||
| 6417 | assignment->action.set(exportNode->assign); | 6450 | assignment->action.set(exportNode->assign); |
| 6418 | transformAssignment(assignment, out); | 6451 | transformAssignment(assignment, out); |
| 6419 | str_list names = transformAssignDefs(expList, DefOp::Get); | 6452 | str_list names = transformAssignDefs(expList, DefOp::Get); |
| 6420 | auto info = extractDestructureInfo(assignment, true); | 6453 | auto info = extractDestructureInfo(assignment, true, false); |
| 6421 | if (!info.first.empty()) { | 6454 | if (!info.first.empty()) { |
| 6422 | for (const auto& destruct : info.first) | 6455 | for (const auto& destruct : info.first) |
| 6423 | for (const auto& item : destruct.items) | 6456 | for (const auto& item : destruct.items) |
| 6424 | if (item.isVariable) | 6457 | if (!item.targetVar.empty()) |
| 6425 | names.push_back(item.name); | 6458 | names.push_back(item.targetVar); |
| 6426 | } | 6459 | } |
| 6427 | if (_info.exportDefault) { | 6460 | if (_info.exportDefault) { |
| 6428 | out.back().append(indent() + _info.moduleName + " = "s + names.back() + nlr(exportNode)); | 6461 | out.back().append(indent() + _info.moduleName + " = "s + names.back() + nlr(exportNode)); |
| @@ -6699,7 +6732,7 @@ private: | |||
| 6699 | void transformImportFrom(ImportFrom_t* import, str_list& out) { | 6732 | void transformImportFrom(ImportFrom_t* import, str_list& out) { |
| 6700 | str_list temp; | 6733 | str_list temp; |
| 6701 | auto x = import; | 6734 | auto x = import; |
| 6702 | auto objVar = singleVariableFrom(import->exp); | 6735 | auto objVar = singleVariableFrom(import->exp, true); |
| 6703 | ast_ptr<false, ExpListAssign_t> objAssign; | 6736 | ast_ptr<false, ExpListAssign_t> objAssign; |
| 6704 | if (objVar.empty()) { | 6737 | if (objVar.empty()) { |
| 6705 | objVar = getUnusedName("_obj_"sv); | 6738 | objVar = getUnusedName("_obj_"sv); |
| @@ -7065,7 +7098,7 @@ private: | |||
| 7065 | pushScope(); | 7098 | pushScope(); |
| 7066 | } | 7099 | } |
| 7067 | bool extraScope = false; | 7100 | bool extraScope = false; |
| 7068 | auto objVar = singleVariableFrom(switchNode->target); | 7101 | auto objVar = singleVariableFrom(switchNode->target, true); |
| 7069 | if (objVar.empty() || !isLocal(objVar)) { | 7102 | if (objVar.empty() || !isLocal(objVar)) { |
| 7070 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 7103 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
| 7071 | extraScope = true; | 7104 | extraScope = true; |
| @@ -7082,24 +7115,89 @@ private: | |||
| 7082 | transformAssignment(assignment, temp); | 7115 | transformAssignment(assignment, temp); |
| 7083 | } | 7116 | } |
| 7084 | const auto& branches = switchNode->branches.objects(); | 7117 | const auto& branches = switchNode->branches.objects(); |
| 7118 | int addScope = 0; | ||
| 7119 | bool firstBranch = true; | ||
| 7120 | std::string tabCheckVar; | ||
| 7085 | for (auto branch_ : branches) { | 7121 | for (auto branch_ : branches) { |
| 7086 | auto branch = static_cast<SwitchCase_t*>(branch_); | 7122 | auto branch = static_cast<SwitchCase_t*>(branch_); |
| 7087 | temp.push_back(indent() + (branches.front() == branch ? "if"s : "elseif"s)); | 7123 | if (auto value = singleValueFrom(branch->valueList); |
| 7088 | str_list tmp; | 7124 | value->item.is<simple_table_t>() || |
| 7089 | const auto& exprs = branch->valueList->exprs.objects(); | 7125 | value->getByPath<SimpleValue_t, TableLit_t>()) { |
| 7090 | for (auto exp_ : exprs) { | 7126 | if (!firstBranch) { |
| 7091 | auto exp = static_cast<Exp_t*>(exp_); | 7127 | temp.push_back(indent() + "else"s + nll(branch)); |
| 7092 | transformExp(exp, tmp, ExpUsage::Closure); | 7128 | pushScope(); |
| 7093 | if (!singleValueFrom(exp)) { | 7129 | addScope++; |
| 7094 | tmp.back() = '(' + tmp.back() + ')'; | 7130 | } |
| 7131 | if (tabCheckVar.empty()) { | ||
| 7132 | if (!extraScope) { | ||
| 7133 | temp.push_back(indent() + "do"s + nll(branch)); | ||
| 7134 | pushScope(); | ||
| 7135 | extraScope = true; | ||
| 7136 | } | ||
| 7137 | tabCheckVar = getUnusedName("_tab_"); | ||
| 7138 | forceAddToScope(tabCheckVar); | ||
| 7139 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + globalVar("type", branch) + '(' + objVar + ')' + nll(branch)); | ||
| 7140 | } | ||
| 7141 | std::string matchVar; | ||
| 7142 | bool lastBranch = branches.back() == branch_; | ||
| 7143 | if (!lastBranch) { | ||
| 7144 | matchVar = getUnusedName("_match_"); | ||
| 7145 | forceAddToScope(matchVar); | ||
| 7146 | temp.push_back(indent() + "local "s + matchVar + " = false"s + nll(branch)); | ||
| 7147 | } | ||
| 7148 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | ||
| 7149 | pushScope(); | ||
| 7150 | auto assignment = assignmentFrom(static_cast<Exp_t*>(branch->valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); | ||
| 7151 | auto info = extractDestructureInfo(assignment, true, false); | ||
| 7152 | transformAssignment(assignment, temp, true); | ||
| 7153 | temp.push_back(indent() + "if"s); | ||
| 7154 | bool firstItem = true; | ||
| 7155 | for (const auto& destruct : info.first) { | ||
| 7156 | for (const auto& item : destruct.items) { | ||
| 7157 | str_list tmp; | ||
| 7158 | transformExp(item.target, tmp, ExpUsage::Closure); | ||
| 7159 | temp.back().append((firstItem ? " " : " and "s) + tmp.back() + " ~= nil"s); | ||
| 7160 | if (firstItem) firstItem = false; | ||
| 7161 | } | ||
| 7162 | } | ||
| 7163 | temp.back().append(" then"s + nll(branch)); | ||
| 7164 | pushScope(); | ||
| 7165 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 7166 | if (!lastBranch) { | ||
| 7167 | temp.push_back(indent() + matchVar + " = true"s + nll(branch)); | ||
| 7168 | } | ||
| 7169 | popScope(); | ||
| 7170 | if (!lastBranch) { | ||
| 7171 | temp.push_back(indent() + "end"s + nll(branch)); | ||
| 7172 | popScope(); | ||
| 7173 | temp.push_back(indent() + "end"s + nll(branch)); | ||
| 7174 | temp.push_back(indent() + "if not "s + matchVar + " then"s + nll(branch)); | ||
| 7175 | pushScope(); | ||
| 7176 | addScope++; | ||
| 7177 | } else { | ||
| 7178 | temp.push_back(indent() + "end"s + nll(branch)); | ||
| 7179 | popScope(); | ||
| 7180 | } | ||
| 7181 | firstBranch = true; | ||
| 7182 | } else { | ||
| 7183 | temp.push_back(indent() + (firstBranch ? "if"s : "elseif"s)); | ||
| 7184 | firstBranch = false; | ||
| 7185 | str_list tmp; | ||
| 7186 | const auto& exprs = branch->valueList->exprs.objects(); | ||
| 7187 | for (auto exp_ : exprs) { | ||
| 7188 | auto exp = static_cast<Exp_t*>(exp_); | ||
| 7189 | transformExp(exp, tmp, ExpUsage::Closure); | ||
| 7190 | if (!singleValueFrom(exp)) { | ||
| 7191 | tmp.back() = '(' + tmp.back() + ')'; | ||
| 7192 | } | ||
| 7193 | temp.back().append(' ' + tmp.back() + " == "s + | ||
| 7194 | (exp == exprs.back() ? objVar : objVar + " or"s)); | ||
| 7095 | } | 7195 | } |
| 7096 | temp.back().append(' ' + tmp.back() + " == "s + | 7196 | temp.back().append(" then"s + nll(branch)); |
| 7097 | (exp == exprs.back() ? objVar : objVar + " or"s)); | 7197 | pushScope(); |
| 7198 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 7199 | popScope(); | ||
| 7098 | } | 7200 | } |
| 7099 | temp.back().append(" then"s + nll(branch)); | ||
| 7100 | pushScope(); | ||
| 7101 | transform_plain_body(branch->body, temp, usage, assignList); | ||
| 7102 | popScope(); | ||
| 7103 | } | 7201 | } |
| 7104 | if (switchNode->lastBranch) { | 7202 | if (switchNode->lastBranch) { |
| 7105 | temp.push_back(indent() + "else"s + nll(switchNode->lastBranch)); | 7203 | temp.push_back(indent() + "else"s + nll(switchNode->lastBranch)); |
| @@ -7107,6 +7205,11 @@ private: | |||
| 7107 | transform_plain_body(switchNode->lastBranch, temp, usage, assignList); | 7205 | transform_plain_body(switchNode->lastBranch, temp, usage, assignList); |
| 7108 | popScope(); | 7206 | popScope(); |
| 7109 | } | 7207 | } |
| 7208 | while (addScope > 0) { | ||
| 7209 | addScope--; | ||
| 7210 | temp.push_back(indent() + "end"s + nlr(switchNode)); | ||
| 7211 | popScope(); | ||
| 7212 | } | ||
| 7110 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 7213 | temp.push_back(indent() + "end"s + nlr(switchNode)); |
| 7111 | if (usage == ExpUsage::Closure) { | 7214 | if (usage == ExpUsage::Closure) { |
| 7112 | _enableReturn.pop(); | 7215 | _enableReturn.pop(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 78b4713..199c0bd 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -225,7 +225,7 @@ YueParser::YueParser() { | |||
| 225 | WithExp = ExpList >> -Assign; | 225 | WithExp = ExpList >> -Assign; |
| 226 | 226 | ||
| 227 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); | 227 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); |
| 228 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(ExpList)) >> plain_body_with("then"); | 228 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(SwitchList)) >> plain_body_with("then"); |
| 229 | SwitchElse = Space >> key("else") >> plain_body; | 229 | SwitchElse = Space >> key("else") >> plain_body; |
| 230 | 230 | ||
| 231 | SwitchBlock = *EmptyLine >> | 231 | SwitchBlock = *EmptyLine >> |
| @@ -235,6 +235,9 @@ YueParser::YueParser() { | |||
| 235 | -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >> | 235 | -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >> |
| 236 | PopIndent; | 236 | PopIndent; |
| 237 | 237 | ||
| 238 | exp_not_tab = not_(simple_table | TableLit) >> Exp; | ||
| 239 | |||
| 240 | SwitchList = Seperator >> Exp >> *(sym(',') >> exp_not_tab); | ||
| 238 | Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) | 241 | Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) |
| 239 | >> -Space >> Break >> SwitchBlock; | 242 | >> -Space >> Break >> SwitchBlock; |
| 240 | 243 | ||
| @@ -550,14 +553,14 @@ YueParser::YueParser() { | |||
| 550 | symx(':') >> not_(':') >> | 553 | symx(':') >> not_(':') >> |
| 551 | (Exp | TableBlock | +SpaceBreak >> Exp); | 554 | (Exp | TableBlock | +SpaceBreak >> Exp); |
| 552 | 555 | ||
| 553 | default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> Exp | Exp >> Seperator) >> sym('=') >> Exp; | 556 | default_pair = (sym(':') >> Variable >> not_('#') >> Seperator | KeyName >> symx(':') >> Seperator >> exp_not_tab | exp_not_tab >> Seperator) >> sym('=') >> Exp; |
| 554 | 557 | ||
| 555 | meta_variable_pair = sym(':') >> Variable >> expr('#'); | 558 | meta_variable_pair = sym(':') >> Variable >> expr('#'); |
| 556 | 559 | ||
| 557 | meta_normal_pair = Space >> -(Name | symx('[') >> not_('[') >> Exp >> sym(']')) >> expr("#:") >> | 560 | meta_normal_pair = Space >> -(Name | symx('[') >> not_('[') >> Exp >> sym(']')) >> expr("#:") >> |
| 558 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | 561 | (Exp | TableBlock | +(SpaceBreak) >> Exp); |
| 559 | 562 | ||
| 560 | meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | Space >> -Name >> expr("#:") >> Seperator >> Exp) >> sym('=') >> Exp; | 563 | meta_default_pair = (sym(':') >> Variable >> expr('#') >> Seperator | Space >> -Name >> expr("#:") >> Seperator >> exp_not_tab) >> sym('=') >> Exp; |
| 561 | 564 | ||
| 562 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; | 565 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; |
| 563 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | 566 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index eea3027..b71a67c 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -188,6 +188,7 @@ private: | |||
| 188 | rule pipe_exp; | 188 | rule pipe_exp; |
| 189 | rule expo_value; | 189 | rule expo_value; |
| 190 | rule expo_exp; | 190 | rule expo_exp; |
| 191 | rule exp_not_tab; | ||
| 191 | rule empty_line_stop; | 192 | rule empty_line_stop; |
| 192 | rule Line; | 193 | rule Line; |
| 193 | rule Shebang; | 194 | rule Shebang; |
| @@ -230,6 +231,7 @@ private: | |||
| 230 | AST_RULE(ExpList) | 231 | AST_RULE(ExpList) |
| 231 | AST_RULE(Return) | 232 | AST_RULE(Return) |
| 232 | AST_RULE(With) | 233 | AST_RULE(With) |
| 234 | AST_RULE(SwitchList) | ||
| 233 | AST_RULE(SwitchCase) | 235 | AST_RULE(SwitchCase) |
| 234 | AST_RULE(Switch) | 236 | AST_RULE(Switch) |
| 235 | AST_RULE(assignment) | 237 | AST_RULE(assignment) |
