11defmodule ElixirScript.Translator.For do
22 @ moduledoc false
3- alias ESTree.Tools.Builder
3+ alias ESTree.Tools.Builder , as: JS
44 alias ElixirScript.Translator
55 alias ElixirScript.Translator.Utils
6+ alias ElixirScript.PatternMatching.Match
7+ alias ElixirScript.Translator.Primitive
8+ alias ElixirScript.Translator.Function
69
710
811 def make_for ( generators , env ) do
9- quoted = quote do: _results
10- _results = Translator . translate ( quoted , env )
11-
12- quoted = quote do: _results = [ ]
13- variable_declaration = Translator . translate ( quoted , env )
14-
15- block_statement = [ variable_declaration ] ++ [ handle_generators ( generators , env ) ] ++ [ Builder . return_statement ( _results ) ]
16-
17- Utils . wrap_in_function_closure ( block_statement )
18- end
19-
20- defp handle_generators ( generators , env ) do
21-
22- case hd ( generators ) do
23- { :<- , [ ] , [ identifier , enum ] } ->
24- case identifier do
25- { value_one , value_two } ->
26- elements = [ value_one , value_two ]
27- make_tuple_for ( elements , enum , generators , env )
28- { :{} , _ , elements } ->
29- make_tuple_for ( elements , enum , generators , env )
30- _ ->
31- i = Translator . translate ( identifier , env )
32- variable_declarator = Builder . variable_declarator ( i )
33- variable_declaration = Builder . variable_declaration ( [ variable_declarator ] , :let )
34-
35- Builder . for_of_statement (
36- variable_declaration ,
37- Translator . translate ( enum , env ) ,
38- Builder . block_statement ( List . wrap ( handle_generators ( tl ( generators ) , env ) ) )
39- )
40- end
41- [ into: _expression ] ->
42- raise ElixirScript.UnsupportedError , :into
43- [ do: expression ] ->
44- push_last_expression ( Translator . translate ( expression , env ) )
45- filter ->
46- Builder . if_statement (
47- Translator . translate ( filter , env ) ,
48- handle_generators ( tl ( generators ) , env ) ,
49- nil
50- )
51- end
52-
53- end
54-
55- defp make_tuple_for ( elements , enum , generators , env ) do
56- i = Builder . identifier ( "_ref" )
57- variable_declarator = Builder . variable_declarator ( i )
58- variable_declaration = Builder . variable_declaration ( [ variable_declarator ] , :let )
59-
60- { variables , _ } = Enum . map_reduce ( elements , 0 ,
61- fn ( x , index ) ->
62- case Translator . translate ( x , env ) do
63- % ESTree.Identifier { } ->
64- variable_declarator = Builder . variable_declarator ( Translator . translate ( x , env ) ,
65- Builder . call_expression (
66- Builder . member_expression (
67- Builder . identifier ( :Kernel ) ,
68- Builder . identifier ( :elem )
69- ) ,
70- [ i , Builder . literal ( index ) ]
71- )
72- )
73- variable_declaration = Builder . variable_declaration ( [ variable_declarator ] , :let )
74-
75- { variable_declaration , index + 1 }
76- _ ->
77- { nil , index + 1 }
78- end
79- end )
80-
81- variables = Enum . filter ( variables , fn ( x ) -> x != nil end )
82-
83- new_identifier = Enum . map ( elements , fn ( x ) ->
84- case Translator . translate ( x , env ) do
85- % ESTree.Identifier { } ->
86- Builder . identifier ( :undefined )
87- _ ->
88- Translator . translate ( x , env )
89- end
90- end )
91-
92- new_identifier = Builder . call_expression (
93- Builder . member_expression (
94- Builder . identifier ( "Erlang" ) ,
95- Builder . identifier ( "tuple" )
12+ args = handle_args ( generators , env )
13+
14+ collections = Primitive . make_list_no_translate ( args . collections )
15+ into = args . into || Primitive . make_list_no_translate ( [ ] )
16+ filter = args . filter || JS . function_expression ( [ ] , [ ] , JS . block_statement ( [ JS . return_statement ( JS . identifier ( "true" ) ) ] ) )
17+ fun = args . fun
18+
19+ JS . call_expression (
20+ JS . member_expression (
21+ JS . member_expression (
22+ JS . identifier ( "Kernel" ) ,
23+ JS . identifier ( "SpecialForms" )
24+ ) ,
25+ JS . identifier ( "_for" )
9626 ) ,
97- new_identifier
27+ [ collections , fun , filter , into ]
9828 )
99-
100- Builder . for_of_statement (
101- variable_declaration ,
102- Translator . translate ( enum , env ) ,
103- Builder . block_statement (
104- [
105- Builder . if_statement (
106- Utils . make_match ( i , new_identifier , env ) ,
107- Builder . block_statement ( variables ++ List . wrap ( handle_generators ( tl ( generators ) , env ) ) )
108- )
109- ]
110- )
111- )
112- end
113-
114- defp push_last_expression ( % ESTree.BlockStatement { } = block ) do
115- % ESTree.BlockStatement { block | body: push_last_expression ( block . body ) }
116- end
117-
118- defp push_last_expression ( [ ] ) do
119- build_push_ast ( Builder . literal ( nil ) )
12029 end
12130
122- defp push_last_expression ( list ) when is_list ( list ) do
123- last_item = List . last ( list )
124-
125- last_item = case last_item do
126- % ESTree.Literal { } ->
127- build_push_ast ( last_item )
128- % ESTree.Identifier { } ->
129- build_push_ast ( last_item )
130- % ESTree.VariableDeclaration { } ->
131- declaration = hd ( last_item . declarations ) . id
132-
133- push_statement = case declaration do
134- % ESTree.ArrayPattern { } ->
135- build_push_ast ( Builder . array_expression ( declaration . elements ) )
136- _ ->
137- build_push_ast ( declaration )
138- end
139-
140- [ last_item , push_statement ]
141- % ESTree.IfStatement { } ->
142-
143- consequent = push_last_expression ( last_item . consequent )
144-
145- alternate = if last_item . alternate do
146- push_last_expression ( last_item . alternate )
147- else
148- nil
149- end
150-
151- last_item = % ESTree.IfStatement { last_item | consequent: consequent , alternate: alternate }
152- % ElixirScript.Translator.Group { body: body } ->
153- last_item = push_last_expression ( body )
154- % ESTree.BlockStatement { } ->
155- last_item = % ESTree.BlockStatement { last_item | body: push_last_expression ( last_item . body ) }
156- _ ->
157- if String . contains? ( last_item . type , "Expression" ) do
158- build_push_ast ( last_item )
159- else
160- [ last_item , build_push_ast ( Builder . literal ( nil ) ) ]
161- end
162- end
163-
164-
165- list = Enum . take ( list , length ( list ) - 1 )
166-
167- if is_list ( last_item ) do
168- list ++ last_item
169- else
170- list ++ [ last_item ]
171- end
172- end
173-
174- defp push_last_expression ( expression ) do
175- build_push_ast ( expression )
176- end
177-
178- defp build_push_ast ( param ) do
179-
180- Builder . expression_statement (
181- Builder . assignment_expression (
182- := ,
183- Builder . identifier ( :_results ) ,
184- Builder . call_expression (
185- Builder . member_expression (
186- Builder . identifier ( "List" ) ,
187- Builder . identifier ( "append" )
188- ) ,
189- [ Builder . identifier ( :_results ) , param ]
190- )
191- )
192- )
193-
194- end
31+ defp handle_args ( generators , env ) do
32+ Enum . reduce ( generators , % { collections: [ ] , args: [ ] , filter: nil , fun: nil , into: nil } , fn
33+ ( { :<- , [ ] , [ identifier , enum ] } , state ) ->
34+ { patterns , params } = Match . build_match ( [ identifier ] , env )
35+
36+ list = Primitive . make_list_no_translate ( [ hd ( patterns ) , Translator . translate ( enum , env ) ] )
37+
38+ % { state | collections: state . collections ++ [ list ] , args: state . args ++ params }
39+ ( [ into: expression ] , state ) ->
40+ % { state | into: Translator . translate ( expression , env ) }
41+ ( [ into: expression , do: expression2 ] , state ) ->
42+ fun = JS . function_expression (
43+ state . args ,
44+ [ ] ,
45+ Function . make_function_body ( expression2 , env )
46+ )
47+
48+ % { state | into: Translator . translate ( expression , env ) , fun: fun }
49+
50+ ( [ do: expression ] , state ) ->
51+
52+ fun = JS . function_expression (
53+ state . args ,
54+ [ ] ,
55+ Function . make_function_body ( expression , env )
56+ )
57+
58+ % { state | fun: fun }
59+ ( filter , state ) ->
60+ fun = JS . function_expression (
61+ state . args ,
62+ [ ] ,
63+ Function . make_function_body ( filter , env )
64+ )
19565
196-
66+ % { state | filter: fun }
67+ end )
68+ end
19769end
0 commit comments