Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix incorrect duplicated module search #36

Closed
wants to merge 11 commits into from

4 participants

@Zert

Hello

Dialyzer sometimes prins incorrect duplicate modules. I wrote mail to mailing list some days ago but not got any reply.

Description of issue: http://erlang.org/pipermail/erlang-bugs/2013-March/003465.html

DeadZen and others added some commits
@DeadZen DeadZen Implement add_report_sup_handler which calls gen_event:add_sup_handler 0b9f404
@nox nox Remove the reverse eta-conversion from v3_kernel
Local function references should be handled directly as a make_fun
internal BIF call instead of creating an extra lambda function every
time they are used.
0386b0d
@nox nox Make trace_local_SUITE work without the reverse eta conversion
The exceptions tracing tests look for {trace_local_SUITE,exc,2} in
stacktraces to strip them and compare them to the excepted result, the
removal of the reverse eta conversion renames '-exception_test/3-fun-0-'
to exc and thus confuses the stripping code. This commit fix this by
not using `fun exc/2` but `fun (F, As) -> exc(F, As) end` instead, which
was what the reverse eta conversion was doing.
92a8961
@nox nox Don't use fun references in cprof_SUITE
Using fun references make a less complicated cprof use case now that the
eta abstraction is gone from v3_kernel.
a675977
@gustehn gustehn Merge branch 'dg/win_icon' into pu 80bb37d
@gustehn gustehn Merge branch 'rc/break-out-asserts' into pu 7e75bf5
@gustehn gustehn Merge branch 'pn/error-logger-sup_handler' into pu 75da625
@gustehn gustehn Merge branch 'ks/hipe-cleanup-escaping' into pu 62d00d4
@gustehn gustehn Merge branch 'mh/emacs-package' into pu 7b1c6fb
@gustehn gustehn Merge branch 'nox/rm-reverse-eta-conversion/OTP-10682' into pu 6b309c8
@Zert Zert Fix incorrect duplicated module search 49ec73a
@nox

This should probably be closed, right?

@Zert

Yes

@Zert Zert closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 1, 2013
  1. @DeadZen
Commits on Mar 18, 2013
  1. @nox

    Remove the reverse eta-conversion from v3_kernel

    nox authored
    Local function references should be handled directly as a make_fun
    internal BIF call instead of creating an extra lambda function every
    time they are used.
  2. @nox

    Make trace_local_SUITE work without the reverse eta conversion

    nox authored
    The exceptions tracing tests look for {trace_local_SUITE,exc,2} in
    stacktraces to strip them and compare them to the excepted result, the
    removal of the reverse eta conversion renames '-exception_test/3-fun-0-'
    to exc and thus confuses the stripping code. This commit fix this by
    not using `fun exc/2` but `fun (F, As) -> exc(F, As) end` instead, which
    was what the reverse eta conversion was doing.
  3. @nox

    Don't use fun references in cprof_SUITE

    nox authored
    Using fun references make a less complicated cprof use case now that the
    eta abstraction is gone from v3_kernel.
Commits on Mar 28, 2013
  1. @gustehn
  2. @gustehn
  3. @gustehn
  4. @gustehn
  5. @gustehn
  6. @gustehn
Commits on Mar 29, 2013
  1. @Zert
This page is out of date. Refresh to see the latest.
View
2  erts/emulator/test/trace_local_SUITE.erl
@@ -874,7 +874,7 @@ exception_test(Opts, Func0, Args0) ->
%% wrap them in wrappers...
?line {Func1,Args1} =
case Function of
- true -> {fun exc/2,[Func0,Args0]};
+ true -> {fun (F, As) -> exc(F, As) end,[Func0,Args0]};
false -> {Func0,Args0}
end,
View
BIN  erts/etc/win32/erlang.ico
Binary file not shown
View
18 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}.
View
31 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}) ->
View
8 lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -255,10 +255,12 @@ compile_and_store(Files, #analysis_state{codeserver = CServer,
CServer2 = dialyzer_codeserver:set_next_core_label(NextLabel, CServer),
case Failed =:= [] of
true ->
- NewFiles = lists:zip(lists:reverse(Modules), Files),
ModDict =
- lists:foldl(fun({Mod, F}, Dict) -> dict:append(Mod, F, Dict) end,
- dict:new(), NewFiles),
+ lists:foldl(fun(F, Dict) ->
+ ModFile = lists:last(filename:split(F)),
+ Mod = filename:basename(ModFile, ".beam"),
+ dict:append(Mod, F, Dict) end,
+ dict:new(), Files),
check_for_duplicate_modules(ModDict);
false ->
Msg = io_lib:format("Could not scan the following file(s): ~p",
View
195 lib/eunit/include/eunit.hrl
@@ -16,6 +16,9 @@
%%
%% Copyright (C) 2004-2006 Mickaël Rémond, Richard Carlsson
+-ifndef(EUNIT_HRL).
+-define(EUNIT_HRL, true).
+
%% Including this file turns on testing and defines TEST, unless NOTEST
%% is defined before the file is included. If both NOTEST and TEST are
%% already defined, then TEST takes precedence, and NOTEST will become
@@ -36,9 +39,6 @@
%% After including this file, EUNIT will be defined if and only if TEST
%% is defined.
--ifndef(EUNIT_HRL).
--define(EUNIT_HRL, true).
-
%% allow defining TEST to override NOTEST
-ifdef(TEST).
@@ -50,13 +50,6 @@
-undef(NODEBUG).
-endif.
-%% allow NODEBUG to imply NOASSERT, unless overridden below
--ifdef(NODEBUG).
--ifndef(NOASSERT).
--define(NOASSERT, true).
--endif.
--endif.
-
%% note that the main switch used within this file is NOTEST; however,
%% both TEST and EUNIT may be used to check whether testing is enabled
-ifndef(NOTEST).
@@ -71,10 +64,8 @@
-undef(EUNIT).
-endif.
-%% allow ASSERT to override NOASSERT (regardless of TEST/NOTEST)
--ifdef(ASSERT).
--undef(NOASSERT).
--endif.
+%% include the assert macros; ASSERT overrides NOASSERT if defined
+-include_lib("stdlib/include/assert.hrl").
%% Parse transforms for automatic exporting/stripping of test functions.
%% (Note that although automatic stripping is convenient, it will make
@@ -129,195 +120,21 @@
current_function)))).
-endif.
-%% The plain assert macro should be defined to do nothing if this file
-%% is included when debugging/testing is turned off.
--ifdef(NOASSERT).
--ifndef(assert).
--define(assert(BoolExpr),ok).
--endif.
--else.
-%% The assert macro is written the way it is so as not to cause warnings
-%% for clauses that cannot match, even if the expression is a constant.
--undef(assert).
--define(assert(BoolExpr),
- ((fun () ->
- case (BoolExpr) of
- true -> ok;
- __V -> erlang:error({assertion_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??BoolExpr)},
- {expected, true},
- {value, case __V of false -> __V;
- _ -> {not_a_boolean,__V}
- end}]})
- end
- end)())).
--endif.
--define(assertNot(BoolExpr), ?assert(not (BoolExpr))).
+%% General test macros
-define(_test(Expr), {?LINE, fun () -> (Expr) end}).
-
-define(_assert(BoolExpr), ?_test(?assert(BoolExpr))).
-
-define(_assertNot(BoolExpr), ?_assert(not (BoolExpr))).
-
-%% This is mostly a convenience which gives more detailed reports.
-%% Note: Guard is a guarded pattern, and can not be used for value.
--ifdef(NOASSERT).
--define(assertMatch(Guard, Expr), ok).
--else.
--define(assertMatch(Guard, Expr),
- ((fun () ->
- case (Expr) of
- Guard -> ok;
- __V -> erlang:error({assertMatch_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern, (??Guard)},
- {value, __V}]})
- end
- end)())).
--endif.
-define(_assertMatch(Guard, Expr), ?_test(?assertMatch(Guard, Expr))).
-
-%% This is the inverse case of assertMatch, for convenience.
--ifdef(NOASSERT).
--define(assertNotMatch(Guard, Expr), ok).
--else.
--define(assertNotMatch(Guard, Expr),
- ((fun () ->
- __V = (Expr),
- case __V of
- Guard -> erlang:error({assertNotMatch_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern, (??Guard)},
- {value, __V}]});
- _ -> ok
- end
- end)())).
--endif.
-define(_assertNotMatch(Guard, Expr), ?_test(?assertNotMatch(Guard, Expr))).
-
-%% This is a convenience macro which gives more detailed reports when
-%% the expected LHS value is not a pattern, but a computed value
--ifdef(NOASSERT).
--define(assertEqual(Expect, Expr), ok).
--else.
--define(assertEqual(Expect, Expr),
- ((fun (__X) ->
- case (Expr) of
- __X -> ok;
- __V -> erlang:error({assertEqual_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {expected, __X},
- {value, __V}]})
- end
- end)(Expect))).
--endif.
-define(_assertEqual(Expect, Expr), ?_test(?assertEqual(Expect, Expr))).
-
-%% This is the inverse case of assertEqual, for convenience.
--ifdef(NOASSERT).
--define(assertNotEqual(Unexpected, Expr), ok).
--else.
--define(assertNotEqual(Unexpected, Expr),
- ((fun (__X) ->
- case (Expr) of
- __X -> erlang:error({assertNotEqual_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {value, __X}]});
- _ -> ok
- end
- end)(Unexpected))).
--endif.
-define(_assertNotEqual(Unexpected, Expr),
?_test(?assertNotEqual(Unexpected, Expr))).
-
-%% Note: Class and Term are patterns, and can not be used for value.
-%% Term can be a guarded pattern, but Class cannot.
--ifdef(NOASSERT).
--define(assertException(Class, Term, Expr), ok).
--else.
--define(assertException(Class, Term, Expr),
- ((fun () ->
- try (Expr) of
- __V -> erlang:error({assertException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "++(??Term)
- ++" , [...] }"},
- {unexpected_success, __V}]})
- catch
- Class:Term -> ok;
- __C:__T ->
- erlang:error({assertException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "++(??Term)
- ++" , [...] }"},
- {unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()}}]})
- end
- end)())).
--endif.
-
--define(assertError(Term, Expr), ?assertException(error, Term, Expr)).
--define(assertExit(Term, Expr), ?assertException(exit, Term, Expr)).
--define(assertThrow(Term, Expr), ?assertException(throw, Term, Expr)).
-
-define(_assertException(Class, Term, Expr),
?_test(?assertException(Class, Term, Expr))).
-define(_assertError(Term, Expr), ?_assertException(error, Term, Expr)).
-define(_assertExit(Term, Expr), ?_assertException(exit, Term, Expr)).
-define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)).
-
-%% This is the inverse case of assertException, for convenience.
-%% Note: Class and Term are patterns, and can not be used for value.
-%% Both Class and Term can be guarded patterns.
--ifdef(NOASSERT).
--define(assertNotException(Class, Term, Expr), ok).
--else.
--define(assertNotException(Class, Term, Expr),
- ((fun () ->
- try (Expr) of
- _ -> ok
- catch
- __C:__T ->
- case __C of
- Class ->
- case __T of
- Term ->
- erlang:error({assertNotException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "
- ++(??Term)++" , [...] }"},
- {unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()
- }}]});
- _ -> ok
- end;
- _ -> ok
- end
- end
- end)())).
--endif.
-define(_assertNotException(Class, Term, Expr),
?_test(?assertNotException(Class, Term, Expr))).
View
2  lib/eunit/src/Makefile
@@ -24,7 +24,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/eunit-$(VSN)
EBIN = ../ebin
INCLUDE=../include
-ERL_COMPILE_FLAGS += -pa $(EBIN) -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard
+ERL_COMPILE_FLAGS += -pa $(EBIN) -pa ../../stdlib/ebin -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard
PARSE_TRANSFORM = eunit_autoexport.erl
View
18 lib/hipe/icode/hipe_icode_coordinator.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. 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
@@ -36,18 +36,16 @@
%%---------------------------------------------------------------------
--spec coordinate(hipe_digraph:hdg(), [{mfa(),boolean()}], [mfa()], module()) ->
+-spec coordinate(hipe_digraph:hdg(), [mfa()], [mfa()], module()) ->
no_return().
coordinate(CG, Escaping, NonEscaping, Mod) ->
ServerPid = initialize_server(Escaping, Mod),
- Clean = [MFA || {MFA, _} <- Escaping],
- All = NonEscaping ++ Clean,
- Restart =
- fun (MFALists, PM) -> restart_funs(MFALists, PM, All, ServerPid) end,
- LastAction =
- fun (PM) -> last_action(PM, ServerPid, Mod, All) end,
- coordinate({Clean,All}, CG, gb_trees:empty(), Restart, LastAction, ServerPid).
+ All = ordsets:from_list(Escaping ++ NonEscaping),
+ Restart = fun (MFALs, PM) -> restart_funs(MFALs, PM, All, ServerPid) end,
+ LastAction = fun (PM) -> last_action(PM, ServerPid, Mod, All) end,
+ MFALists = {Escaping, All},
+ coordinate(MFALists, CG, gb_trees:empty(), Restart, LastAction, ServerPid).
-type mfalists() :: {[mfa()], [mfa()]}.
@@ -129,7 +127,7 @@ restart_funs({Queue, Busy} = QB, PM, All, ServerPid) ->
initialize_server(Escaping, Mod) ->
Pid = spawn_link(fun () -> info_server(Mod) end),
- lists:foreach(fun ({MFA, _}) -> Pid ! {set_escaping, MFA} end, Escaping),
+ lists:foreach(fun (MFA) -> Pid ! {set_escaping, MFA} end, Escaping),
Pid.
safe_get_args(MFA, Cfg, Pid, Mod) ->
View
21 lib/hipe/main/hipe.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -242,8 +242,7 @@
%%
%% @see load/2
--spec load(Mod) -> {'module', Mod} | {'error', term()}
- when is_subtype(Mod, mod()).
+-spec load(Mod) -> {'module', Mod} | {'error', term()} when Mod :: mod().
load(Mod) ->
load(Mod, beam_file(Mod)).
@@ -265,7 +264,7 @@ load(Mod) ->
%% @see load/1
-spec load(Mod, string()) -> {'module', Mod} | {'error', term()}
- when is_subtype(Mod, mod()).
+ when Mod :: mod().
load(Mod, BeamFileName) when is_list(BeamFileName) ->
Architecture = erlang:system_info(hipe_architecture),
@@ -522,7 +521,7 @@ compile(Name, Core, File, Opts) when is_atom(Name) ->
%% @equiv file(File, [])
-spec file(Mod) -> {'ok', Mod, compile_ret()} | {'error', term()}
- when is_subtype(Mod, mod()).
+ when Mod :: mod().
file(File) ->
file(File, []).
@@ -542,7 +541,7 @@ file(File) ->
-spec file(Mod, comp_options()) -> {'ok', Mod, compile_ret()}
| {'error', term()}
- when is_subtype(Mod, mod()).
+ when Mod :: mod().
file(File, Options) when is_atom(File) ->
case beam_lib:info(File) of
L when is_list(L) ->
@@ -760,13 +759,15 @@ finalize_fun_concurrent(MfaIcodeList, Exports, Opts) ->
case MfaIcodeList of
[{{M,_,_},_}|_] ->
CallGraph = hipe_icode_callgraph:construct_callgraph(MfaIcodeList),
- Closures = [{MFA, true} || {MFA, Icode} <- MfaIcodeList,
- hipe_icode:icode_is_closure(Icode)],
- Exported = [{{M, F, A}, false} || {F, A} <- Exports],
+ Exported = [{M, F, A} || {F, A} <- Exports],
+ Closures = [MFA || {MFA, Icode} <- MfaIcodeList,
+ hipe_icode:icode_is_closure(Icode)],
+ %% In principle, a function could both be exported and used as a
+ %% closure so make sure to add it only once in Escaping below
+ Escaping = ordsets:from_list(Exported ++ Closures),
NonEscaping = [MFA || {{_M, F, A} = MFA, Icode} <- MfaIcodeList,
not lists:member({F, A}, Exports),
not hipe_icode:icode_is_closure(Icode)],
- Escaping = Closures ++ Exported,
TypeServerFun =
fun() ->
hipe_icode_coordinator:coordinate(CallGraph, Escaping,
View
16 lib/kernel/src/error_logger.erl
@@ -24,6 +24,7 @@
info_msg/1,info_msg/2,warning_msg/1,warning_msg/2,
logfile/1,tty/1,swap_handler/1,
add_report_handler/1,add_report_handler/2,
+ add_report_sup_handler/1,add_report_sup_handler/2,
delete_report_handler/1]).
-export([init/1,
@@ -272,6 +273,21 @@ add_report_handler(Module) when is_atom(Module) ->
add_report_handler(Module, Args) when is_atom(Module) ->
gen_event:add_handler(error_logger, Module, Args).
+-spec add_report_sup_handler(Handler) -> any() when
+ Handler :: module().
+
+add_report_sup_handler(Module) when is_atom(Module) ->
+ gen_event:add_sup_handler(error_logger, Module, []).
+
+-spec add_report_sup_handler(Handler, Args) -> Result when
+ Handler :: module(),
+ Args :: gen_event:handler_args(),
+ Result :: gen_event:add_handler_ret().
+
+add_report_sup_handler(Module, Args) when is_atom(Module) ->
+ gen_event:add_sup_handler(error_logger, Module, Args).
+
+
-spec delete_report_handler(Handler) -> Result when
Handler :: module(),
Result :: gen_event:del_handler_ret().
View
230 lib/stdlib/include/assert.hrl
@@ -0,0 +1,230 @@
+%% Licensed under the Apache License, Version 2.0 (the "License"); you may
+%% not use this file except in compliance with the License. You may obtain
+%% a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% Copyright (C) 2004-2012 Richard Carlsson, Mickaël Rémond
+
+-ifndef(ASSERT_HRL).
+-define(ASSERT_HRL, true).
+
+%% Asserts are enabled unless NOASSERT is defined, and ASSERT can be used to
+%% override it: if both ASSERT and NOASSERT are defined, then ASSERT takes
+%% precedence, and NOASSERT will become undefined.
+%%
+%% Furthermore, if NODEBUG is defined, it implies NOASSERT, unless DEBUG or
+%% ASSERT are defined.
+
+
+%% allow NODEBUG to imply NOASSERT, unless DEBUG
+-ifdef(NODEBUG).
+-ifndef(DEBUG).
+-ifndef(NOASSERT).
+-define(NOASSERT, true).
+-endif.
+-endif.
+-endif.
+
+
+%% allow ASSERT to override NOASSERT
+-ifdef(ASSERT).
+-undef(NOASSERT).
+-endif.
+
+
+%% Assert macros must not depend on any non-kernel or stdlib libraries.
+%%
+%% We must use fun-call wrappers ((fun () -> ... end)()) to avoid
+%% exporting local variables, and furthermore we only use variable names
+%% prefixed with "__", that hopefully will not be bound outside the fun.
+%% It is not possible to nest assert macros.
+
+
+%% The plain assert macro should be defined to do nothing if this file is
+%% included when asserts are turned off, but avoid getting a compilation
+%% error if a macro called assert is already defined for some reason.
+-ifdef(NOASSERT).
+-ifndef(assert).
+-define(assert(BoolExpr),ok).
+-endif.
+-else.
+%% The assert macro is written the way it is so as not to cause warnings
+%% for clauses that cannot match, even if the expression is a constant.
+-undef(assert).
+-define(assert(BoolExpr),
+ ((fun () ->
+ case (BoolExpr) of
+ true -> ok;
+ __V -> erlang:error({assertion_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??BoolExpr)},
+ {expected, true},
+ {value, case __V of false -> __V;
+ _ -> {not_a_boolean,__V}
+ end}]})
+ end
+ end)())).
+-endif.
+
+-define(assertNot(BoolExpr), ?assert(not (BoolExpr))).
+
+
+%% This is mostly a convenience which gives more detailed reports.
+%% Note: Guard is a guarded pattern, and can not be used for value.
+-ifdef(NOASSERT).
+-define(assertMatch(Guard, Expr), ok).
+-else.
+-define(assertMatch(Guard, Expr),
+ ((fun () ->
+ case (Expr) of
+ Guard -> ok;
+ __V -> erlang:error({assertMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]})
+ end
+ end)())).
+-endif.
+
+
+%% This is the inverse case of assertMatch, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotMatch(Guard, Expr), ok).
+-else.
+-define(assertNotMatch(Guard, Expr),
+ ((fun () ->
+ __V = (Expr),
+ case __V of
+ Guard -> erlang:error({assertNotMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]});
+ _ -> ok
+ end
+ end)())).
+-endif.
+
+
+%% This is a convenience macro which gives more detailed reports when
+%% the expected LHS value is not a pattern, but a computed value
+-ifdef(NOASSERT).
+-define(assertEqual(Expect, Expr), ok).
+-else.
+-define(assertEqual(Expect, Expr),
+ ((fun (__X) ->
+ case (Expr) of
+ __X -> ok;
+ __V -> erlang:error({assertEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {expected, __X},
+ {value, __V}]})
+ end
+ end)(Expect))).
+-endif.
+
+
+%% This is the inverse case of assertEqual, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotEqual(Unexpected, Expr), ok).
+-else.
+-define(assertNotEqual(Unexpected, Expr),
+ ((fun (__X) ->
+ case (Expr) of
+ __X -> erlang:error({assertNotEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {value, __X}]});
+ _ -> ok
+ end
+ end)(Unexpected))).
+-endif.
+
+
+%% Note: Class and Term are patterns, and can not be used for value.
+%% Term can be a guarded pattern, but Class cannot.
+-ifdef(NOASSERT).
+-define(assertException(Class, Term, Expr), ok).
+-else.
+-define(assertException(Class, Term, Expr),
+ ((fun () ->
+ try (Expr) of
+ __V -> erlang:error({assertException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "++(??Term)
+ ++" , [...] }"},
+ {unexpected_success, __V}]})
+ catch
+ Class:Term -> ok;
+ __C:__T ->
+ erlang:error({assertException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "++(??Term)
+ ++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ erlang:get_stacktrace()}}]})
+ end
+ end)())).
+-endif.
+
+-define(assertError(Term, Expr), ?assertException(error, Term, Expr)).
+-define(assertExit(Term, Expr), ?assertException(exit, Term, Expr)).
+-define(assertThrow(Term, Expr), ?assertException(throw, Term, Expr)).
+
+
+%% This is the inverse case of assertException, for convenience.
+%% Note: Class and Term are patterns, and can not be used for value.
+%% Both Class and Term can be guarded patterns.
+-ifdef(NOASSERT).
+-define(assertNotException(Class, Term, Expr), ok).
+-else.
+-define(assertNotException(Class, Term, Expr),
+ ((fun () ->
+ try (Expr) of
+ _ -> ok
+ catch
+ __C:__T ->
+ case __C of
+ Class ->
+ case __T of
+ Term ->
+ erlang:error({assertNotException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "
+ ++(??Term)++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ erlang:get_stacktrace()
+ }}]});
+ _ -> ok
+ end;
+ _ -> ok
+ end
+ end
+ end)())).
+-endif.
+
+
+-endif. % ASSERT_HRL
View
1  lib/stdlib/src/Makefile
@@ -120,6 +120,7 @@ MODULES= \
zip
HRL_FILES= \
+ ../include/assert.hrl \
../include/erl_compile.hrl \
../include/erl_bits.hrl \
../include/ms_transform.hrl \
View
3  lib/stdlib/test/Makefile
@@ -101,7 +101,8 @@ RELSYSDIR = $(RELEASE_PATH)/stdlib_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
- -I$(ERL_TOP)/lib/kernel/include
+ -I$(ERL_TOP)/lib/kernel/include \
+ -I$(ERL_TOP)/lib/stdlib/include
EBIN = .
View
29 lib/stdlib/test/stdlib_SUITE.erl
@@ -33,7 +33,7 @@
-export([init_per_testcase/2, end_per_testcase/2]).
% Test cases must be exported.
--export([app_test/1, appup_test/1]).
+-export([app_test/1, appup_test/1, assert_test/1]).
%%
%% all/1
@@ -41,7 +41,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app_test, appup_test].
+ [app_test, appup_test, assert_test].
groups() ->
[].
@@ -136,3 +136,28 @@ check_appup([Vsn|Vsns],Instrs,Expected) ->
end;
check_appup([],_,_) ->
ok.
+
+-include_lib("stdlib/include/assert.hrl").
+-include_lib("stdlib/include/assert.hrl"). % test repeated inclusion
+assert_test(suite) ->
+ [];
+assert_test(doc) ->
+ ["Assert macros test."];
+assert_test(_Config) ->
+ ?assert(1 =:= 1),
+ ?assertNot(1 =:= 1.0),
+ ?assertMatch({foo,_}, {foo,bar}),
+ ?assertNotMatch({foo,_}, {foo,bar,baz}),
+ ?assertMatch({foo,N} when N > 0, {foo,1}),
+ ?assertNotMatch({foo,N} when N > 0, {foo,0}),
+ ?assertEqual(1.0, 1.0),
+ ?assertNotEqual(1, 1.0),
+ ?assertException(error, badarith, 1/0),
+ ?assertException(exit, foo, exit(foo)),
+ ?assertException(throw, foo, throw(foo)),
+ ?assertException(throw, {foo,_}, throw({foo,bar})),
+ ?assertNotException(throw, {foo,baz}, throw({foo,bar})),
+ ?assertError(badarith, 1/0),
+ ?assertExit(foo, exit(foo)),
+ ?assertThrow(foo, throw(foo)),
+ ok.
View
3  lib/tools/emacs/erlang-start.el
@@ -83,6 +83,7 @@
;; Associate files extensions ".erl" and ".hrl" with Erlang mode.
;;
+;;;###autoload
(let ((a '("\\.erl\\'" . erlang-mode))
(b '("\\.hrl\\'" . erlang-mode)))
(or (assoc (car a) auto-mode-alist)
@@ -94,6 +95,7 @@
;; Associate files using interpreter "escript" with Erlang mode.
;;
+;;;###autoload
(add-to-list 'interpreter-mode-alist (cons "escript" 'erlang-mode))
;;
@@ -101,6 +103,7 @@
;; file completion.
;;
+;;;###autoload
(let ((erl-ext '(".jam" ".vee" ".beam")))
(while erl-ext
(let ((cie completion-ignored-extensions))
View
16 lib/tools/test/cprof_SUITE.erl
@@ -230,10 +230,10 @@ on_load_test(Config) ->
%%
?line N4 = cprof:restart(),
?line {ok,Module} = c:c(File, [{outdir,Priv}]),
- ?line L = Module:seq(1, M, fun succ/1),
- ?line Lr = Module:seq_r(1, M, fun succ/1),
- ?line L = seq(1, M, fun succ/1),
- ?line Lr = seq_r(1, M, fun succ/1),
+ ?line L = Module:seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = Module:seq_r(1, M, fun (I) -> succ(I) end),
+ ?line L = seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = seq_r(1, M, fun (I) -> succ(I) end),
?line N2 = cprof:pause(),
?line {Module,0,[]} = cprof:analyse(Module),
?line M_1 = M - 1,
@@ -265,10 +265,10 @@ modules_test(Config) ->
?line M2__1 = M2 + 1,
?line erlang:yield(),
?line N = cprof:start(),
- ?line L = Module:seq(1, M, fun succ/1),
- ?line Lr = Module:seq_r(1, M, fun succ/1),
- ?line L = seq(1, M, fun succ/1),
- ?line Lr = seq_r(1, M, fun succ/1),
+ ?line L = Module:seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = Module:seq_r(1, M, fun (I) -> succ(I) end),
+ ?line L = seq(1, M, fun (I) -> succ(I) end),
+ ?line Lr = seq_r(1, M, fun (I) -> succ(I) end),
?line N = cprof:pause(),
?line Lr = lists:reverse(L),
?line M_1 = M - 1,
Something went wrong with that request. Please try again.