diff options
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/doc/src/compile.xml | 26 | ||||
-rw-r--r-- | lib/compiler/src/beam_dict.erl | 18 | ||||
-rw-r--r-- | lib/compiler/src/compile.erl | 13 | ||||
-rw-r--r-- | lib/compiler/src/core_scan.erl | 27 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 112 | ||||
-rw-r--r-- | lib/compiler/src/sys_pre_expand.erl | 66 | ||||
-rw-r--r-- | lib/compiler/src/v3_kernel.erl | 31 | ||||
-rw-r--r-- | lib/compiler/test/compilation_SUITE.erl | 3 | ||||
-rw-r--r-- | lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl | 28 | ||||
-rw-r--r-- | lib/compiler/test/compile_SUITE.erl | 30 | ||||
-rw-r--r-- | lib/compiler/test/inline_SUITE.erl | 43 |
11 files changed, 205 insertions, 192 deletions
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml index 27d750f929..ddaae2655d 100644 --- a/lib/compiler/doc/src/compile.xml +++ b/lib/compiler/doc/src/compile.xml @@ -816,6 +816,32 @@ pi() -> 3.1416. </section> <section> + <title>Inlining of list functions</title> + <p>The compiler can also inline a variety of list manipulation functions + from the stdlib's lists module.</p> + + <p>This feature must be explicitly enabled with a compiler option or a + <c>-compile()</c> attribute in the source module.</p> + + <p>To enable inlining of list functions, use the <c>inline_list_funcs</c> + option.</p> + + <p>The following functions are inlined:</p> + <list type="bulleted"> + <item><seealso marker="stdlib:lists#all/2">lists:all/2</seealso></item> + <item><seealso marker="stdlib:lists#any/2">lists:any/2</seealso></item> + <item><seealso marker="stdlib:lists#foreach/2">lists:foreach/2</seealso></item> + <item><seealso marker="stdlib:lists#map/2">lists:map/2</seealso></item> + <item><seealso marker="stdlib:lists#flatmap/2">lists:flatmap/2</seealso></item> + <item><seealso marker="stdlib:lists#filter/2">lists:filter/2</seealso></item> + <item><seealso marker="stdlib:lists#foldl/3">lists:foldl/3</seealso></item> + <item><seealso marker="stdlib:lists#foldr/3">lists:foldr/3</seealso></item> + <item><seealso marker="stdlib:lists#mapfoldl/3">lists:mapfoldl/3</seealso></item> + <item><seealso marker="stdlib:lists#mapfoldr/3">lists:mapfoldr/3</seealso></item> + </list> + </section> + + <section> <title>Parse Transformations</title> <p>Parse transformations are used when a programmer wants to use diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl index 531968b3c8..ff6c7c11dc 100644 --- a/lib/compiler/src/beam_dict.erl +++ b/lib/compiler/src/beam_dict.erl @@ -138,7 +138,17 @@ string(Str, Dict) when is_list(Str) -> -spec lambda(label(), non_neg_integer(), bdict()) -> {non_neg_integer(), bdict()}. -lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) -> +lambda(Lbl, 0, #asm{lambdas=Lambdas0}=Dict) -> + case lists:keyfind(Lbl, 1, Lambdas0) of + {Lbl,{OldIndex,_,_,_,_}} -> + {OldIndex,Dict}; + false -> + new_lambda(Lbl, 0, Dict) + end; +lambda(Lbl, NumFree, Dict) -> + new_lambda(Lbl, NumFree, Dict). + +new_lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) -> OldIndex = length(Lambdas0), %% Set Index the same as OldIndex. Index = OldIndex, @@ -235,10 +245,12 @@ string_table(#asm{strings=Strings,string_offset=Size}) -> -spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}. -lambda_table(#asm{locals=Loc0,lambdas=Lambdas0}) -> +lambda_table(#asm{exports=Ext0,locals=Loc0,lambdas=Lambdas0}) -> Lambdas1 = sofs:relation(Lambdas0), Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]), - Lambdas2 = sofs:relative_product1(Lambdas1, Loc), + Ext = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Ext0]), + All = sofs:union(Loc, Ext), + Lambdas2 = sofs:relative_product1(Lambdas1, All), Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> || {{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)], {length(Lambdas),Lambdas}. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index a3120eb917..2d1557fa5b 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -907,11 +907,8 @@ add_default_base(St, Forms) -> F = St#compile.filename, case F of "" -> - M = case get_module(Forms) of - PackageModule when is_list(PackageModule) -> last(PackageModule); - M0 -> M0 - end, - St#compile{base = atom_to_list(M)}; + M = get_module(Forms), + St#compile{base=atom_to_list(M)}; _ -> St end. @@ -1342,16 +1339,12 @@ save_binary(#compile{code=none}=St) -> {ok,St}; save_binary(#compile{module=Mod,ofile=Outfile, options=Opts}=St) -> %% Test that the module name and output file name match. - %% We must take care to not completely break a packaged module - %% (even though packages still is as an experimental, unsupported - %% feature) - so we will extract the last part of a packaged - %% module name and compare only that. case member(no_error_module_mismatch, Opts) of true -> save_binary_1(St); false -> Base = filename:rootname(filename:basename(Outfile)), - case lists:last(packages:split(Mod)) of + case atom_to_list(Mod) of Base -> save_binary_1(St); _ -> diff --git a/lib/compiler/src/core_scan.erl b/lib/compiler/src/core_scan.erl index 5aab8ae855..0ca2f57dde 100644 --- a/lib/compiler/src/core_scan.erl +++ b/lib/compiler/src/core_scan.erl @@ -1,7 +1,8 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% Copyright Ericsson AB 2000-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -31,16 +32,16 @@ %% 173 - 176 { - ~ punctuation %% 177 DEL control %% 200 - 237 control -%% 240 - 277 NBSP - � punctuation -%% 300 - 326 � - � uppercase -%% 327 � punctuation -%% 330 - 336 � - � uppercase -%% 337 - 366 � - � lowercase -%% 367 � punctuation -%% 370 - 377 � - � lowercase +%% 240 - 277 NBSP - ¿ punctuation +%% 300 - 326 À - Ö uppercase +%% 327 × punctuation +%% 330 - 336 Ø - Þ uppercase +%% 337 - 366 ß - ö lowercase +%% 367 ÷ punctuation +%% 370 - 377 ø - ÿ lowercase %% %% Many punctuation characters region have special meaning. Must -%% watch using � \327, bvery close to x \170 +%% watch using × \327, bvery close to x \170 -module(core_scan). @@ -239,11 +240,11 @@ scan1([C|Cs], Toks, Pos) when C >= $\200, C =< $\240 -> scan1(Cs, Toks, Pos); scan1([C|Cs], Toks, Pos) when C >= $a, C =< $z -> %Keywords scan_key_word(C, Cs, Toks, Pos); -scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� -> +scan1([C|Cs], Toks, Pos) when C >= $ß, C =< $ÿ, C /= $÷ -> scan_key_word(C, Cs, Toks, Pos); scan1([C|Cs], Toks, Pos) when C >= $A, C =< $Z -> %Variables scan_variable(C, Cs, Toks, Pos); -scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� -> +scan1([C|Cs], Toks, Pos) when C >= $À, C =< $Þ, C /= $× -> scan_variable(C, Cs, Toks, Pos); scan1([C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Numbers scan_number(C, Cs, Toks, Pos); @@ -308,9 +309,9 @@ scan_name([], Ncs) -> {Ncs,[]}. name_char(C) when C >= $a, C =< $z -> true; -name_char(C) when C >= $�, C =< $�, C /= $� -> true; +name_char(C) when C >= $ß, C =< $ÿ, C /= $÷ -> true; name_char(C) when C >= $A, C =< $Z -> true; -name_char(C) when C >= $�, C =< $�, C /= $� -> true; +name_char(C) when C >= $À, C =< $Þ, C /= $× -> true; name_char(C) when C >= $0, C =< $9 -> true; name_char($_) -> true; name_char($@) -> true; diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 18fba7962b..f17b0bd130 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -686,11 +686,14 @@ call_1(#c_call{anno=Anno}, lists, all, [Arg1,Arg2], Sub) -> C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true}, body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]}, clauses = [CC1, CC2, CC3]}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=1}]}, body=#c_literal{val=true}}, - Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err2)}, + body=match_fail([{function_name,{'lists^all',1}}|Anno], Err2)}, Fun = #c_fun{vars=[Xs], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -713,11 +716,14 @@ call_1(#c_call{anno=Anno}, lists, any, [Arg1,Arg2], Sub) -> C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true}, body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]}, clauses = [CC1, CC2, CC3]}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=1}]}, body=#c_literal{val=false}}, - Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err2)}, + body=match_fail([{function_name,{'lists^any',1}}|Anno], Err2)}, Fun = #c_fun{vars=[Xs], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -733,11 +739,14 @@ call_1(#c_call{anno=Anno}, lists, foreach, [Arg1,Arg2], Sub) -> C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true}, body=#c_seq{arg=#c_apply{anno=Anno, op=F, args=[X]}, body=#c_apply{anno=Anno, op=Loop, args=[Xs]}}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=1}]}, body=#c_literal{val=ok}}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^foreach',1}}|Anno], Err)}, Fun = #c_fun{vars=[Xs], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -756,14 +765,18 @@ call_1(#c_call{anno=Anno}, lists, map, [Arg1,Arg2], Sub) -> op=F, args=[X]}, body=#c_cons{hd=H, + anno=[compiler_generated], tl=#c_apply{anno=Anno, op=Loop, args=[Xs]}}}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=1}]}, body=#c_literal{val=[]}}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^map',1}}|Anno], Err)}, Fun = #c_fun{vars=[Xs], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -780,18 +793,21 @@ call_1(#c_call{anno=Anno}, lists, flatmap, [Arg1,Arg2], Sub) -> C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true}, body=#c_let{vars=[H], arg=#c_apply{anno=Anno, op=F, args=[X]}, - body=#c_call{anno=Anno, + body=#c_call{anno=[compiler_generated|Anno], module=#c_literal{val=erlang}, name=#c_literal{val='++'}, args=[H, #c_apply{anno=Anno, op=Loop, args=[Xs]}]}}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=1}]}, body=#c_literal{val=[]}}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^flatmap',1}}|Anno], Err)}, Fun = #c_fun{vars=[Xs], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -807,7 +823,7 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) -> B = #c_var{name='B'}, Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]}, CC1 = #c_clause{pats=[#c_literal{val=true}], guard=#c_literal{val=true}, - body=#c_cons{hd=X, tl=Xs}}, + body=#c_cons{anno=[compiler_generated], hd=X, tl=Xs}}, CC2 = #c_clause{pats=[#c_literal{val=false}], guard=#c_literal{val=true}, body=Xs}, CC3 = #c_clause{pats=[X], guard=#c_literal{val=true}, @@ -821,11 +837,14 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) -> op=Loop, args=[Xs]}, body=Case}}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=1}]}, body=#c_literal{val=[]}}, - Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err2)}, + body=match_fail([{function_name,{'lists^filter',1}}|Anno], Err2)}, Fun = #c_fun{vars=[Xs], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -845,10 +864,14 @@ call_1(#c_call{anno=Anno}, lists, foldl, [Arg1,Arg2,Arg3], Sub) -> args=[Xs, #c_apply{anno=Anno, op=F, args=[X, A]}]}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=2}]}, + body=A}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^foldl',2}}|Anno], Err)}, Fun = #c_fun{vars=[Xs, A], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -868,10 +891,14 @@ call_1(#c_call{anno=Anno}, lists, foldr, [Arg1,Arg2,Arg3], Sub) -> args=[X, #c_apply{anno=Anno, op=Loop, args=[Xs, A]}]}}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=2}]}, + body=A}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^foldr',2}}|Anno], Err)}, Fun = #c_fun{vars=[Xs, A], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -901,7 +928,10 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) -> op=Loop, args=[Xs, Avar]}, #c_tuple{es=[Xs, Avar]}, - #c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]}) + #c_tuple{anno=[compiler_generated], + es=[#c_cons{anno=[compiler_generated], + hd=X, tl=Xs}, + Avar]}) %%% Multiple-value version %%% #c_let{vars=[Xs,A], %%% %% The tuple here will be optimised @@ -910,14 +940,18 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) -> %%% body=#c_values{es=[#c_cons{hd=X, tl=Xs}, %%% A]}} )}, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=2}]}, %%% Tuple passing version - body=#c_tuple{es=[#c_literal{val=[]}, Avar]}}, + body=#c_tuple{anno=[compiler_generated], + es=[#c_literal{val=[]}, Avar]}}, %%% Multiple-value version %%% body=#c_values{es=[#c_literal{val=[]}, A]}}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^mapfoldl',2}}|Anno], Err)}, Fun = #c_fun{vars=[Xs, Avar], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, @@ -955,7 +989,9 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) -> #c_tuple{es=[Xs, Avar]}, Match(#c_apply{anno=Anno, op=F, args=[X, Avar]}, #c_tuple{es=[X, Avar]}, - #c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]})) + #c_tuple{anno=[compiler_generated], + es=[#c_cons{anno=[compiler_generated], + hd=X, tl=Xs}, Avar]})) %%% Multiple-value version %%% body=#c_let{vars=[Xs,A], %%% %% The tuple will be optimised away @@ -965,14 +1001,18 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) -> %%% #c_values{es=[#c_cons{hd=X, tl=Xs}, %%% A]})} }, - C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, + C2 = #c_clause{pats=[#c_literal{val=[]}], + guard=#c_call{module=#c_literal{val=erlang}, + name=#c_literal{val=is_function}, + args=[F, #c_literal{val=2}]}, %%% Tuple passing version - body=#c_tuple{es=[#c_literal{val=[]}, Avar]}}, + body=#c_tuple{anno=[compiler_generated], + es=[#c_literal{val=[]}, Avar]}}, %%% Multiple-value version %%% body=#c_values{es=[#c_literal{val=[]}, A]}}, - Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]}, + Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]}, C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true}, - body=match_fail(Anno, Err)}, + body=match_fail([{function_name,{'lists^mapfoldr',2}}|Anno], Err)}, Fun = #c_fun{vars=[Xs, Avar], body=#c_case{arg=Xs, clauses=[C1, C2, C3]}}, L = #c_var{name='L'}, diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index e55fb2a037..a8c69c3cb1 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -35,10 +35,8 @@ -record(expand, {module=[], %Module name parameters=undefined, %Module parameters - package="", %Module package exports=[], %Exports imports=[], %Imports - mod_imports, %Module Imports compile=[], %Compile flags attributes=[], %Attributes callbacks=[], %Callbacks @@ -67,12 +65,8 @@ module(Fs0, Opts0) -> %% Set pre-defined exported functions. PreExp = [{module_info,0},{module_info,1}], - %% Set pre-defined module imports. - PreModImp = [{erlang,erlang},{packages,packages}], - %% Build initial expand record. St0 = #expand{exports=PreExp, - mod_imports=dict:from_list(PreModImp), compile=Opts, defined=PreExp, bitdefault = erl_bits:system_bitdefault(), @@ -242,14 +236,12 @@ forms([], St) -> {[],St}. %% Process an attribute, this just affects the state. attribute(module, {Module, As}, _L, St) -> - M = package_to_string(Module), - St#expand{module=list_to_atom(M), - package=packages:strip_last(M), + true = is_atom(Module), + St#expand{module=Module, parameters=As}; attribute(module, Module, _L, St) -> - M = package_to_string(Module), - St#expand{module=list_to_atom(M), - package=packages:strip_last(M)}; + true = is_atom(Module), + St#expand{module=Module}; attribute(export, Es, _L, St) -> St#expand{exports=union(from_list(Es), St#expand.exports)}; attribute(import, Is, _L, St) -> @@ -312,8 +304,6 @@ pattern({tuple,Line,Ps}, St0) -> %%pattern({struct,Line,Tag,Ps}, St0) -> %% {TPs,TPsvs,St1} = pattern_list(Ps, St0), %% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1}; -pattern({record_field,_,_,_}=M, St) -> - {expand_package(M, St),St}; % must be a package name pattern({bin,Line,Es0}, St0) -> {Es1,St1} = pattern_bin(Es0, St0), {{bin,Line,Es1},St1}; @@ -404,8 +394,6 @@ expr({tuple,Line,Es0}, St0) -> %%expr({struct,Line,Tag,Es0}, Vs, St0) -> %% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0), %% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1}; -expr({record_field,_,_,_}=M, St) -> - {expand_package(M, St),St}; % must be a package name expr({bin,Line,Es0}, St0) -> {Es1,St1} = expr_bin(Es0, St0), {{bin,Line,Es1},St1}; @@ -448,12 +436,9 @@ expr({call,Line,{atom,La,N}=Atom,As0}, St0) -> end end end; -expr({call,Line,{record_field,_,_,_}=M,As0}, St0) -> - expr({call,Line,expand_package(M, St0),As0}, St0); -expr({call,Line,{remote,Lr,M,F},As0}, St0) -> - M1 = expand_package(M, St0), - {[M2,F1|As1],St1} = expr_list([M1,F|As0], St0), - {{call,Line,{remote,Lr,M2,F1},As1},St1}; +expr({call,Line,{remote,Lr,M0,F},As0}, St0) -> + {[M1,F1|As1],St1} = expr_list([M0,F|As0], St0), + {{call,Line,{remote,Lr,M1,F1},As1},St1}; expr({call,Line,F,As0}, St0) -> {[Fun1|As1],St1} = expr_list([F|As0], St0), {{call,Line,Fun1,As1},St1}; @@ -666,32 +651,6 @@ string_to_conses(Line, Cs, Tail) -> foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs). -%% In syntax trees, module/package names are atoms or lists of atoms. - -package_to_string(A) when is_atom(A) -> atom_to_list(A); -package_to_string(L) when is_list(L) -> packages:concat(L). - -expand_package({atom,L,A} = M, St) -> - case dict:find(A, St#expand.mod_imports) of - {ok, A1} -> - {atom,L,A1}; - error -> - case packages:is_segmented(A) of - true -> - M; - false -> - M1 = packages:concat(St#expand.package, A), - {atom,L,list_to_atom(M1)} - end - end; -expand_package(M, _St) -> - case erl_parse:package_segments(M) of - error -> - M; - M1 -> - {atom,element(2,M),list_to_atom(package_to_string(M1))} - end. - %% import(Line, Imports, State) -> %% State' %% imported(Name, Arity, State) -> @@ -699,15 +658,10 @@ expand_package(M, _St) -> %% Handle import declarations and test for imported functions. No need to %% check when building imports as code is correct. -import({Mod0,Fs}, St) -> - Mod = list_to_atom(package_to_string(Mod0)), +import({Mod,Fs}, St) -> + true = is_atom(Mod), Mfs = from_list(Fs), - St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}; -import(Mod0, St) -> - Mod = package_to_string(Mod0), - Key = list_to_atom(packages:last(Mod)), - St#expand{mod_imports=dict:store(Key, list_to_atom(Mod), - St#expand.mod_imports)}. + St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}. add_imports(Mod, [F|Fs], Is) -> add_imports(Mod, Fs, orddict:store(F, Mod, Is)); diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index 8ef71e1346..b1bff47f69 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -235,16 +235,8 @@ gexpr_test_add(Ke, St0) -> %% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}. %% Convert a Core expression, flattening it at the same time. -expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) -> - %% A local in an expression. - %% For now, these are wrapped into a fun by reverse - %% etha-conversion, but really, there should be exactly one - %% such "lambda function" for each escaping local name, - %% instead of one for each occurrence as done now. - Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} || - V <- integers(1, Arity)], - Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}}, - expr(Fun, Sub, St); +expr(#c_var{anno=A,name={Name,Arity}}, Sub, St) -> + {#k_local{anno=A,name=get_fsub(Name, Arity, Sub),arity=Arity},[],St}; expr(#c_var{anno=A,name=V}, Sub, St) -> {#k_var{anno=A,name=get_vsub(V, Sub)},[],St}; expr(#c_literal{anno=A,val=V}, _Sub, St) -> @@ -1663,6 +1655,19 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) -> #k_int{val=Index},#k_int{val=Uniq}|Fvs], ret=Rs}, Free,add_local_function(Fun, St)}; +uexpr(#k_local{anno=A,name=Name,arity=Arity}, {break,Rs}, St) -> + Fs = get_free(Name, Arity, St), + FsCount = length(Fs), + Free = lit_list_vars(Fs), + %% Set dummy values for Index and Uniq -- the real values will + %% be assigned by beam_asm. + Index = Uniq = 0, + Bif = #k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A}, + op=#k_internal{name=make_fun,arity=FsCount+3}, + args=[#k_atom{val=Name},#k_int{val=FsCount+Arity}, + #k_int{val=Index},#k_int{val=Uniq}|Fs], + ret=Rs}, + {Bif,Free,St}; uexpr(Lit, {break,Rs0}, St0) -> %% Transform literals to puts here. %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]), @@ -1843,12 +1848,6 @@ make_list(Es) -> #c_cons{hd=E,tl=Acc} end, #c_literal{val=[]}, Es). -%% List of integers in interval [N,M]. Empty list if N > M. - -integers(N, M) when N =< M -> - [N|integers(N + 1, M)]; -integers(_, _) -> []. - %% is_in_guard(State) -> true|false. is_in_guard(#kern{guard_refc=Refc}) -> diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index bec97b0199..f8f74e6f7a 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -44,7 +44,7 @@ groups() -> {group,vsn},otp_2380,otp_2141,otp_2173,otp_4790, const_list_256,bin_syntax_1,bin_syntax_2, bin_syntax_3,bin_syntax_4,bin_syntax_5,bin_syntax_6, - live_var,convopts,bad_functional_value, + live_var,convopts, catch_in_catch,redundant_case,long_string,otp_5076, complex_guard,otp_5092,otp_5151,otp_5235,otp_5244, trycatch_4,opt_crash,otp_5404,otp_5436,otp_5481, @@ -143,7 +143,6 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) -> ?comp(live_var). ?comp(trycatch_4). -?comp(bad_functional_value). ?comp(catch_in_catch). diff --git a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl deleted file mode 100644 index 126a573e83..0000000000 --- a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl +++ /dev/null @@ -1,28 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(bad_functional_value). - --export([?MODULE/0,a/0]). - -?MODULE() -> - ok. - -a() -> - .list_to_atom("ok"). - diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 2cd75944f4..229e5a98a1 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -27,7 +27,7 @@ app_test/1, file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1, binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, - other_output/1, package_forms/1, encrypted_abstr/1, + other_output/1, encrypted_abstr/1, bad_record_use1/1, bad_record_use2/1, strict_record/1, missing_testheap/1, cover/1, env/1, core/1, asm/1, sys_pre_attributes/1]). @@ -44,7 +44,7 @@ all() -> test_lib:recompile(?MODULE), [app_test, file_1, forms_2, module_mismatch, big_file, outdir, binary, makedep, cond_and_ifdef, listings, listings_big, - other_output, package_forms, encrypted_abstr, + other_output, encrypted_abstr, {group, bad_record_use}, strict_record, missing_testheap, cover, env, core, asm, sys_pre_attributes]. @@ -410,32 +410,6 @@ other_output(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. -package_forms(Config) when is_list(Config) -> - Fs = [{attribute,1,file,{"./p.erl",1}}, - {attribute,1,module,[p,p]}, - {attribute,3,compile,export_all}, - {attribute,1,file, - {"/clearcase/otp/erts/lib/stdlib/include/qlc.hrl",1}}, - {attribute,6,file,{"./p.erl",6}}, - {function,7,q,0, - [{clause,7,[],[], - [{call,8, - {remote,8,{atom,8,qlc},{atom,8,q}}, - [{tuple,-8, - [{atom,-8,qlc_lc}, - {'fun',-8, - {clauses, - [{clause,-8,[],[], - [{tuple,-8, - [{atom,-8,simple_v1}, - {atom,-8,'X'}, - {'fun',-8,{clauses,[{clause,-8,[],[],[{nil,8}]}]}}, - {integer,-8,8}]}]}]}}, - {atom,-8,undefined}]}]}]}]}, - {eof,9}], - {ok,'p.p',_} = compile:forms(Fs, ['S',report]), - ok. - encrypted_abstr(Config) when is_list(Config) -> ?line Dog = test_server:timetrap(test_server:minutes(10)), ?line {Simple,Target} = files(Config, "encrypted_abstr"), diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl index e2eb6a0dec..6dc7548437 100644 --- a/lib/compiler/test/inline_SUITE.erl +++ b/lib/compiler/test/inline_SUITE.erl @@ -258,6 +258,49 @@ lists(Config) when is_list(Config) -> %% Cleanup. erase(?MODULE), + + {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} = + (catch lists:map(fun (X) -> X end, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} = + (catch lists:flatmap(fun (X) -> X end, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} = + (catch lists:foreach(fun (X) -> X end, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} = + (catch lists:filter(fun (_) -> true end, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} = + (catch lists:any(fun (_) -> false end, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} = + (catch lists:all(fun (_) -> true end, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} = + (catch lists:foldl(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} = + (catch lists:foldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} = + (catch lists:mapfoldl(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)), + {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} = + (catch lists:mapfoldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)), + + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} = + (catch lists:map(not_a_function, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} = + (catch lists:flatmap(not_a_function, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} = + (catch lists:foreach(not_a_function, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} = + (catch lists:filter(not_a_function, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} = + (catch lists:any(not_a_function, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} = + (catch lists:all(not_a_function, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} = + (catch lists:foldl(not_a_function, acc, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} = + (catch lists:foldr(not_a_function, acc, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} = + (catch lists:mapfoldl(not_a_function, acc, [])), + {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} = + (catch lists:mapfoldr(not_a_function, acc, [])), + ok. my_apply(M, F, A, Init) -> |