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