Skip to content

Commit 096b407

Browse files
committed
comprehensions moved to transformer
1 parent 5cdbb68 commit 096b407

File tree

6 files changed

+230
-160
lines changed

6 files changed

+230
-160
lines changed

moonscript/compile/line.lua

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -305,44 +305,6 @@ line_compile = {
305305
end
306306
return nil
307307
end,
308-
comprehension = function(self, node, action)
309-
local _, exp, clauses = unpack(node)
310-
if not action then
311-
action = function(exp)
312-
return {
313-
exp
314-
}
315-
end
316-
end
317-
local current_stms = action(exp)
318-
for _, clause in reversed(clauses) do
319-
local t = clause[1]
320-
if t == "for" then
321-
local names, iter
322-
_, names, iter = unpack(clause)
323-
current_stms = {
324-
"foreach",
325-
names,
326-
iter,
327-
current_stms
328-
}
329-
elseif t == "when" then
330-
local cond
331-
_, cond = unpack(clause)
332-
current_stms = {
333-
"if",
334-
cond,
335-
current_stms
336-
}
337-
else
338-
current_stms = error("Unknown comprehension clause: " .. t)
339-
end
340-
current_stms = {
341-
current_stms
342-
}
343-
end
344-
return self:stms(current_stms)
345-
end,
346308
with = function(self, node, ret)
347309
local _, exp, block = unpack(node)
348310
do

moonscript/compile/line.moon

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -167,28 +167,6 @@ line_compile =
167167
@declare names
168168
nil
169169

170-
comprehension: (node, action) =>
171-
_, exp, clauses = unpack node
172-
173-
if not action
174-
action = (exp) -> {exp}
175-
176-
current_stms = action exp
177-
for _, clause in reversed clauses
178-
t = clause[1]
179-
current_stms = if t == "for"
180-
_, names, iter = unpack clause
181-
{"foreach", names, iter, current_stms}
182-
elseif t == "when"
183-
_, cond = unpack clause
184-
{"if", cond, current_stms}
185-
else
186-
error "Unknown comprehension clause: "..t
187-
current_stms = {current_stms}
188-
189-
@stms current_stms
190-
191-
192170
with: (node, ret) =>
193171
_, exp, block = unpack node
194172

moonscript/compile/value.lua

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -103,31 +103,6 @@ value_compile = {
103103
return _with_0
104104
end
105105
end,
106-
comprehension = function(self, node)
107-
local _, exp, iter = unpack(node)
108-
do
109-
local _with_0 = self:block()
110-
local tmp_name = _with_0:init_free_var("accum", {
111-
"table"
112-
})
113-
local len_name = _with_0:init_free_var("len", 0)
114-
local action
115-
action = function(value)
116-
return table_append(tmp_name, len_name, value)
117-
end
118-
_with_0:stm(node, action)
119-
_with_0:stm({
120-
"return",
121-
tmp_name
122-
})
123-
if _with_0.has_varargs then
124-
_with_0.header, _with_0.footer = "(function(...)", "end)(...)"
125-
else
126-
_with_0.header, _with_0.footer = "(function()", "end)()"
127-
end
128-
return _with_0
129-
end
130-
end,
131106
chain = function(self, node)
132107
local callee = node[2]
133108
if callee == -1 then

moonscript/compile/value.moon

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,6 @@ value_compile =
5252
with @block "(function()", "end)()"
5353
\stm node, default_return
5454

55-
-- todo: convert to transformation
56-
comprehension: (node) =>
57-
_, exp, iter = unpack node
58-
59-
with @block!
60-
tmp_name = \init_free_var "accum", {"table"}
61-
len_name = \init_free_var "len", 0
62-
63-
action = (value) ->
64-
table_append tmp_name, len_name, value
65-
66-
\stm node, action
67-
\stm {"return", tmp_name}
68-
69-
.header, .footer = if .has_varargs
70-
"(function(...)", "end)(...)"
71-
else
72-
"(function()", "end)()"
73-
7455
chain: (node) =>
7556
callee = node[2]
7657

moonscript/transform.lua

Lines changed: 143 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module("moonscript.transform", package.seeall)
22
local types = require("moonscript.types")
33
local util = require("moonscript.util")
44
local data = require("moonscript.data")
5+
local reversed = util.reversed
56
local ntype, build, smart_node, is_slice = types.ntype, types.build, types.smart_node, types.is_slice
67
local insert = table.insert
78
NameProxy = (function()
@@ -136,11 +137,22 @@ apply_to_last = function(stms, fn)
136137
return _accum_0
137138
end)()
138139
end
140+
local is_singular
141+
is_singular = function(body)
142+
if #body ~= 1 then
143+
return false
144+
end
145+
if "group" == ntype(body) then
146+
return is_singular(body[2])
147+
else
148+
return true
149+
end
150+
end
139151
local constructor_name = "new"
140152
local Transformer
141153
Transformer = function(transformers)
142154
local seen_nodes = { }
143-
return function(n)
155+
return function(n, ...)
144156
if seen_nodes[n] then
145157
return n
146158
end
@@ -149,7 +161,7 @@ Transformer = function(transformers)
149161
local transformer = transformers[ntype(n)]
150162
local res
151163
if transformer then
152-
res = transformer(n) or n
164+
res = transformer(n, ...) or n
153165
else
154166
res = n
155167
end
@@ -161,6 +173,42 @@ Transformer = function(transformers)
161173
end
162174
end
163175
stm = Transformer({
176+
comprehension = function(node, action)
177+
local _, exp, clauses = unpack(node)
178+
action = action or function(exp)
179+
return {
180+
exp
181+
}
182+
end
183+
local current_stms = action(exp)
184+
for _, clause in reversed(clauses) do
185+
local t = clause[1]
186+
if t == "for" then
187+
local names, iter
188+
_, names, iter = unpack(clause)
189+
current_stms = {
190+
"foreach",
191+
names,
192+
iter,
193+
current_stms
194+
}
195+
elseif t == "when" then
196+
local cond
197+
_, cond = unpack(clause)
198+
current_stms = {
199+
"if",
200+
cond,
201+
current_stms
202+
}
203+
else
204+
current_stms = error("Unknown comprehension clause: " .. t)
205+
end
206+
current_stms = {
207+
current_stms
208+
}
209+
end
210+
return current_stms[1]
211+
end,
164212
foreach = function(node)
165213
smart_node(node)
166214
if ntype(node.iter) == "unpack" then
@@ -437,45 +485,108 @@ stm = Transformer({
437485
return value
438486
end
439487
})
440-
local create_accumulator
441-
create_accumulator = function(body_index)
442-
return function(node)
443-
local accum_name = NameProxy("accum")
444-
local value_name = NameProxy("value")
445-
local len_name = NameProxy("len")
446-
local body = apply_to_last(node[body_index], function(n)
447-
return build.assign_one(value_name, n)
448-
end)
449-
table.insert(body, build["if"]({
450-
cond = {
451-
"exp",
452-
value_name,
453-
"!=",
454-
"nil"
455-
},
456-
["then"] = {
488+
local Accumulator
489+
Accumulator = (function()
490+
local _parent_0 = nil
491+
local _base_0 = {
492+
body_idx = {
493+
["for"] = 4,
494+
["while"] = 3,
495+
foreach = 4
496+
},
497+
convert = function(self, node)
498+
local index = self.body_idx[ntype(node)]
499+
node[index] = self:mutate_body(node[index])
500+
return self:wrap(node)
501+
end,
502+
wrap = function(self, node)
503+
return build.block_exp({
504+
build.assign_one(self.accum_name, build.table()),
505+
build.assign_one(self.len_name, 0),
506+
node,
507+
self.accum_name
508+
})
509+
end,
510+
mutate_body = function(self, body, skip_nil)
511+
if skip_nil == nil then
512+
skip_nil = true
513+
end
514+
local val
515+
if not skip_nil and is_singular(body) then
516+
do
517+
local _with_0 = body[1]
518+
body = { }
519+
val = _with_0
520+
end
521+
else
522+
body = apply_to_last(body, function(n)
523+
return build.assign_one(self.value_name, n)
524+
end)
525+
val = self.value_name
526+
end
527+
local update = {
457528
{
458529
"update",
459-
len_name,
530+
self.len_name,
460531
"+=",
461532
1
462533
},
463-
build.assign_one(accum_name:index(len_name), value_name)
534+
build.assign_one(self.accum_name:index(self.len_name), val)
464535
}
465-
}))
466-
node[body_index] = body
467-
return build.block_exp({
468-
build.assign_one(accum_name, build.table()),
469-
build.assign_one(len_name, 0),
470-
node,
471-
accum_name
472-
})
536+
if skip_nil then
537+
table.insert(body, build["if"]({
538+
cond = {
539+
"exp",
540+
self.value_name,
541+
"!=",
542+
"nil"
543+
},
544+
["then"] = update
545+
}))
546+
else
547+
table.insert(body, build.group(update))
548+
end
549+
return body
550+
end
551+
}
552+
_base_0.__index = _base_0
553+
if _parent_0 then
554+
setmetatable(_base_0, getmetatable(_parent_0).__index)
473555
end
556+
local _class_0 = setmetatable({
557+
__init = function(self)
558+
self.accum_name = NameProxy("accum")
559+
self.value_name = NameProxy("value")
560+
self.len_name = NameProxy("len")
561+
end
562+
}, {
563+
__index = _base_0,
564+
__call = function(cls, ...)
565+
local _self_0 = setmetatable({}, _base_0)
566+
cls.__init(_self_0, ...)
567+
return _self_0
568+
end
569+
})
570+
_base_0.__class = _class_0
571+
return _class_0
572+
end)()
573+
local default_accumulator
574+
default_accumulator = function(node)
575+
return Accumulator():convert(node)
474576
end
475577
value = Transformer({
476-
["for"] = create_accumulator(4),
477-
["while"] = create_accumulator(3),
478-
foreach = create_accumulator(4),
578+
["for"] = default_accumulator,
579+
["while"] = default_accumulator,
580+
foreach = default_accumulator,
581+
comprehension = function(node)
582+
local a = Accumulator()
583+
node = stm(node, function(exp)
584+
return a:mutate_body({
585+
exp
586+
}, false)
587+
end)
588+
return a:wrap(node)
589+
end,
479590
chain = function(node)
480591
local stub = node[#node]
481592
if type(stub) == "table" and stub[1] == "colon_stub" then

0 commit comments

Comments
 (0)