@@ -2,6 +2,7 @@ module("moonscript.transform", package.seeall)
22local types = require (" moonscript.types" )
33local util = require (" moonscript.util" )
44local data = require (" moonscript.data" )
5+ local reversed = util .reversed
56local ntype , build , smart_node , is_slice = types .ntype , types .build , types .smart_node , types .is_slice
67local insert = table.insert
78NameProxy = (function ()
@@ -136,11 +137,22 @@ apply_to_last = function(stms, fn)
136137 return _accum_0
137138 end )()
138139end
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
139151local constructor_name = " new"
140152local Transformer
141153Transformer = 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
162174end
163175stm = 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 )
474576end
475577value = 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