rufus-lua-moon 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,9 +3,11 @@ local types = require("moonscript.types")
3
3
  local util = require("moonscript.util")
4
4
  local data = require("moonscript.data")
5
5
  local reversed = util.reversed
6
- local ntype, build, smart_node, is_slice = types.ntype, types.build, types.smart_node, types.is_slice
6
+ local ntype, build, smart_node, is_slice, value_is_singular = types.ntype, types.build, types.smart_node, types.is_slice, types.value_is_singular
7
7
  local insert = table.insert
8
- LocalName = (function()
8
+ local mtype = util.moon.type
9
+ local implicitly_return
10
+ do
9
11
  local _parent_0 = nil
10
12
  local _base_0 = {
11
13
  get_name = function(self)
@@ -40,9 +42,12 @@ LocalName = (function()
40
42
  end
41
43
  })
42
44
  _base_0.__class = _class_0
43
- return _class_0
44
- end)()
45
- NameProxy = (function()
45
+ if _parent_0 and _parent_0.__inherited then
46
+ _parent_0.__inherited(_parent_0, _class_0)
47
+ end
48
+ LocalName = _class_0
49
+ end
50
+ do
46
51
  local _parent_0 = nil
47
52
  local _base_0 = {
48
53
  get_name = function(self, scope)
@@ -127,9 +132,12 @@ NameProxy = (function()
127
132
  end
128
133
  })
129
134
  _base_0.__class = _class_0
130
- return _class_0
131
- end)()
132
- Run = (function()
135
+ if _parent_0 and _parent_0.__inherited then
136
+ _parent_0.__inherited(_parent_0, _class_0)
137
+ end
138
+ NameProxy = _class_0
139
+ end
140
+ do
133
141
  local _parent_0 = nil
134
142
  local _base_0 = {
135
143
  call = function(self, state)
@@ -164,8 +172,11 @@ Run = (function()
164
172
  end
165
173
  })
166
174
  _base_0.__class = _class_0
167
- return _class_0
168
- end)()
175
+ if _parent_0 and _parent_0.__inherited then
176
+ _parent_0.__inherited(_parent_0, _class_0)
177
+ end
178
+ Run = _class_0
179
+ end
169
180
  local apply_to_last
170
181
  apply_to_last = function(stms, fn)
171
182
  local last_exp_id = 0
@@ -205,9 +216,136 @@ is_singular = function(body)
205
216
  return true
206
217
  end
207
218
  end
219
+ local find_assigns
220
+ find_assigns = function(body, out)
221
+ if out == nil then
222
+ out = { }
223
+ end
224
+ local _list_0 = body
225
+ for _index_0 = 1, #_list_0 do
226
+ local thing = _list_0[_index_0]
227
+ local _exp_0 = thing[1]
228
+ if "group" == _exp_0 then
229
+ find_assigns(thing[2], out)
230
+ elseif "assign" == _exp_0 then
231
+ table.insert(out, thing[2])
232
+ end
233
+ end
234
+ return out
235
+ end
236
+ local hoist_declarations
237
+ hoist_declarations = function(body)
238
+ local assigns = { }
239
+ local _list_0 = find_assigns(body)
240
+ for _index_0 = 1, #_list_0 do
241
+ local names = _list_0[_index_0]
242
+ local _list_1 = names
243
+ for _index_1 = 1, #_list_1 do
244
+ local name = _list_1[_index_1]
245
+ if type(name) == "string" then
246
+ table.insert(assigns, name)
247
+ end
248
+ end
249
+ end
250
+ local idx = 1
251
+ while mtype(body[idx]) == Run do
252
+ idx = idx + 1
253
+ end
254
+ return table.insert(body, idx, {
255
+ "declare",
256
+ assigns
257
+ })
258
+ end
259
+ local expand_elseif_assign
260
+ expand_elseif_assign = function(ifstm)
261
+ for i = 4, #ifstm do
262
+ local case = ifstm[i]
263
+ if ntype(case) == "elseif" and ntype(case[2]) == "assign" then
264
+ local split = {
265
+ unpack(ifstm, 1, i - 1)
266
+ }
267
+ insert(split, {
268
+ "else",
269
+ {
270
+ {
271
+ "if",
272
+ case[2],
273
+ case[3],
274
+ unpack(ifstm, i + 1)
275
+ }
276
+ }
277
+ })
278
+ return split
279
+ end
280
+ end
281
+ return ifstm
282
+ end
208
283
  local constructor_name = "new"
284
+ local with_continue_listener
285
+ with_continue_listener = function(body)
286
+ local continue_name = nil
287
+ return {
288
+ Run(function(self)
289
+ return self:listen("continue", function()
290
+ if not (continue_name) then
291
+ continue_name = NameProxy("continue")
292
+ self:put_name(continue_name)
293
+ end
294
+ return continue_name
295
+ end)
296
+ end),
297
+ build.group(body),
298
+ Run(function(self)
299
+ if not (continue_name) then
300
+ return
301
+ end
302
+ self:put_name(continue_name, nil)
303
+ return self:splice(function(lines)
304
+ return {
305
+ {
306
+ "assign",
307
+ {
308
+ continue_name
309
+ },
310
+ {
311
+ "false"
312
+ }
313
+ },
314
+ {
315
+ "repeat",
316
+ "true",
317
+ {
318
+ lines,
319
+ {
320
+ "assign",
321
+ {
322
+ continue_name
323
+ },
324
+ {
325
+ "true"
326
+ }
327
+ }
328
+ }
329
+ },
330
+ {
331
+ "if",
332
+ {
333
+ "not",
334
+ continue_name
335
+ },
336
+ {
337
+ {
338
+ "break"
339
+ }
340
+ }
341
+ }
342
+ }
343
+ end)
344
+ end)
345
+ }
346
+ end
209
347
  local Transformer
210
- Transformer = (function()
348
+ do
211
349
  local _parent_0 = nil
212
350
  local _base_0 = {
213
351
  transform = function(self, scope, node, ...)
@@ -228,12 +366,15 @@ Transformer = (function()
228
366
  end
229
367
  node = res
230
368
  end
369
+ return node
231
370
  end,
232
- __call = function(self, node, ...)
233
- return self:transform(self.scope, node, ...)
371
+ bind = function(self, scope)
372
+ return function(...)
373
+ return self:transform(scope, ...)
374
+ end
234
375
  end,
235
- instance = function(self, scope)
236
- return Transformer(self.transformers, scope)
376
+ __call = function(self, ...)
377
+ return self:transform(...)
237
378
  end,
238
379
  can_transform = function(self, node)
239
380
  return self.transformers[ntype(node)] ~= nil
@@ -244,9 +385,11 @@ Transformer = (function()
244
385
  setmetatable(_base_0, _parent_0.__base)
245
386
  end
246
387
  local _class_0 = setmetatable({
247
- __init = function(self, transformers, scope)
248
- self.transformers, self.scope = transformers, scope
249
- self.seen_nodes = { }
388
+ __init = function(self, transformers)
389
+ self.transformers = transformers
390
+ self.seen_nodes = setmetatable({ }, {
391
+ __mode = "k"
392
+ })
250
393
  end,
251
394
  __base = _base_0,
252
395
  __name = "Transformer",
@@ -267,23 +410,30 @@ Transformer = (function()
267
410
  end
268
411
  })
269
412
  _base_0.__class = _class_0
270
- return _class_0
271
- end)()
413
+ if _parent_0 and _parent_0.__inherited then
414
+ _parent_0.__inherited(_parent_0, _class_0)
415
+ end
416
+ Transformer = _class_0
417
+ end
272
418
  local construct_comprehension
273
419
  construct_comprehension = function(inner, clauses)
274
420
  local current_stms = inner
275
421
  for _, clause in reversed(clauses) do
276
422
  local t = clause[1]
277
423
  if t == "for" then
278
- local _, names, iter = unpack(clause)
424
+ local names, iter
425
+ _, names, iter = unpack(clause)
279
426
  current_stms = {
280
427
  "foreach",
281
428
  names,
282
- iter,
429
+ {
430
+ iter
431
+ },
283
432
  current_stms
284
433
  }
285
434
  elseif t == "when" then
286
- local _, cond = unpack(clause)
435
+ local cond
436
+ _, cond = unpack(clause)
287
437
  current_stms = {
288
438
  "if",
289
439
  cond,
@@ -299,33 +449,56 @@ construct_comprehension = function(inner, clauses)
299
449
  return current_stms[1]
300
450
  end
301
451
  Statement = Transformer({
452
+ root_stms = function(self, body)
453
+ return apply_to_last(body, implicitly_return(self))
454
+ end,
302
455
  assign = function(self, node)
303
- local _, names, values = unpack(node)
304
- if #values == 1 and types.cascading[ntype(values[1])] then
305
- values[1] = self.transform.statement(values[1], function(stm)
306
- local t = ntype(stm)
307
- if types.is_value(stm) then
308
- return {
309
- "assign",
310
- names,
311
- {
312
- stm
456
+ local names, values = unpack(node, 2)
457
+ local transformed
458
+ if #values == 1 then
459
+ local value = values[1]
460
+ local t = ntype(value)
461
+ if t == "decorated" then
462
+ value = self.transform.statement(value)
463
+ t = ntype(value)
464
+ end
465
+ if types.cascading[t] then
466
+ local ret
467
+ ret = function(stm)
468
+ if types.is_value(stm) then
469
+ return {
470
+ "assign",
471
+ names,
472
+ {
473
+ stm
474
+ }
313
475
  }
314
- }
315
- else
316
- return stm
476
+ else
477
+ return stm
478
+ end
317
479
  end
318
- end)
319
- return build.group({
320
- {
321
- "declare",
322
- names
323
- },
324
- values[1]
325
- })
326
- else
327
- return node
480
+ transformed = build.group({
481
+ {
482
+ "declare",
483
+ names
484
+ },
485
+ self.transform.statement(value, ret, node)
486
+ })
487
+ end
328
488
  end
489
+ return transformed or node
490
+ end,
491
+ continue = function(self, node)
492
+ local continue_name = self:send("continue")
493
+ if not (continue_name) then
494
+ error("continue must be inside of a loop")
495
+ end
496
+ return build.group({
497
+ build.assign_one(continue_name, "true"),
498
+ {
499
+ "break"
500
+ }
501
+ })
329
502
  end,
330
503
  export = function(self, node)
331
504
  if #node > 2 then
@@ -359,6 +532,12 @@ Statement = Transformer({
359
532
  if not op_final then
360
533
  error("Unknown op: " .. op)
361
534
  end
535
+ if not (value_is_singular(exp)) then
536
+ exp = {
537
+ "parens",
538
+ exp
539
+ }
540
+ end
362
541
  return build.assign_one(name, {
363
542
  "exp",
364
543
  name,
@@ -461,7 +640,100 @@ Statement = Transformer({
461
640
  end
462
641
  return construct_comprehension(action(exp), clauses)
463
642
  end,
643
+ ["do"] = function(self, node, ret)
644
+ if ret then
645
+ node[2] = apply_to_last(node[2], ret)
646
+ end
647
+ return node
648
+ end,
649
+ decorated = function(self, node)
650
+ local stm, dec = unpack(node, 2)
651
+ local wrapped
652
+ local _exp_0 = dec[1]
653
+ if "if" == _exp_0 then
654
+ local cond, fail = unpack(dec, 2)
655
+ if fail then
656
+ fail = {
657
+ "else",
658
+ {
659
+ fail
660
+ }
661
+ }
662
+ end
663
+ wrapped = {
664
+ "if",
665
+ cond,
666
+ {
667
+ stm
668
+ },
669
+ fail
670
+ }
671
+ elseif "unless" == _exp_0 then
672
+ wrapped = {
673
+ "unless",
674
+ dec[2],
675
+ {
676
+ stm
677
+ }
678
+ }
679
+ elseif "comprehension" == _exp_0 then
680
+ wrapped = {
681
+ "comprehension",
682
+ stm,
683
+ dec[2]
684
+ }
685
+ else
686
+ wrapped = error("Unknown decorator " .. dec[1])
687
+ end
688
+ if ntype(stm) == "assign" then
689
+ wrapped = build.group({
690
+ build.declare({
691
+ names = (function()
692
+ local _accum_0 = { }
693
+ local _len_0 = 0
694
+ local _list_0 = stm[2]
695
+ for _index_0 = 1, #_list_0 do
696
+ local name = _list_0[_index_0]
697
+ if type(name) == "string" then
698
+ _len_0 = _len_0 + 1
699
+ _accum_0[_len_0] = name
700
+ end
701
+ end
702
+ return _accum_0
703
+ end)()
704
+ }),
705
+ wrapped
706
+ })
707
+ end
708
+ return wrapped
709
+ end,
710
+ unless = function(self, node)
711
+ return {
712
+ "if",
713
+ {
714
+ "not",
715
+ {
716
+ "parens",
717
+ node[2]
718
+ }
719
+ },
720
+ unpack(node, 3)
721
+ }
722
+ end,
464
723
  ["if"] = function(self, node, ret)
724
+ if ntype(node[2]) == "assign" then
725
+ local _, assign, body = unpack(node)
726
+ local name = assign[2][1]
727
+ return build["do"]({
728
+ assign,
729
+ {
730
+ "if",
731
+ name,
732
+ unpack(node, 3)
733
+ }
734
+ })
735
+ end
736
+ node = expand_elseif_assign(node)
465
737
  if ret then
466
738
  smart_node(node)
467
739
  node['then'] = apply_to_last(node['then'], ret)
@@ -476,11 +748,26 @@ Statement = Transformer({
476
748
  with = function(self, node, ret)
477
749
  local _, exp, block = unpack(node)
478
750
  local scope_name = NameProxy("with")
751
+ local named_assign
752
+ if ntype(exp) == "assign" then
753
+ local names, values = unpack(exp, 2)
754
+ local assign_name = names[1]
755
+ exp = values[1]
756
+ values[1] = scope_name
757
+ named_assign = {
758
+ "assign",
759
+ names,
760
+ values
761
+ }
762
+ end
479
763
  return build["do"]({
480
- build.assign_one(scope_name, exp),
481
764
  Run(function(self)
482
765
  return self:set("scope_var", scope_name)
483
766
  end),
767
+ build.assign_one(scope_name, exp),
768
+ build.group({
769
+ named_assign
770
+ }),
484
771
  build.group(block),
485
772
  (function()
486
773
  if ret then
@@ -491,8 +778,9 @@ Statement = Transformer({
491
778
  end,
492
779
  foreach = function(self, node)
493
780
  smart_node(node)
494
- if ntype(node.iter) == "unpack" then
495
- local list = node.iter[2]
781
+ local source = unpack(node.iter)
782
+ if ntype(source) == "unpack" then
783
+ local list = source[2]
496
784
  local index_name = NameProxy("index")
497
785
  local list_name = NameProxy("list")
498
786
  local slice_var = nil
@@ -554,6 +842,15 @@ Statement = Transformer({
554
842
  })
555
843
  })
556
844
  end
845
+ node.body = with_continue_listener(node.body)
846
+ end,
847
+ ["while"] = function(self, node)
848
+ smart_node(node)
849
+ node.body = with_continue_listener(node.body)
850
+ end,
851
+ ["for"] = function(self, node)
852
+ smart_node(node)
853
+ node.body = with_continue_listener(node.body)
557
854
  end,
558
855
  switch = function(self, node, ret)
559
856
  local _, exp, conds = unpack(node)
@@ -602,7 +899,7 @@ Statement = Transformer({
602
899
  if_stm
603
900
  })
604
901
  end,
605
- class = function(self, node)
902
+ class = function(self, node, ret, parent_assign)
606
903
  local _, name, parent_val, body = unpack(node)
607
904
  local statements = { }
608
905
  local properties = { }
@@ -614,9 +911,13 @@ Statement = Transformer({
614
911
  insert(statements, item[2])
615
912
  elseif "props" == _exp_0 then
616
913
  local _list_1 = item
617
- for _index_0 = 2, #_list_1 do
618
- local tuple = _list_1[_index_0]
619
- insert(properties, tuple)
914
+ for _index_1 = 2, #_list_1 do
915
+ local tuple = _list_1[_index_1]
916
+ if ntype(tuple[1]) == "self" then
917
+ insert(statements, build.assign_one(unpack(tuple)))
918
+ else
919
+ insert(properties, tuple)
920
+ end
620
921
  end
621
922
  end
622
923
  end
@@ -627,8 +928,9 @@ Statement = Transformer({
627
928
  local _list_1 = properties
628
929
  for _index_0 = 1, #_list_1 do
629
930
  local tuple = _list_1[_index_0]
931
+ local key = tuple[1]
630
932
  local _value_0
631
- if tuple[1] == constructor_name then
933
+ if key[1] == "key_literal" and key[2] == constructor_name then
632
934
  constructor = tuple[2]
633
935
  _value_0 = nil
634
936
  else
@@ -674,6 +976,31 @@ Statement = Transformer({
674
976
  smart_node(constructor)
675
977
  constructor.arrow = "fat"
676
978
  end
979
+ local real_name = name or parent_assign and parent_assign[2][1]
980
+ local _exp_0 = ntype(real_name)
981
+ if "chain" == _exp_0 then
982
+ local last = real_name[#real_name]
983
+ local _exp_1 = ntype(last)
984
+ if "dot" == _exp_1 then
985
+ real_name = {
986
+ "string",
987
+ '"',
988
+ last[2]
989
+ }
990
+ elseif "index" == _exp_1 then
991
+ real_name = last[2]
992
+ else
993
+ real_name = "nil"
994
+ end
995
+ elseif "nil" == _exp_0 then
996
+ real_name = "nil"
997
+ else
998
+ real_name = {
999
+ "string",
1000
+ '"',
1001
+ real_name
1002
+ }
1003
+ end
677
1004
  local cls = build.table({
678
1005
  {
679
1006
  "__init",
@@ -685,11 +1012,7 @@ Statement = Transformer({
685
1012
  },
686
1013
  {
687
1014
  "__name",
688
- {
689
- "string",
690
- '"',
691
- name
692
- }
1015
+ real_name
693
1016
  },
694
1017
  {
695
1018
  "__parent",
@@ -792,8 +1115,11 @@ Statement = Transformer({
792
1115
  local value = nil
793
1116
  do
794
1117
  local _with_0 = build
795
- value = _with_0.block_exp({
1118
+ local out_body = {
796
1119
  Run(function(self)
1120
+ if name then
1121
+ self:put_name(name)
1122
+ end
797
1123
  return self:set("super", function(block, chain)
798
1124
  if chain then
799
1125
  local slice = (function()
@@ -815,8 +1141,8 @@ Statement = Transformer({
815
1141
  if head == nil then
816
1142
  return parent_cls_name
817
1143
  end
818
- local _exp_0 = head[1]
819
- if "call" == _exp_0 then
1144
+ local _exp_1 = head[1]
1145
+ if "call" == _exp_1 then
820
1146
  local calling_name = block:get("current_block")
821
1147
  slice[1] = {
822
1148
  "call",
@@ -825,17 +1151,18 @@ Statement = Transformer({
825
1151
  unpack(head[2])
826
1152
  }
827
1153
  }
828
- local act
829
- if ntype(calling_name) ~= "value" then
830
- act = "index"
1154
+ if ntype(calling_name) == "key_literal" then
1155
+ insert(new_chain, {
1156
+ "dot",
1157
+ calling_name[2]
1158
+ })
831
1159
  else
832
- act = "dot"
1160
+ insert(new_chain, {
1161
+ "index",
1162
+ calling_name
1163
+ })
833
1164
  end
834
- insert(new_chain, {
835
- act,
836
- calling_name
837
- })
838
- elseif "colon" == _exp_0 then
1165
+ elseif "colon" == _exp_1 then
839
1166
  local call = head[3]
840
1167
  insert(new_chain, {
841
1168
  "dot",
@@ -866,7 +1193,7 @@ Statement = Transformer({
866
1193
  properties
867
1194
  }),
868
1195
  _with_0.assign_one(base_name:chain("__index"), base_name),
869
- build["if"]({
1196
+ _with_0["if"]({
870
1197
  cond = parent_cls_name,
871
1198
  ["then"] = {
872
1199
  _with_0.chain({
@@ -895,33 +1222,59 @@ Statement = Transformer({
895
1222
  _with_0.assign_one(LocalName("self"), cls_name),
896
1223
  _with_0.group(statements)
897
1224
  }
898
- else
899
- return { }
900
1225
  end
901
1226
  end)()),
902
- cls_name
903
- })
904
- value = _with_0.group({
905
- _with_0.declare({
906
- names = {
907
- name
908
- }
909
- }),
910
- _with_0.assign({
911
- names = {
912
- name
1227
+ _with_0["if"]({
1228
+ cond = {
1229
+ "exp",
1230
+ parent_cls_name,
1231
+ "and",
1232
+ parent_cls_name:chain("__inherited")
913
1233
  },
914
- values = {
915
- value
1234
+ ["then"] = {
1235
+ parent_cls_name:chain("__inherited", {
1236
+ "call",
1237
+ {
1238
+ parent_cls_name,
1239
+ cls_name
1240
+ }
1241
+ })
916
1242
  }
917
- })
1243
+ }),
1244
+ _with_0.group((function()
1245
+ if name then
1246
+ return {
1247
+ _with_0.assign_one(name, cls_name)
1248
+ }
1249
+ end
1250
+ end)()),
1251
+ (function()
1252
+ if ret then
1253
+ return ret(cls_name)
1254
+ end
1255
+ end)()
1256
+ }
1257
+ hoist_declarations(out_body)
1258
+ value = _with_0.group({
1259
+ _with_0.group((function()
1260
+ if ntype(name) == "value" then
1261
+ return {
1262
+ _with_0.declare({
1263
+ names = {
1264
+ name
1265
+ }
1266
+ })
1267
+ }
1268
+ end
1269
+ end)()),
1270
+ _with_0["do"](out_body)
918
1271
  })
919
1272
  end
920
1273
  return value
921
1274
  end
922
1275
  })
923
1276
  local Accumulator
924
- Accumulator = (function()
1277
+ do
925
1278
  local _parent_0 = nil
926
1279
  local _base_0 = {
927
1280
  body_idx = {
@@ -955,7 +1308,19 @@ Accumulator = (function()
955
1308
  end
956
1309
  else
957
1310
  body = apply_to_last(body, function(n)
958
- return build.assign_one(self.value_name, n)
1311
+ if types.is_value(n) then
1312
+ return build.assign_one(self.value_name, n)
1313
+ else
1314
+ return build.group({
1315
+ {
1316
+ "declare",
1317
+ {
1318
+ self.value_name
1319
+ }
1320
+ },
1321
+ n
1322
+ })
1323
+ end
959
1324
  end)
960
1325
  val = self.value_name
961
1326
  end
@@ -1013,21 +1378,33 @@ Accumulator = (function()
1013
1378
  end
1014
1379
  })
1015
1380
  _base_0.__class = _class_0
1016
- return _class_0
1017
- end)()
1381
+ if _parent_0 and _parent_0.__inherited then
1382
+ _parent_0.__inherited(_parent_0, _class_0)
1383
+ end
1384
+ Accumulator = _class_0
1385
+ end
1018
1386
  local default_accumulator
1019
1387
  default_accumulator = function(self, node)
1020
1388
  return Accumulator():convert(node)
1021
1389
  end
1022
- local implicitly_return
1023
1390
  implicitly_return = function(scope)
1391
+ local is_top = true
1024
1392
  local fn
1025
1393
  fn = function(stm)
1026
1394
  local t = ntype(stm)
1027
- if types.manual_return[t] or not types.is_value(stm) then
1028
- return stm
1029
- elseif types.cascading[t] then
1395
+ if t == "decorated" then
1396
+ stm = scope.transform.statement(stm)
1397
+ t = ntype(stm)
1398
+ end
1399
+ if types.cascading[t] then
1400
+ is_top = false
1030
1401
  return scope.transform.statement(stm, fn)
1402
+ elseif types.manual_return[t] or not types.is_value(stm) then
1403
+ if is_top and t == "return" and stm[2] == "" then
1404
+ return nil
1405
+ else
1406
+ return stm
1407
+ end
1031
1408
  else
1032
1409
  if t == "comprehension" and not types.comprehension_has_value(stm) then
1033
1410
  return stm
@@ -1045,6 +1422,58 @@ Value = Transformer({
1045
1422
  ["for"] = default_accumulator,
1046
1423
  ["while"] = default_accumulator,
1047
1424
  foreach = default_accumulator,
1425
+ ["do"] = function(self, node)
1426
+ return build.block_exp(node[2])
1427
+ end,
1428
+ decorated = function(self, node)
1429
+ return self.transform.statement(node)
1430
+ end,
1431
+ class = function(self, node)
1432
+ return build.block_exp({
1433
+ node
1434
+ })
1435
+ end,
1436
+ string = function(self, node)
1437
+ local delim = node[2]
1438
+ local convert_part
1439
+ convert_part = function(part)
1440
+ if type(part) == "string" or part == nil then
1441
+ return {
1442
+ "string",
1443
+ delim,
1444
+ part or ""
1445
+ }
1446
+ else
1447
+ return build.chain({
1448
+ base = "tostring",
1449
+ {
1450
+ "call",
1451
+ {
1452
+ part[2]
1453
+ }
1454
+ }
1455
+ })
1456
+ end
1457
+ end
1458
+ if #node <= 3 then
1459
+ return (function()
1460
+ if type(node[3]) == "string" then
1461
+ return node
1462
+ else
1463
+ return convert_part(node[3])
1464
+ end
1465
+ end)()
1466
+ end
1467
+ local e = {
1468
+ "exp",
1469
+ convert_part(node[3])
1470
+ }
1471
+ for i = 4, #node do
1472
+ insert(e, "..")
1473
+ insert(e, convert_part(node[i]))
1474
+ end
1475
+ return e
1476
+ end,
1048
1477
  comprehension = function(self, node)
1049
1478
  local a = Accumulator()
1050
1479
  node = self.transform.statement(node, function(exp)
@@ -1055,27 +1484,58 @@ Value = Transformer({
1055
1484
  return a:wrap(node)
1056
1485
  end,
1057
1486
  tblcomprehension = function(self, node)
1058
- local _, key_exp, value_exp, clauses = unpack(node)
1487
+ local _, explist, clauses = unpack(node)
1488
+ local key_exp, value_exp = unpack(explist)
1059
1489
  local accum = NameProxy("tbl")
1060
- local dest = build.chain({
1061
- base = accum,
1062
- {
1063
- "index",
1064
- key_exp
1490
+ local inner
1491
+ if value_exp then
1492
+ local dest = build.chain({
1493
+ base = accum,
1494
+ {
1495
+ "index",
1496
+ key_exp
1497
+ }
1498
+ })
1499
+ inner = {
1500
+ build.assign_one(dest, value_exp)
1065
1501
  }
1066
- })
1067
- local inner = build.assign_one(dest, value_exp)
1502
+ else
1503
+ local key_name, val_name = NameProxy("key"), NameProxy("val")
1504
+ local dest = build.chain({
1505
+ base = accum,
1506
+ {
1507
+ "index",
1508
+ key_name
1509
+ }
1510
+ })
1511
+ inner = {
1512
+ build.assign({
1513
+ names = {
1514
+ key_name,
1515
+ val_name
1516
+ },
1517
+ values = {
1518
+ key_exp
1519
+ }
1520
+ }),
1521
+ build.assign_one(dest, val_name)
1522
+ }
1523
+ end
1068
1524
  return build.block_exp({
1069
1525
  build.assign_one(accum, build.table()),
1070
- construct_comprehension({
1071
- inner
1072
- }, clauses),
1526
+ construct_comprehension(inner, clauses),
1073
1527
  accum
1074
1528
  })
1075
1529
  end,
1076
1530
  fndef = function(self, node)
1077
1531
  smart_node(node)
1078
1532
  node.body = apply_to_last(node.body, implicitly_return(self))
1533
+ node.body = {
1534
+ Run(function(self)
1535
+ return self:listen("varargs", function() end)
1536
+ end),
1537
+ unpack(node.body)
1538
+ }
1079
1539
  return node
1080
1540
  end,
1081
1541
  ["if"] = function(self, node)
@@ -1083,6 +1543,11 @@ Value = Transformer({
1083
1543
  node
1084
1544
  })
1085
1545
  end,
1546
+ unless = function(self, node)
1547
+ return build.block_exp({
1548
+ node
1549
+ })
1550
+ end,
1086
1551
  with = function(self, node)
1087
1552
  return build.block_exp({
1088
1553
  node
@@ -1095,7 +1560,25 @@ Value = Transformer({
1095
1560
  end,
1096
1561
  chain = function(self, node)
1097
1562
  local stub = node[#node]
1098
- if type(stub) == "table" and stub[1] == "colon_stub" then
1563
+ for i = 3, #node do
1564
+ local part = node[i]
1565
+ if ntype(part) == "dot" and data.lua_keywords[part[2]] then
1566
+ node[i] = {
1567
+ "index",
1568
+ {
1569
+ "string",
1570
+ '"',
1571
+ part[2]
1572
+ }
1573
+ }
1574
+ end
1575
+ end
1576
+ if ntype(node[2]) == "string" then
1577
+ node[2] = {
1578
+ "parens",
1579
+ node[2]
1580
+ }
1581
+ elseif type(stub) == "table" and stub[1] == "colon_stub" then
1099
1582
  table.remove(node, #node)
1100
1583
  local base_name = NameProxy("base")
1101
1584
  local fn_name = NameProxy("fn")
@@ -1149,16 +1632,19 @@ Value = Transformer({
1149
1632
  local _, body = unpack(node)
1150
1633
  local fn = nil
1151
1634
  local arg_list = { }
1152
- insert(body, Run(function(self)
1153
- if self.has_varargs then
1154
- insert(arg_list, "...")
1155
- return insert(fn.args, {
1156
- "..."
1157
- })
1158
- end
1159
- end))
1160
1635
  fn = smart_node(build.fndef({
1161
- body = body
1636
+ body = {
1637
+ Run(function(self)
1638
+ return self:listen("varargs", function()
1639
+ insert(arg_list, "...")
1640
+ insert(fn.args, {
1641
+ "..."
1642
+ })
1643
+ return self:unlisten("varargs")
1644
+ end)
1645
+ end),
1646
+ unpack(body)
1647
+ }
1162
1648
  }))
1163
1649
  return build.chain({
1164
1650
  base = {