/
proper_report.erl
116 lines (105 loc) · 5 KB
/
proper_report.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
-module(proper_report).
-export([report/4, report_ct/4, report/5]).
-define(NAMES,
["MARY", "PATRICIA", "LINDA", "BARBARA", "ELIZABETH", "JENNIFER",
"MARIA", "SUSAN", "MARGARET","DOROTHY", "LISA", "NANCY", "KAREN",
"BETTY", "HELEN", "SANDRA", "DONNA", "CAROL", "RUTH", "SHARON",
"MICHELLE", "LAURA", "SARAH", "KIMBERLY", "DEBORAH", "JESSICA",
"SHIRLEY", "CYNTHIA", "ANGELA", "MELISSA", "BRENDA", "AMY", "ANNA",
"REBECCA","VIRGINIA", "KATHLEEN", "PAMELA", "MARTHA","DEBRA","AMANDA",
"STEPHANIE", "CAROLYN", "CHRISTINE", "MARIE", "JANET", "CATHERINE",
"FRANCES", "ANN", "JOYCE", "DIANE","ALICE","JULIE","HEATHER","TERESA",
"DORIS", "GLORIA", "EVELYN", "JEAN", "CHERYL", "MILDRED", "KATHERINE",
"JOAN", "ASHLEY", "JUDITH", "ROSE", "JANICE","KELLY","NICOLE", "JUDY",
"CHRISTINA", "KATHY", "THERESA", "BEVERLY", "DENISE", "TAMMY", "IRENE",
"JANE", "LORI", "RACHEL", "MARILYN", "ANDREA", "KATHRYN", "LOUISE",
"SARA", "ANNE", "JACQUELINE","WANDA","BONNIE","JULIA", "RUBY", "LOIS",
"TINA", "PHYLLIS", "NORMA","PAULA","DIANA","ANNIE", "LILLIAN", "EMILY",
"ROBIN"]).
report(Cmds, History, FinalState, Result) ->
report(Cmds, History, FinalState, Result, fun (Format, Data) -> io:format(user, Format, Data) end).
report_ct(Cmds, History, FinalState, Result) ->
report(Cmds, History, FinalState, Result, fun (Format, Data) -> ct:pal(Format, Data) end).
report([{init, _InitialState}|Cmds], History, FinalState, Result, Fun) ->
report(Cmds, History, FinalState, Result, Fun);
report(Cmds, History, FinalState, Result, Fun) ->
Vars = lists:sort(find_reused(Cmds)),
VarsArray = lists:foldl(
fun(X, A) -> array:set(X, array:get(X, A) + 1, A) end,
array:new({default, 0}), Vars),
VarsPLst = my_enumerate(array:sparse_to_orddict(VarsArray)),
States = [S || {S, _R} <- History] ++ [FinalState],
Results = [init|[R || {_S, R} <- History]],
FullHistory = lists:zip(Results, States),
Fun("~n---Result:~n~p~n", [Result]),
Sequence = [ translate(VarsPLst, Cmd) || Cmd <- Cmds],
Fun("~n---Command sequence:~n~s~n", [string:join(Sequence,"\n")]),
Fun("~n---States and results:~n", []),
AdjustedSequence = lists:reverse(
lists:nthtail(length(Sequence) + 1 -
length(FullHistory),
lists:reverse(["init"|Sequence]))),
[Fun("Command:~n~s~n"
"Result:~n~s~n"
"State was:~n~s~n"
"--------------------~n",
[
Command,
io_lib_pretty:print(Res, 1, 80, -1),
io_lib_pretty:print(State, 1, 80, -1)
])
|| {{Res, State}, Command} <- lists:zip(FullHistory,
AdjustedSequence) ].
find_reused(Cmds) ->
find_reused(Cmds, []).
find_reused({var, VarN}, Vars) ->
[VarN|Vars];
find_reused(Tuple, Vars) when is_tuple(Tuple) ->
find_reused(tuple_to_list(Tuple), Vars);
find_reused(Cmds, Vars) when is_list(Cmds) ->
VarsDeep = [find_reused(Cmd, Vars) || Cmd <- Cmds],
lists:flatten(VarsDeep);
find_reused(_, Vars) -> Vars.
translate(_VarsDict, init) ->
"Initial state";
translate(VarsDict, {set, {var, VarN}, Call}) ->
Prefix = case proplists:lookup(VarN, VarsDict) of
{_, none} -> "";
{_, Name} -> Name ++ " = "
end,
Prefix ++ translate_call(VarsDict, Call).
translate_call(VarsDict, {call, erlang, element, [N, {var, VarN}]}) ->
case proplists:lookup(VarN, VarsDict) of
{_, none} -> exit(var_not_exists);
{_, Name} -> io_lib:format("~s#~B", [Name, N])
end;
translate_call(VarsDict, {call, M, F, A}) ->
io_lib:format("~s:~s(~s)", [M, F, translate_args(VarsDict, A)]).
translate_args(VarsDict, Args) ->
TranslatedArgs = [translate_arg(VarsDict, Arg) || Arg <- Args],
string:join(TranslatedArgs, ", ").
translate_arg(VarsDict, {call, _, _, _}=C) -> translate_call(VarsDict, C);
translate_arg(VarsDict, {var, VarN}) ->
case proplists:lookup(VarN, VarsDict) of
{_, none} -> exit(var_not_exists);
{_, Name} -> io_lib:format("~s#~B", [Name, VarN])
end;
translate_arg(VarsDict, X) when is_list(X) ->
PL = io_lib:printable_list(X),
PUL = io_lib:printable_unicode_list(X),
if
X == [] -> "[]";
PL -> lists:flatten(io_lib:format("~p",[X]));
PUL -> lists:flatten(io_lib:format("~tp",[X]));
true -> "[" ++ translate_args(VarsDict, X) ++ "]"
end;
translate_arg(VarsDict, X) when is_tuple(X) ->
"{" ++ translate_args(VarsDict, tuple_to_list(X)) ++ "}";
translate_arg(_VarsDict, X) -> io_lib:format("~p", [X]).
my_enumerate(Lst) ->
lists:reverse(my_enumerate(Lst, ?NAMES, [])).
my_enumerate([], _, Res) -> Res;
my_enumerate([{Var, Num}|Rest], [Name|Names], Res) when Num > 1 ->
my_enumerate(Rest, Names, [{Var, Name}|Res]);
my_enumerate([{Var, _Num}|Rest], Names, Res) ->
my_enumerate(Rest, Names, [{Var, none}|Res]).