1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2015-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%% Purpose : Inline high order lists functions from the lists module.
21
22-module(sys_core_fold_lists).
23
24-export([call/4]).
25
26-include("core_parse.hrl").
27
28%% We inline some very common higher order list operations.
29%% We use the same evaluation order as the library function.
30
31-spec call(cerl:c_call(), atom(), atom(), [cerl:cerl()]) ->
32		  'none' | cerl:cerl().
33
34call(#c_call{anno=Anno}, lists, all, [Arg1,Arg2]) ->
35    Loop = #c_var{name={'lists^all',1}},
36    F = #c_var{name='F'},
37    Xs = #c_var{name='Xs'},
38    X = #c_var{name='X'},
39    Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]},
40    CC1 = #c_clause{anno=Anno,
41                    pats=[#c_literal{val=true}], guard=#c_literal{val=true},
42		    body=#c_apply{anno=Anno, op=Loop, args=[Xs]}},
43    CC2 = #c_clause{anno=Anno,
44                    pats=[#c_literal{val=false}], guard=#c_literal{val=true},
45		    body=#c_literal{val=false}},
46    CC3 = #c_clause{anno=Anno,
47                    pats=[X], guard=#c_literal{val=true},
48		    body=match_fail(Anno, Err1)},
49    C1 = #c_clause{anno=Anno,
50                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
51		   body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
52				clauses = [CC1, CC2, CC3]}},
53    C2 = #c_clause{anno=Anno,
54                   pats=[#c_literal{val=[]}],
55		   guard=#c_call{module=#c_literal{val=erlang},
56				 name=#c_literal{val=is_function},
57				 args=[F, #c_literal{val=1}]},
58		   body=#c_literal{val=true}},
59    Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
60    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
61		   body=match_fail([{function_name,{'lists^all',1}}|Anno], Err2)},
62    Fun = #c_fun{vars=[Xs],
63		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
64    L = #c_var{name='L'},
65    #c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
66	   body=#c_letrec{defs=[{Loop,Fun}],
67			  body=#c_apply{anno=Anno, op=Loop, args=[L]}}};
68call(#c_call{anno=Anno}, lists, any, [Arg1,Arg2]) ->
69    Loop = #c_var{name={'lists^any',1}},
70    F = #c_var{name='F'},
71    Xs = #c_var{name='Xs'},
72    X = #c_var{name='X'},
73    Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]},
74    CC1 = #c_clause{anno=Anno,
75                    pats=[#c_literal{val=true}], guard=#c_literal{val=true},
76		    body=#c_literal{val=true}},
77    CC2 = #c_clause{anno=Anno,
78                    pats=[#c_literal{val=false}], guard=#c_literal{val=true},
79		    body=#c_apply{anno=Anno, op=Loop, args=[Xs]}},
80    CC3 = #c_clause{anno=Anno,
81                    pats=[X], guard=#c_literal{val=true},
82		    body=match_fail(Anno, Err1)},
83    C1 = #c_clause{anno=Anno,
84                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
85		   body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
86				clauses = [CC1, CC2, CC3]}},
87    C2 = #c_clause{anno=Anno,
88                   pats=[#c_literal{val=[]}],
89		   guard=#c_call{module=#c_literal{val=erlang},
90				 name=#c_literal{val=is_function},
91				 args=[F, #c_literal{val=1}]},
92		   body=#c_literal{val=false}},
93    Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
94    C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
95		   body=match_fail([{function_name,{'lists^any',1}}|Anno], Err2)},
96    Fun = #c_fun{vars=[Xs],
97		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
98    L = #c_var{name='L'},
99    #c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
100	   body=#c_letrec{defs=[{Loop,Fun}],
101			  body=#c_apply{anno=Anno, op=Loop, args=[L]}}};
102call(#c_call{anno=Anno}, lists, foreach, [Arg1,Arg2]) ->
103    Loop = #c_var{name={'lists^foreach',1}},
104    F = #c_var{name='F'},
105    Xs = #c_var{name='Xs'},
106    X = #c_var{name='X'},
107    C1 = #c_clause{anno=Anno,
108                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
109		   body=#c_seq{arg=#c_apply{anno=Anno, op=F, args=[X]},
110			       body=#c_apply{anno=Anno, op=Loop, args=[Xs]}}},
111    C2 = #c_clause{anno=Anno, pats=[#c_literal{val=[]}],
112		   guard=#c_call{module=#c_literal{val=erlang},
113				 name=#c_literal{val=is_function},
114				 args=[F, #c_literal{val=1}]},
115		   body=#c_literal{val=ok}},
116    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
117    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
118		   body=match_fail([{function_name,{'lists^foreach',1}}|Anno], Err)},
119    Fun = #c_fun{vars=[Xs],
120		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
121    L = #c_var{name='L'},
122    #c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
123	   body=#c_letrec{defs=[{Loop,Fun}],
124			  body=#c_apply{anno=Anno, op=Loop, args=[L]}}};
125call(#c_call{anno=Anno}, lists, map, [Arg1,Arg2]) ->
126    Loop = #c_var{name={'lists^map',1}},
127    F = #c_var{name='F'},
128    Xs = #c_var{name='Xs'},
129    X = #c_var{name='X'},
130    H = #c_var{name='H'},
131    C1 = #c_clause{anno=Anno,
132                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
133		   body=#c_let{vars=[H], arg=#c_apply{anno=Anno,
134						      op=F,
135						      args=[X]},
136			       body=#c_cons{hd=H,
137					    anno=[compiler_generated],
138					    tl=#c_apply{anno=Anno,
139							op=Loop,
140							args=[Xs]}}}},
141    C2 = #c_clause{anno=Anno, pats=[#c_literal{val=[]}],
142		   guard=#c_call{module=#c_literal{val=erlang},
143				 name=#c_literal{val=is_function},
144				 args=[F, #c_literal{val=1}]},
145		   body=#c_literal{val=[]}},
146    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
147    C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
148		   body=match_fail([{function_name,{'lists^map',1}}|Anno], Err)},
149    Fun = #c_fun{vars=[Xs],
150		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
151    L = #c_var{name='L'},
152    #c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
153	   body=#c_letrec{defs=[{Loop,Fun}],
154			  body=#c_apply{anno=Anno, op=Loop, args=[L]}}};
155call(#c_call{anno=Anno}, lists, flatmap, [Arg1,Arg2]) ->
156    Loop = #c_var{name={'lists^flatmap',1}},
157    F = #c_var{name='F'},
158    Xs = #c_var{name='Xs'},
159    X = #c_var{name='X'},
160    H = #c_var{name='H'},
161    C1 = #c_clause{anno=Anno,
162                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
163		   body=#c_let{vars=[H],
164			       arg=#c_apply{anno=Anno, op=F, args=[X]},
165			       body=#c_call{anno=[compiler_generated|Anno],
166					    module=#c_literal{val=erlang},
167					    name=#c_literal{val='++'},
168					    args=[H,
169						  #c_apply{anno=Anno,
170							   op=Loop,
171							   args=[Xs]}]}}},
172    C2 = #c_clause{anno=Anno, pats=[#c_literal{val=[]}],
173		   guard=#c_call{module=#c_literal{val=erlang},
174				 name=#c_literal{val=is_function},
175				 args=[F, #c_literal{val=1}]},
176		   body=#c_literal{val=[]}},
177    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
178    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
179		   body=match_fail([{function_name,{'lists^flatmap',1}}|Anno], Err)},
180    Fun = #c_fun{vars=[Xs],
181		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
182    L = #c_var{name='L'},
183    #c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
184	   body=#c_letrec{defs=[{Loop,Fun}],
185			  body=#c_apply{anno=Anno, op=Loop, args=[L]}}};
186call(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2]) ->
187    Loop = #c_var{name={'lists^filter',1}},
188    F = #c_var{name='F'},
189    Xs = #c_var{name='Xs'},
190    X = #c_var{name='X'},
191    B = #c_var{name='B'},
192    Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]},
193    CC1 = #c_clause{anno=Anno,
194                    pats=[#c_literal{val=true}], guard=#c_literal{val=true},
195		    body=#c_cons{anno=[compiler_generated], hd=X, tl=Xs}},
196    CC2 = #c_clause{anno=Anno,
197                    pats=[#c_literal{val=false}], guard=#c_literal{val=true},
198		    body=Xs},
199    CC3 = #c_clause{anno=Anno, pats=[X], guard=#c_literal{val=true},
200		    body=match_fail(Anno, Err1)},
201    Case = #c_case{arg=B, clauses = [CC1, CC2, CC3]},
202    C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
203		   body=#c_let{vars=[B],
204			       arg=#c_apply{anno=Anno, op=F, args=[X]},
205			       body=#c_let{vars=[Xs],
206					   arg=#c_apply{anno=Anno,
207							op=Loop,
208							args=[Xs]},
209					   body=Case}}},
210    C2 = #c_clause{anno=Anno,
211                   pats=[#c_literal{val=[]}],
212		   guard=#c_call{module=#c_literal{val=erlang},
213				 name=#c_literal{val=is_function},
214				 args=[F, #c_literal{val=1}]},
215		   body=#c_literal{val=[]}},
216    Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
217    C3 = #c_clause{anno=Anno,
218                   pats=[Xs], guard=#c_literal{val=true},
219		   body=match_fail([{function_name,{'lists^filter',1}}|Anno], Err2)},
220    Fun = #c_fun{vars=[Xs],
221		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
222    L = #c_var{name='L'},
223    #c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
224		body=#c_letrec{defs=[{Loop,Fun}],
225			       body=#c_apply{anno=Anno, op=Loop, args=[L]}}};
226call(#c_call{anno=Anno}, lists, foldl, [Arg1,Arg2,Arg3]) ->
227    Loop = #c_var{name={'lists^foldl',2}},
228    F = #c_var{name='F'},
229    Xs = #c_var{name='Xs'},
230    X = #c_var{name='X'},
231    A = #c_var{name='A'},
232    C1 = #c_clause{anno=Anno,
233                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
234		   body=#c_apply{anno=Anno,
235				 op=Loop,
236				 args=[Xs, #c_apply{anno=Anno,
237						    op=F,
238						    args=[X, A]}]}},
239    C2 = #c_clause{anno=Anno, pats=[#c_literal{val=[]}],
240		   guard=#c_call{module=#c_literal{val=erlang},
241				 name=#c_literal{val=is_function},
242				 args=[F, #c_literal{val=2}]},
243		   body=A},
244    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]},
245    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
246		   body=match_fail([{function_name,{'lists^foldl',2}}|Anno], Err)},
247    Fun = #c_fun{vars=[Xs, A],
248		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
249    L = #c_var{name='L'},
250    #c_let{vars=[F, A, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
251	   body=#c_letrec{defs=[{Loop,Fun}],
252			  body=#c_apply{anno=Anno, op=Loop, args=[L, A]}}};
253call(#c_call{anno=Anno}, lists, foldr, [Arg1,Arg2,Arg3]) ->
254    Loop = #c_var{name={'lists^foldr',2}},
255    F = #c_var{name='F'},
256    Xs = #c_var{name='Xs'},
257    X = #c_var{name='X'},
258    A = #c_var{name='A'},
259    C1 = #c_clause{anno=Anno,
260                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
261		   body=#c_apply{anno=Anno,
262				 op=F,
263				 args=[X, #c_apply{anno=Anno,
264						   op=Loop,
265						   args=[Xs, A]}]}},
266    C2 = #c_clause{anno=Anno, pats=[#c_literal{val=[]}],
267		   guard=#c_call{module=#c_literal{val=erlang},
268				 name=#c_literal{val=is_function},
269				 args=[F, #c_literal{val=2}]},
270		   body=A},
271    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]},
272    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
273		   body=match_fail([{function_name,{'lists^foldr',2}}|Anno], Err)},
274    Fun = #c_fun{vars=[Xs, A],
275		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
276    L = #c_var{name='L'},
277    #c_let{vars=[F, A, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
278	   body=#c_letrec{defs=[{Loop,Fun}],
279			  body=#c_apply{anno=Anno, op=Loop, args=[L, A]}}};
280call(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3]) ->
281    Loop = #c_var{name={'lists^mapfoldl',2}},
282    F = #c_var{name='F'},
283    Xs = #c_var{name='Xs'},
284    X = #c_var{name='X'},
285    Avar = #c_var{name='A'},
286    Match =
287	fun (A, P, E) ->
288		C1 = #c_clause{anno=Anno, pats=[P], guard=#c_literal{val=true}, body=E},
289		Err = #c_tuple{es=[#c_literal{val='badmatch'}, X]},
290		C2 = #c_clause{anno=Anno, pats=[X], guard=#c_literal{val=true},
291			       body=match_fail(Anno, Err)},
292		#c_case{arg=A, clauses=[C1, C2]}
293	end,
294    C1 = #c_clause{anno=Anno,
295                   pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
296		   body=Match(#c_apply{anno=Anno, op=F, args=[X, Avar]},
297			      #c_tuple{es=[X, Avar]},
298%%% Tuple passing version
299			      Match(#c_apply{anno=Anno,
300					     op=Loop,
301					     args=[Xs, Avar]},
302				    #c_tuple{es=[Xs, Avar]},
303				    #c_tuple{anno=[compiler_generated],
304					     es=[#c_cons{anno=[compiler_generated],
305							 hd=X, tl=Xs},
306						 Avar]})
307%%% Multiple-value version
308%%% 			      #c_let{vars=[Xs,A],
309%%% 				     %% The tuple here will be optimised
310%%% 				     %% away later; no worries.
311%%% 				     arg=#c_apply{op=Loop, args=[Xs, A]},
312%%% 				     body=#c_values{es=[#c_cons{hd=X, tl=Xs},
313%%% 							A]}}
314			     )},
315    C2 = #c_clause{anno=Anno, pats=[#c_literal{val=[]}],
316		   guard=#c_call{module=#c_literal{val=erlang},
317				 name=#c_literal{val=is_function},
318				 args=[F, #c_literal{val=2}]},
319%%% Tuple passing version
320		   body=#c_tuple{anno=[compiler_generated],
321				 es=[#c_literal{val=[]}, Avar]}},
322%%% Multiple-value version
323%%% 		   body=#c_values{es=[#c_literal{val=[]}, A]}},
324    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]},
325    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
326		   body=match_fail([{function_name,{'lists^mapfoldl',2}}|Anno], Err)},
327    Fun = #c_fun{vars=[Xs, Avar],
328		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
329    L = #c_var{name='L'},
330    #c_let{vars=[F, Avar, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
331	   body=#c_letrec{defs=[{Loop,Fun}],
332%%% Tuple passing version
333			  body=#c_apply{anno=Anno,
334					op=Loop,
335					args=[L, Avar]}}};
336%%% Multiple-value version
337%%% 			       body=#c_let{vars=[Xs, A],
338%%% 					   arg=#c_apply{op=Loop,
339%%% 							args=[L, A]},
340%%% 					   body=#c_tuple{es=[Xs, A]}}}};
341call(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3]) ->
342    Loop = #c_var{name={'lists^mapfoldr',2}},
343    F = #c_var{name='F'},
344    Xs = #c_var{name='Xs'},
345    X = #c_var{name='X'},
346    Avar = #c_var{name='A'},
347    Match =
348	fun (A, P, E) ->
349		C1 = #c_clause{anno=Anno, pats=[P], guard=#c_literal{val=true}, body=E},
350		Err = #c_tuple{es=[#c_literal{val='badmatch'}, X]},
351		C2 = #c_clause{anno=Anno, pats=[X], guard=#c_literal{val=true},
352			       body=match_fail(Anno, Err)},
353		#c_case{arg=A, clauses=[C1, C2]}
354	end,
355    C1 = #c_clause{anno=Anno, pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
356%%% Tuple passing version
357		   body=Match(#c_apply{anno=Anno,
358				       op=Loop,
359				       args=[Xs, Avar]},
360			      #c_tuple{es=[Xs, Avar]},
361			      Match(#c_apply{anno=Anno, op=F, args=[X, Avar]},
362				    #c_tuple{es=[X, Avar]},
363				    #c_tuple{anno=[compiler_generated],
364					     es=[#c_cons{anno=[compiler_generated],
365							 hd=X, tl=Xs}, Avar]}))
366%%% Multiple-value version
367%%% 		   body=#c_let{vars=[Xs,A],
368%%% 			       %% The tuple will be optimised away
369%%% 			       arg=#c_apply{op=Loop, args=[Xs, A]},
370%%% 			       body=Match(#c_apply{op=F, args=[X, A]},
371%%% 					  #c_tuple{es=[X, A]},
372%%% 					  #c_values{es=[#c_cons{hd=X, tl=Xs},
373%%% 						        A]})}
374		  },
375    C2 = #c_clause{anno=Anno,
376                   pats=[#c_literal{val=[]}],
377		   guard=#c_call{module=#c_literal{val=erlang},
378				 name=#c_literal{val=is_function},
379				 args=[F, #c_literal{val=2}]},
380%%% Tuple passing version
381		   body=#c_tuple{anno=[compiler_generated],
382				 es=[#c_literal{val=[]}, Avar]}},
383%%% Multiple-value version
384%%% 		   body=#c_values{es=[#c_literal{val=[]}, A]}},
385    Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]},
386    C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
387		   body=match_fail([{function_name,{'lists^mapfoldr',2}}|Anno], Err)},
388    Fun = #c_fun{vars=[Xs, Avar],
389		 body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
390    L = #c_var{name='L'},
391    #c_let{vars=[F, Avar, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
392	   body=#c_letrec{defs=[{Loop,Fun}],
393%%% Tuple passing version
394			  body=#c_apply{anno=Anno,
395					op=Loop,
396					args=[L, Avar]}}};
397%%% Multiple-value version
398%%% 			       body=#c_let{vars=[Xs, A],
399%%% 					   arg=#c_apply{op=Loop,
400%%% 							args=[L, A]},
401%%% 					   body=#c_tuple{es=[Xs, A]}}}};
402call(_, _, _, _) ->
403    none.
404
405match_fail(Ann, Arg) ->
406    Name = cerl:abstract(match_fail),
407    Args = [Arg],
408    cerl:ann_c_primop(Ann, Name, Args).
409