[m-rev.] for post-commit review: cords in the deep_profiler
Zoltan Somogyi
zs at csse.unimelb.edu.au
Mon Aug 4 13:16:40 AEST 2008
Convert Paul's new code to use cords of strings to represent HTML.
deep_profiler/html_format.m:
Convert to using cords. Restructure the code in a couple of places
to always put start and end tags around HTML fragments together.
Fix a missing "=" in a tag.
deep_profiler/interface.m:
deep_profiler/mdprof_cgi.m:
deep_profiler/read_profile.m:
Provide better diagnostics.
deep_profiler/create_report.m:
deep_profiler/display.m:
deep_profiler/display_report.m:
deep_profiler/mdprof_feedback.m:
deep_profiler/measurement_units.m:
deep_profiler/query.m:
deep_profiler/report.m:
mdbcomp/feedback.m:
Misc cleanups. They can be considered my post-commit review of Paul's
diff.
In mdprof_feedback.m, delete a strange test that prevented the program
from being used from the command line.
deep_profiler/dump.m:
deep_profiler/mdprof_dump.m:
deep_profiler/timeout.m:
deep_profiler/util.m:
Misc cleanups of old code.
Zoltan.
cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
Index: deep_profiler/create_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/create_report.m,v
retrieving revision 1.1
diff -u -b -r1.1 create_report.m
--- deep_profiler/create_report.m 29 Jul 2008 01:42:59 -0000 1.1
+++ deep_profiler/create_report.m 3 Aug 2008 14:52:53 -0000
@@ -9,8 +9,7 @@
% File: create_report.m.
% Author: pbone.
%
-% This module contains the create_report predicate that creates a report
-% from a deep data structure and a query.
+% This module creates a report from a deep data structure and a query.
%
%-----------------------------------------------------------------------------%
@@ -43,30 +42,31 @@
%-----------------------------------------------------------------------------%
-create_report(deep_cmd_quit, Deep, Report) :-
- Report = report_message(string.format(
- "Shutting down deep profile server for %s.",
- [s(Deep ^ data_file_name)])).
-
-create_report(deep_cmd_timeout(Timeout), _Deep, Report) :-
- Report = report_message(string.format(
- "Timeout set to %d minutes.", [i(Timeout)])).
-
-create_report(deep_cmd_restart, _, _) :-
- error("create_report/3", "unexpected restart command").
-
-create_report(deep_cmd_menu, Deep, Report) :-
+create_report(Cmd, Deep, Report) :-
+ (
+ Cmd = deep_cmd_quit,
+ Msg = string.format("Shutting down deep profile server for %s.",
+ [s(Deep ^ data_file_name)]),
+ Report = report_message(Msg)
+ ;
+ Cmd = deep_cmd_timeout(Timeout),
+ Msg = string.format("Timeout set to %d minutes.", [i(Timeout)]),
+ Report = report_message(Msg)
+ ;
+ Cmd = deep_cmd_menu,
Deep ^ profile_stats = profile_stats(NumCSD, NumCSS, NumPD, NumPS,
- QuantaPerSec, InstrumentationQuanta, UserQuanta, NumCallsequs, _, _),
- NumClique = array.max(Deep ^ clique_members),
+ QuantaPerSec, InstrumentationQuanta, UserQuanta, NumCallsequs,
+ _, _),
+ NumCliques = array.max(Deep ^ clique_members),
Report = report_menu(QuantaPerSec, UserQuanta, InstrumentationQuanta,
- NumCallsequs, NumCSD, NumCSS, NumPD, NumPS, NumClique).
-
-create_report(deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope), Deep,
- Report) :-
- create_top_procs_report(Deep, Limit, CostKind, InclDesc, Scope, Report).
-
-create_report(Cmd, _, _) :-
+ NumCallsequs, NumCSD, NumCSS, NumPD, NumPS, NumCliques)
+ ;
+ Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
+ create_top_procs_report(Deep, Limit, CostKind, InclDesc, Scope, Report)
+ ;
+ Cmd = deep_cmd_restart,
+ error("create_report/3", "unexpected restart command")
+ ;
( Cmd = deep_cmd_root(_)
; Cmd = deep_cmd_clique(_)
; Cmd = deep_cmd_proc(_)
@@ -77,8 +77,10 @@
; Cmd = deep_cmd_proc_dynamic(_)
; Cmd = deep_cmd_call_site_static(_)
; Cmd = deep_cmd_call_site_dynamic(_)
- ; Cmd = deep_cmd_raw_clique(_)),
- error("create_report/3", "Command not supported: " ++ string(Cmd)).
+ ; Cmd = deep_cmd_raw_clique(_)
+ ),
+ error("create_report/3", "Command not supported: " ++ string(Cmd))
+ ).
%-----------------------------------------------------------------------------%
%
@@ -115,18 +117,19 @@
;
MaybeTopPSIs = ok(TopPSIs),
Ordering = report_ordering(Limit, CostKind, InclDesc, Scope),
- map(psi_to_row_data(Deep), TopPSIs, RowData),
+ list.map(psi_to_perf_row_data(Deep), TopPSIs, RowData),
Report = report_top_procs(Ordering, RowData)
).
%-----------------------------------------------------------------------------%
- % For a Proc Static Index query the deep data and retrive the data to
- % include in that row of the report.
+ % Lookup the proc_static structure with the given PSI index number
+ % and return performance information about it.
%
-:- pred psi_to_row_data(deep::in, int::in, row_data(report_proc)::out) is det.
+:- pred psi_to_perf_row_data(deep::in, int::in,
+ perf_row_data(report_proc)::out) is det.
-psi_to_row_data(Deep, PSI, RowData) :-
+psi_to_perf_row_data(Deep, PSI, RowData) :-
% Gather global deep profiling information.
ProfileStats = Deep ^ profile_stats,
TicksPerSec = ProfileStats ^ ticks_per_sec,
Index: deep_profiler/display.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/display.m,v
retrieving revision 1.1
diff -u -b -r1.1 display.m
--- deep_profiler/display.m 29 Jul 2008 01:42:59 -0000 1.1
+++ deep_profiler/display.m 2 Aug 2008 01:30:01 -0000
@@ -9,8 +9,8 @@
% File: display.m.
% Author: pbone.
%
-% This module contains a data structure for displaying deep profiler
-% reports. It may be versatile enough for other uses.
+% This module contains a data structure for displaying deep profiler reports.
+% It may be versatile enough for other uses.
%
%-----------------------------------------------------------------------------%
@@ -36,14 +36,14 @@
---> display_message(string)
; display_table(table)
; display_list(
- list_class,
% Class of the list, may be used to display the list.
+ list_class,
- maybe(string),
% An optional title.
+ maybe(string),
- list(display_item)
% Items within the list.
+ list(display_item)
)
; display_command_link(deep_link).
@@ -54,22 +54,22 @@
:- type table
---> table(
- table_class :: table_class,
% Enumeration of what the table stores, this can be used
% for layout hints.
+ table_class :: table_class,
+ % The number of columns in the table. If the number of cells
+ % in any data row is not equal to this number, the table is not
+ % well formed. The number of cells in the header may be smaller
+ % than this value when there are header cells that span
+ % multiple sub-header cells.
table_num_cols :: int,
- % The number of columns in the table. If the number of
- % cells in any data row is not equal to this number the
- % table is not well formed. The number of cells in the
- % header may be smaller than this value when there are
- % header cells that span multiple sub-header cells.
- table_header :: maybe(table_header),
% Header row of table.
+ table_header :: maybe(table_header),
+ % The data in table.
table_rows :: list(table_row)
- % Data in table,
).
:- type table_header
@@ -79,20 +79,20 @@
:- type table_header_cell
---> table_header_cell(
- thc_contents :: table_data,
% The table contents.
+ thc_contents :: table_data,
- thc_class :: table_col_class
% The class may be used by a layout to make decisions
% about how to paint this column.
+ thc_class :: table_col_class
)
; table_header_group(
thg_title :: string,
thg_subtitles :: list(table_data),
- thg_class :: table_col_class
% The class may be used by a layout to make decisions
% about how to paint this column.
+ thg_class :: table_col_class
).
:- type table_row
@@ -132,14 +132,14 @@
; i(int)
; l(deep_link)
; m(
+ % The amount of memory.
memory,
- % The amount of memory
+ % The units to display memory in.
memory_units,
- % The units to display memory in
+ % The number of decimal places to show.
int
- % The number of decimal places to show
)
; p(percent)
; s(string)
@@ -162,17 +162,17 @@
:- type deep_link
---> deep_link(
- cmd,
% The link command.
+ cmd,
- maybe(preferences),
% The preferences for the link command.
+ maybe(preferences),
- string,
% A label for the link.
+ string,
- link_class
% Class of the link may control how it is displayed.
+ link_class
).
:- type link_class
Index: deep_profiler/display_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/display_report.m,v
retrieving revision 1.1
diff -u -b -r1.1 display_report.m
--- deep_profiler/display_report.m 29 Jul 2008 01:42:59 -0000 1.1
+++ deep_profiler/display_report.m 3 Aug 2008 14:13:06 -0000
@@ -21,16 +21,15 @@
:- import_module profile.
:- import_module report.
-% XXX: This include should be removed or replaced. Some datastructes such as
-% preferences are currenty defined in query, the should be moved into a
-% different module so that this module doesn't need to include the whole of
-% query.
+% XXX: This include should be removed or replaced. Some data structures
+% such as preferences are currently defined in query, they should be moved
+% into a different module so that this module doesn't need to include
+% the whole of query.
:- import_module query.
%-----------------------------------------------------------------------------%
-:- pred display_report(deep::in, preferences::in, deep_report::in,
- display::out) is det.
+:- func report_to_display(deep, preferences, deep_report) = display.
%-----------------------------------------------------------------------------%
@@ -48,28 +47,30 @@
%-----------------------------------------------------------------------------%
-display_report(_, _, report_message(Msg), Display) :-
- Display = display(no, [display_message(Msg)]).
-
-display_report(Deep, _, Report, Display) :-
- Report = report_menu(QuantaPerSec, UserQuanta, InstQuanta, NumCallsequs,
- NumCSD, NumCSS, NumPD, NumPS, NumClique),
+report_to_display(Deep, Prefs, Report) = Display :-
+ (
+ Report = report_message(Msg),
+ Display = display(no, [display_message(Msg)])
+ ;
+ Report = report_menu(QuantaPerSec, UserQuanta, InstQuanta,
+ NumCallseqs, NumCSD, NumCSS, NumPD, NumPS, NumClique),
display_report_menu(Deep, QuantaPerSec, UserQuanta, InstQuanta,
- NumCallsequs, NumCSD, NumCSS, NumPD, NumPS, NumClique, Display).
-
-display_report(_, Prefs, report_top_procs(Ordering, TopProcs), Display) :-
- display_report_top_procs(Prefs, Ordering, TopProcs, Display).
+ NumCallseqs, NumCSD, NumCSS, NumPD, NumPS, NumClique, Display)
+ ;
+ Report = report_top_procs(Ordering, TopProcs),
+ display_report_top_procs(Prefs, Ordering, TopProcs, Display)
+ ).
%-----------------------------------------------------------------------------%
%
-% Code to display menu report..
+% Code to display menu report.
%
:- pred display_report_menu(deep::in, int::in, int::in, int::in, int::in,
int::in, int::in, int::in, int::in, int::in, display::out)
is det.
-display_report_menu(Deep, QuantaPerSec, UserQuanta, InstQuanta, NumCallsequs,
+display_report_menu(Deep, QuantaPerSec, UserQuanta, InstQuanta, NumCallseqs,
NumCSD, NumCSS, NumPD, NumPS, NumClique, Display) :-
ShouldDisplayTimes = should_display_times(Deep),
@@ -140,10 +141,10 @@
(deep_cmd_top_procs(threshold_percent(0.1), cost_words, self,
overall) -
"Procedures above 0.1% threshold: words, self."),
- % 2M words is chosen arbitrary because it is 8MB on ia32
(deep_cmd_top_procs(threshold_percent(1.0), cost_words,
self_and_desc, overall) -
"Procedures above 1% threshold: words, self+descendants."),
+ % 2M words is chosen because it is 8MB on ia32.
(deep_cmd_top_procs(threshold_value(float(1024 * 1024 * 2)),
cost_words, self_and_desc, overall) -
"Procedures above 2M words threshold: words, self+descendants.")],
@@ -151,22 +152,24 @@
LinkCmds = LinksExploration ++
LinksTopProcsByLimitTime ++ LinksTopProcsByLimit ++
LinksTopProcsByPercentTime ++ LinksTopProcsByPercent,
- map(make_command_link, LinkCmds, LinksList),
+ list.map(make_command_link, LinkCmds, LinksList),
Links = display_list(list_class_vertical_bullets,
yes("You can start exploring the deep profile at the following" ++
" points."), LinksList),
% Display the table section of the report.
- ProfilingStatistics = [("Quanta per second:" - QuantaPerSec),
+ ProfilingStatistics =
+ [("Quanta per second:" - QuantaPerSec),
("Quanta in user code:" - UserQuanta),
("Quanta in instrumentation:" - InstQuanta),
- ("Call sequence numbers:" - NumCallsequs),
+ ("Call sequence numbers:" - NumCallseqs),
("CallSiteDyanic structures:" - NumCSD),
("ProcDynamic structures:" - NumPD),
("CallSiteStatic structures:" - NumCSS),
("ProcStatic structures:" - NumPS),
("Cliques:" - NumClique)],
- map(make_menu_table_row, ProfilingStatistics, Rows),
+
+ list.map(make_menu_table_row, ProfilingStatistics, Rows),
Table = table(table_class_menu, 2, no, Rows),
% Display the Controls section of the report.
@@ -202,24 +205,20 @@
% Create a display_report structure for a top_procedures report.
%
:- pred display_report_top_procs(preferences::in, report_ordering::in,
- list(row_data(report_proc))::in, display::out) is det.
+ list(perf_row_data(report_proc))::in, display::out) is det.
display_report_top_procs(Prefs, Ordering, TopProcs, Display) :-
Ordering = report_ordering(DisplayLimit, CostKind, InclDesc, Scope),
Desc = cost_criteria_to_description(CostKind, InclDesc, Scope),
Title = "Top procedures " ++ Desc,
- %
- % Build table
- %
+ % Build table.
top_procs_table(Prefs, Ordering, TopProcs, Table),
DisplayTable = display_table(Table),
TableAndLabel = display_list(list_class_vertical_no_bullets,
yes(Title), [DisplayTable]),
- %
- % Build controls at bottom of page
- %
+ % Build controls at bottom of page.
Cmd = deep_cmd_top_procs(DisplayLimit, CostKind, InclDesc, Scope),
sort_controls(Prefs, Ordering, SortControls),
incldesc_and_scope_controls(Prefs, Ordering, InclDescScope),
@@ -288,7 +287,7 @@
).
:- pred top_procs_table(preferences::in, report_ordering::in,
- list(row_data(report_proc))::in, table::out) is det.
+ list(perf_row_data(report_proc))::in, table::out) is det.
top_procs_table(Prefs, Ordering, TopProcs, Table) :-
TableInfo = table_info(table_class_top_procs, ranked, Prefs, Ordering),
@@ -314,24 +313,37 @@
% Produce a table for all these procedures.
%
-:- pred proc_table(table_info::in, list(row_data(report_proc))::in, table::out)
- is det.
+:- pred proc_table(table_info::in, list(perf_row_data(report_proc))::in,
+ table::out) is det.
proc_table(TableInfo, TopProcs, Table) :-
% Later add support for non-ranked tables.
proc_table_header(TableInfo, NumCols, Header),
- map_foldl(proc_table_row(TableInfo), TopProcs, Rows, 1, _),
+ list.map_foldl(proc_table_row(TableInfo), TopProcs, Rows, 1, _),
Table = table(TableInfo ^ table_class, NumCols, yes(Header), Rows).
- % Common column header strings.
- %
+%-----------------------------------------------------------------------------%
+%
+% Common column header strings.
+%
+
:- func percall = table_data.
percall = s("/call").
+
:- func percent_label = table_data.
percent_label = s("%").
+
:- func self = table_data.
self = s("Self").
+:- func time = table_data.
+time = s("Time").
+
+:- func total = table_data.
+total = s("Total").
+
+%-----------------------------------------------------------------------------%
+
:- func make_link(report_ordering, preferences, string, cost_kind,
include_descendants, measurement_scope) = deep_link.
@@ -362,6 +374,8 @@
Ordering = TableInfo ^ table_ordering,
Prefs = TableInfo ^ prefs.
+%-----------------------------------------------------------------------------%
+
:- func self_link(table_info, cost_kind) = table_data.
self_link(TableInfo, CostKind) = Link :-
make_table_link(TableInfo, "Self", CostKind, self, overall) = Link.
@@ -386,17 +400,13 @@
total_time_link(TableInfo) =
make_table_link(TableInfo, "Time", cost_time, self_and_desc, overall).
-
-:- func time = table_data.
-time = s("Time").
-:- func total = table_data.
-total = s("Total").
+%-----------------------------------------------------------------------------%
% Convert row data of procedures from the deep profiler into a table row
- % accoding to the preferences.
+ % according to the preferences.
%
-:- pred proc_table_row(table_info::in,
- row_data(report_proc)::in, table_row::out, int::in, int::out) is det.
+:- pred proc_table_row(table_info::in, perf_row_data(report_proc)::in,
+ table_row::out, int::in, int::out) is det.
proc_table_row(TableInfo, RowData, table_row(Cells), Rank, Rank+1) :-
Ranked = TableInfo ^ table_ranked,
@@ -424,7 +434,8 @@
Fails = RowData ^ fails,
Redos = RowData ^ redos,
Excps = RowData ^ excps,
- PortCells = [table_cell(i(Calls)), table_cell(i(Exits)),
+ PortCells =
+ [table_cell(i(Calls)), table_cell(i(Exits)),
table_cell(i(Fails)), table_cell(i(Redos)),
table_cell(i(Excps))]
;
@@ -465,9 +476,11 @@
TimeCell, TimePercentCell, TimePercallCell]
;
TimeFields = ticks_and_time_and_percall,
- TimeCells = [SelfTicksCell, SelfTimeCell, SelfTimePercentCell,
- SelfTimePercallCell,
- TicksCell, TimeCell, TimePercentCell, TimePercallCell]
+ TimeCells =
+ [SelfTicksCell, SelfTimeCell,
+ SelfTimePercentCell, SelfTimePercallCell,
+ TicksCell, TimeCell,
+ TimePercentCell, TimePercallCell]
)
),
@@ -484,16 +497,19 @@
CallseqsPercentCell = table_cell(p(RowData ^ callseqs_percent)),
(
CallSeqsFields = callseqs,
- CallSeqsCells = [SelfCallseqsCell, SelfCallseqsPercentCell,
+ CallSeqsCells =
+ [SelfCallseqsCell, SelfCallseqsPercentCell,
CallseqsCell, CallseqsPercentCell]
;
CallSeqsFields = callseqs_and_percall,
SelfCallseqsPercallCell =
table_cell(f(RowData ^ self_callseqs_percall)),
CallseqsPercallCell = table_cell(f(RowData ^ callseqs_percall)),
- CallSeqsCells = [SelfCallseqsCell, SelfCallseqsPercentCell,
+ CallSeqsCells =
+ [SelfCallseqsCell, SelfCallseqsPercentCell,
SelfCallseqsPercallCell,
- CallseqsCell, CallseqsPercentCell, CallseqsPercallCell]
+ CallseqsCell, CallseqsPercentCell,
+ CallseqsPercallCell]
)
),
@@ -509,15 +525,16 @@
AllocsPercentCell = table_cell(p(RowData ^ allocs_percent)),
(
AllocFields = alloc,
- AllocCells = [SelfAllocsCell, SelfAllocsPercentCell,
+ AllocCells =
+ [SelfAllocsCell, SelfAllocsPercentCell,
AllocsCell, AllocsPercentCell]
;
AllocFields = alloc_and_percall,
SelfAllocsPercallCell =
table_cell(f(RowData ^ self_allocs_percall)),
AllocsPercallCell = table_cell(f(RowData ^ allocs_percall)),
- AllocCells = [SelfAllocsCell, SelfAllocsPercentCell,
- SelfAllocsPercallCell,
+ AllocCells =
+ [SelfAllocsCell, SelfAllocsPercentCell, SelfAllocsPercallCell,
AllocsCell, AllocsPercentCell, AllocsPercallCell]
)
),
@@ -538,11 +555,13 @@
MemPercentCell = table_cell(p(RowData ^ mem_percent)),
(
MemoryFields = memory(_),
- MemoryCells = [SelfMemCell, SelfMemPercentCell,
+ MemoryCells =
+ [SelfMemCell, SelfMemPercentCell,
MemCell, MemPercentCell]
;
MemoryFields = memory_and_percall(_),
- MemoryCells = [SelfMemCell, SelfMemPercentCell, SelfMemPercallCell,
+ MemoryCells =
+ [SelfMemCell, SelfMemPercentCell, SelfMemPercallCell,
MemCell, MemPercentCell, MemPercallCell]
)
),
@@ -550,7 +569,6 @@
Cells = RankCells ++ cons(ProcCell, PortCells ++ TimeCells ++
CallSeqsCells ++ AllocCells ++ MemoryCells).
-
:- pred proc_to_cell(table_info::in, report_proc::in, table_cell::out) is det.
proc_to_cell(TableInfo, ReportProc, table_cell(Data)) :-
@@ -560,7 +578,6 @@
Cmd = deep_cmd_proc(PSIndex),
Data = l(deep_link(Cmd, yes(Prefs), Name, link_class_link)).
-
% Create the table header cell for the timing fields.
%
:- pred proc_table_time_header(table_info::in, fields::in,
@@ -595,12 +612,14 @@
;
TimeFields = time_and_percall,
Title = "Time",
- SubTitles = [Self, percent_label, SelfPercall,
+ SubTitles =
+ [Self, percent_label, SelfPercall,
Total, percent_label, TotalPercall]
;
TimeFields = ticks_and_time_and_percall,
Title = "Clock ticks and times",
- SubTitles = [Self, Time, percent_label, SelfPercall,
+ SubTitles =
+ [Self, Time, percent_label, SelfPercall,
Total, TotalTime, percent_label, TotalPercall]
),
MaybeHeaderCell = yes(table_header_group(Title, SubTitles,
@@ -645,7 +664,8 @@
Callseqs = callseqs_and_percall,
SelfPercall = self_percall_link(TableInfo, cost_callseqs),
TotalPercall = total_percall_link(TableInfo, cost_callseqs),
- SubTitles = [Self, percent_label, SelfPercall,
+ SubTitles =
+ [Self, percent_label, SelfPercall,
Total, percent_label, TotalPercall]
),
MaybeCallseqsHeader = yes(table_header_group("Call sequence numbers",
@@ -672,7 +692,8 @@
AllocFields = alloc_and_percall,
SelfPercall = self_percall_link(TableInfo, cost_allocs),
TotalPercall = total_percall_link(TableInfo, cost_allocs),
- SubTitles = [Self, percent_label, SelfPercall,
+ SubTitles =
+ [Self, percent_label, SelfPercall,
Total, percent_label, TotalPercall]
),
MaybeHeader = yes(table_header_group("Memory allocations", SubTitles,
@@ -700,7 +721,8 @@
Memory = memory_and_percall(Units),
SelfPercall = self_percall_link(TableInfo, cost_words),
TotalPercall = total_percall_link(TableInfo, cost_words),
- SubTitles = [Self, Percent, SelfPercall,
+ SubTitles =
+ [Self, Percent, SelfPercall,
Total, Percent, TotalPercall]
),
(
@@ -735,8 +757,9 @@
;
Ranked = non_ranked
),
- table_add_header_col(table_header_cell(s("Procedure"),
- table_col_class_proc), !Cols, !NumCols),
+ ProcHeaderCell =
+ table_header_cell(s("Procedure"), table_col_class_proc),
+ table_add_header_col(ProcHeaderCell, !Cols, !NumCols),
proc_table_ports_header(TableInfo, Fields, MaybePortsHeader),
table_maybe_add_header_col(MaybePortsHeader, !Cols, !NumCols),
@@ -836,7 +859,7 @@
deep_cmd_top_procs(DisplayLimit, CostKind, CurrentInclDesc, Scope),
yes(Prefs), ScopeLabel, link_class_control),
- map(link_to_display, [InclDescControl, ScopeControl], Controls),
+ list.map(link_to_display, [InclDescControl, ScopeControl], Controls),
ControlsList = display_list(list_class_horizontal, no, Controls).
% Provide a predicate to be used as a higher order value that wraps the
@@ -1054,8 +1077,8 @@
:- mode make_fields_control(pred(in, in, out) is det, pred(in, out) is det,
in, in, in, out) is det.
-make_fields_control(UpdateFields, MakeLabel, Cmd, Prefs0, NewFields, Control)
- :-
+make_fields_control(UpdateFields, MakeLabel, Cmd, Prefs0, NewFields,
+ Control) :-
Fields0 = Prefs0 ^ pref_fields,
UpdateFields(NewFields, Fields0, Fields),
Prefs = Prefs0 ^ pref_fields := Fields,
@@ -1094,8 +1117,8 @@
%-----------------------------------------------------------------------------%
- % Make a mercury list of display items into a display item representing a
- % horizontal list of these items.
+ % Make a mercury list of display items into a display item representing
+ % a horizontal list of these items.
%
:- pred make_horizontal_list(list(display_item)::in, display_item::out) is det.
Index: deep_profiler/dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/dump.m,v
retrieving revision 1.14
diff -u -b -r1.14 dump.m
--- deep_profiler/dump.m 29 Jul 2008 23:57:59 -0000 1.14
+++ deep_profiler/dump.m 3 Aug 2008 14:14:56 -0000
@@ -38,7 +38,6 @@
do_dump_prop_measurements :: dump_prop_measurements
).
-
% This type is used to describe if a restricted set of "css" and "ps"
% structures should be shown, (those for code that was executed), or if all
% "css" and "ps" structures should be shown.
@@ -47,7 +46,6 @@
---> show_restricted_dump
; show_complete_dump.
-
% This type indicates the arrays in the deep profile data that may be
% printed.
%
@@ -57,14 +55,12 @@
; pd
; ps.
-
% show_stats describes whether to show some statistics and the root node
% in the dump.
%
:- type show_stats
---> show_stats
- ; dont_show_stats.
-
+ ; do_not_show_stats.
% Types to specifiy if cliques, rev (proc static to caller) links and
% propagated measurements should be dumpped by dump_deep/3.
@@ -81,14 +77,12 @@
---> dump_prop_measurements
; do_not_dump_prop_measurements.
-
%-----------------------------------------------------------------------------%
% returns the default dump options.
%
:- func default_dump_options = dump_options.
-
% dump_array_options will take a list of strings for the accumulating
% dump options and produce a set if possible.
%
@@ -100,7 +94,6 @@
:- pred det_dump_array_options(list(string)::in, set(dumpable_array)::out)
is det.
-
% dump_array_options_to_dump_options takes a list of strings of the
% accumulating array dump options and create a dump_options structure
% based on the default plus these spacific array options.
@@ -108,7 +101,6 @@
:- pred dump_array_options_to_dump_options(list(string)::in,
dump_options::out) is det.
-
% dump_initial_deep(InitialDeep, DumpOptions, !IO):
%
% Print selected parts of InitialDeep to standard output. Which parts
@@ -153,7 +145,6 @@
DumpOptions = dump_options(show_complete_dump, all_array_options,
show_stats, dump_cliques, dump_rev_links, dump_prop_measurements).
-
det_dump_array_options(Strings, DumpArrayOptions) :-
(
dump_array_options_special(Strings, DumpArrayOptionsSpecial)
@@ -174,7 +165,6 @@
DumpArrayOptions)
).
-
% Handle special cases in the list of array options.
%
:- pred dump_array_options_special(list(string)::in, set(dumpable_array)::out)
@@ -183,22 +173,18 @@
dump_array_options_special([], all_array_options).
dump_array_options_special(["all"], all_array_options).
-
dump_array_options_to_dump_options(Strings, DumpOptions) :-
det_dump_array_options(Strings, DumpArrayOptions),
DumpOptions = default_dump_options ^ do_arrays := DumpArrayOptions.
-
-
:- pred string_list_to_sym_set(pred(string, X), list(string), set(X)).
:- mode string_list_to_sym_set(pred(in, out) is det, in, out) is det.
:- mode string_list_to_sym_set(pred(in, out) is semidet, in, out) is semidet.
-string_list_to_sym_set(StrToSym, List0, Set) :-
- map(StrToSym, List0, List),
+string_list_to_sym_set(StrToSym, StrList, Set) :-
+ list.map(StrToSym, StrList, List),
list_to_set(List, Set).
-
:- pred det_string_to_dumpable_array(string::in, dumpable_array::out) is det.
det_string_to_dumpable_array(String, Array) :-
@@ -208,7 +194,6 @@
error("Invalid array name in dump options: " ++ String)
).
-
:- pred string_to_dumpable_array(string::in, dumpable_array::out) is semidet.
string_to_dumpable_array("csd", csd).
@@ -216,13 +201,11 @@
string_to_dumpable_array("pd", pd).
string_to_dumpable_array("ps", ps).
-
:- func all_array_options = set(dumpable_array).
all_array_options = Set :-
Set = set.list_to_set([csd, css, pd, ps]).
-
%----------------------------------------------------------------------------%
%
% Dump initial deep profiling structure.
@@ -245,7 +228,7 @@
dump_init_profile_stats(Stats, !IO),
dump_init_root(InitRoot, !IO)
;
- ShowStats = dont_show_stats
+ ShowStats = do_not_show_stats
),
( should_dump(DumpOptions, csd) ->
dump_init_call_site_dynamics(CSDs, !IO)
@@ -586,7 +569,6 @@
CSSPtr = call_site_static_ptr(CSSI),
io.format("\tps_site[%d]: css%d\n", [i(Slot), i(CSSI)], !IO).
-
:- pred dump_coverage_point(int::in, coverage_point::in, io::di, io::uo)
is det.
@@ -596,7 +578,6 @@
io.format("\tcoverage_point[%d]: %s, %s: %d\n",
[i(Num), s(string(Type)), s(PathString), i(Count)], !IO).
-
%----------------------------------------------------------------------------%
:- func dump_proc_id(string_proc_label) = string.
@@ -660,7 +641,6 @@
DumpPropMeasurements = do_not_dump_prop_measurements
).
-
%----------------------------------------------------------------------------%
:- pred dump_deep_cliques(deep::in, io::di, io::uo) is det.
Index: deep_profiler/html_format.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/html_format.m,v
retrieving revision 1.22
diff -u -b -r1.22 html_format.m
--- deep_profiler/html_format.m 29 Jul 2008 01:42:59 -0000 1.22
+++ deep_profiler/html_format.m 3 Aug 2008 14:41:36 -0000
@@ -11,15 +11,12 @@
%
% This module contains code that sets the format of the HTML tables
% we generate for individual queries.
-%
-% This module makes many calls to string.append. In the C backends
-% string.append is linear time over the length of both input strings when
-% called in in, in, out mode. If we build a long string from many short
-% strings the cost will be quadratic. It may be better to build a data
-% structure with cords to describe how strings should be appended and then
-% use calls to string.append_list at a final stage to construct a single
-% string from the cord of strings. There are alternative approaches that
-% should reduce the final cost to linear.
+
+% This module appends many strings. Since string.append takes time that is
+% linear over the length of both input strings, building a long string
+% from many short strings would take quadratic time. This is why we represent
+% HTML as a cord of strings instead. This cord is then converted to a list of
+% strings and then a single list just before being given to the browser.
%
%-----------------------------------------------------------------------------%
@@ -33,18 +30,25 @@
:- import_module display.
:- import_module bool.
+:- import_module cord.
:- import_module list.
:- import_module unit.
%-----------------------------------------------------------------------------%
+:- type html == cord(string).
+
+:- func html_to_string(html) = string.
+
+%-----------------------------------------------------------------------------%
+
% Construct a complete HTML page from the given display structure.
%
- % The first parameter is used to geather extra information from the deep
+ % The first parameter is used to gather extra information from the deep
% profile, for example the name of the Deep.data file to build the URLs
% from.
%
-:- pred htmlize_display(deep::in, display::in, string::out) is det.
+:- func htmlize_display(deep, display) = html.
%-----------------------------------------------------------------------------%
@@ -183,19 +187,42 @@
%-----------------------------------------------------------------------------%
-htmlize_display(Deep, display(MaybeTitle, Content), HTML) :-
- maybe_title_to_title(Deep, MaybeTitle, Title),
+html_to_string(HTML) = Str :-
+ string.append_list(cord.list(HTML), Str).
+
+%-----------------------------------------------------------------------------%
+
+htmlize_display(Deep, display(MaybeSubTitle, Items)) = HTML :-
+ MainTitle = str_to_html("Mercury Deep Profile for ") ++
+ str_to_html(Deep ^ data_file_name),
+ (
+ MaybeSubTitle = no,
+ Title = MainTitle
+ ;
+ MaybeSubTitle = yes(Subtitle),
+ Title = MainTitle ++ str_to_html(" - ") ++ str_to_html(Subtitle)
+ ),
+ TitleHTML = wrap_tags("<title>", "</title>", Title),
deep_to_http_context(Deep, HTTPContext),
- map_join_html("</div><div>", item_to_html(HTTPContext), Content, Body),
- string.format(html_template, [s(Title), s(Body)], HTML).
+ map_join_html(item_to_html("<div>\n", "</div>\n", HTTPContext),
+ Items, ItemsHTML),
+ HTML = doc_type_html ++
+ wrap_tags("<html>", "</html>",
+ wrap_tags("<head>", "</head>", TitleHTML ++ css_style_html) ++
+ wrap_tags("<body>", "</body>", ItemsHTML)
+ ).
+
+:- func doc_type_html = html.
+
+doc_type_html =
+ str_to_html(
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"
+ \"http://www.w3.org/TR/html4/strict.dtd\">").
-:- func html_template = string.
-html_template =
-"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01//EN""
-""http://www.w3.org/TR/html4/strict.dtd"">
-<html>
- <head>
- <title>%s</title>
+:- func css_style_html = html.
+
+css_style_html =
+ str_to_html("
<style type=\"text/css\">
td.allocations
{
@@ -257,74 +284,79 @@
border-style: inset inset inset inset;
}
</style>
- </head>
- <body>
- <div>
- %s
- </div>
- </body>
-</html>".
+").
%-----------------------------------------------------------------------------%
% Convert a display item into a HTML snippet.
%
-:- pred item_to_html(http_context::in, display_item::in, string::out) is det.
-
-item_to_html(_, display_message(Message), HTML) :-
- HTML = "<h3>" ++ Message ++ "</h3>\n".
-
-item_to_html(HTTPContext, display_table(Table), HTML) :-
- table_to_html(HTTPContext, Table, HTML).
+:- func item_to_html(string, string, http_context, display_item) = html.
-item_to_html(HTTPContext, display_list(Class, MaybeTitle, Items), HTML) :-
- some [!HTML]
+item_to_html(StartTag, EndTag, HTTPContext, Item) = HTML :-
(
+ Item = display_message(Message),
+ HTML = wrap_tags(StartTag, EndTag,
+ wrap_tags("<h3>", "</h3>\n", str_to_html(Message)))
+ ;
+ Item = display_command_link(DeepLink),
+ HTML = wrap_tags(StartTag, EndTag,
+ link_to_html(HTTPContext, DeepLink))
+ ;
+ Item = display_table(Table),
+ HTML = wrap_tags(StartTag, EndTag,
+ table_to_html(HTTPContext, Table))
+ ;
+ Item = display_list(Class, MaybeTitle, Items),
(
MaybeTitle = yes(Title),
- !:HTML = "<span id=""list_title"">" ++ Title ++ "</span>",
+ TitleStartTag = "<span id=\"list_title\">",
+ TitleEndTag = "</span>",
+ TitleHTML = wrap_tags(TitleStartTag, TitleEndTag,
+ str_to_html(Title)),
(
- Class = list_class_vertical_bullets
+ Class = list_class_vertical_bullets,
+ PostTitleHTML = empty_html
;
( Class = list_class_horizontal
- ; Class = list_class_vertical_no_bullets ),
- !:HTML = !.HTML ++ "<br>"
+ ; Class = list_class_vertical_no_bullets
+ ),
+ PostTitleHTML = str_to_html("<br>")
)
;
MaybeTitle = no,
- !:HTML = ""
- ),
- (
- Class = list_class_vertical_bullets,
- Delim = "</li>\n<li>",
- !:HTML = !.HTML ++ "<ul><li>"
- ;
- Class = list_class_vertical_no_bullets,
- Delim = "<br>"
- ;
- Class = list_class_horizontal,
- Delim = " "
+ TitleHTML = empty_html,
+ PostTitleHTML = empty_html
),
- map_join_html(Delim, item_to_html(HTTPContext), Items, HTML_Items),
- !:HTML = !.HTML ++ HTML_Items,
(
Class = list_class_vertical_bullets,
- HTML_End = "</li></ul>\n"
+ OutsideStartTag = "<ul>",
+ OutsideEndTag = "<ul>\n",
+ InnerStartTag = "<li>", % XXX add \n?
+ InnerEndTag = "</li>\n",
+ Separator = empty_html
;
Class = list_class_vertical_no_bullets,
- HTML_End = "<br>\n"
+ OutsideStartTag = "",
+ OutsideEndTag = "\n",
+ InnerStartTag = "",
+ InnerEndTag = "", % XXX add \n?
+ Separator = str_to_html("<br>\n")
;
Class = list_class_horizontal,
- HTML_End = "\n"
- ),
- !:HTML = !.HTML ++ HTML_End,
- HTML = !.HTML
+ OutsideStartTag = "",
+ OutsideEndTag = "\n",
+ InnerStartTag = "",
+ InnerEndTag = "",
+ Separator = str_to_html(" ")
+ ),
+ sep_map_join_html(Separator,
+ item_to_html(InnerStartTag, InnerEndTag, HTTPContext), Items,
+ InnerItemsHTML),
+ ItemsHTML = wrap_tags(OutsideStartTag, OutsideEndTag, InnerItemsHTML),
+ HTML = wrap_tags(StartTag, EndTag,
+ TitleHTML ++ PostTitleHTML ++ ItemsHTML)
).
-item_to_html(HTTPContext, display_command_link(DeepLink), HTML) :-
- link_to_html(HTTPContext, DeepLink, HTML).
-
-
%-----------------------------------------------------------------------------%
%
% Table htmlization.
@@ -333,8 +365,8 @@
% The number of rows to be used for a table header.
%
:- type table_header_rows
- ---> one
- ; two.
+ ---> one_header_row
+ ; two_header_rows.
% A mapping of column numbers to classes.
%
@@ -344,99 +376,111 @@
% Create a HTML table entity from the given table description.
%
-:- pred table_to_html(http_context::in, table::in, string::out) is det.
+:- func table_to_html(http_context, table) = html.
-table_to_html(HTTPContext, table(Class, NumCols, MaybeHeader, Rows), HTML) :-
- table_class_to_string(Class, ClassStr),
- Open = "<table class=\"" ++ ClassStr ++ "\">\n",
- Close = "</table>\n",
+table_to_html(HTTPContext, Table) = HTML :-
+ Table = table(Class, NumCols, MaybeHeader, BodyRows),
+
+ ClassStr = table_class_to_string(Class),
+ TableStartTag = "<table class=\"" ++ ClassStr ++ "\">\n",
+ TableEndTag = "</table>\n",
% Build a header row.
(
MaybeHeader = yes(table_header(THCells)),
- foldl3(table_header_num_rows_and_classmap, THCells, one, THNumRows,
- 0, _, map.init, ClassMap),
+ list.foldl3(table_header_num_rows_and_classmap, THCells,
+ one_header_row, THNumRows, 0, _, map.init, ClassMap),
MaybeClassMap = yes(ClassMap),
map_join_html(table_header_cell_to_html_row_1(HTTPContext, THNumRows),
- THCells, HeaderHTML0),
- HeaderHTML1 = "<tr>" ++ HeaderHTML0 ++ "</tr>\n",
+ THCells, InnerHeaderRowOneHTML),
+ HeaderRowOneHTML =
+ wrap_tags("<tr>", "</tr>\n", InnerHeaderRowOneHTML),
(
- THNumRows = one,
- HeaderHTML2 = HeaderHTML1
+ THNumRows = one_header_row,
+ HeaderRowTwoHTML = empty_html
;
- THNumRows = two,
+ THNumRows = two_header_rows,
map_join_html(table_header_cell_to_html_row_2(HTTPContext),
- THCells, HeaderHTML11),
- HeaderHTML2 = HeaderHTML1 ++ "<tr>" ++ HeaderHTML11 ++ "</tr>\n"
- ),
- HeaderHTML = HeaderHTML2 ++
- format("<tr><td colspan=\"%d\"/></tr>\n", [i(NumCols)])
+ THCells, InnerHeaderRowTwoHTML),
+ HeaderRowTwoHTML =
+ wrap_tags("<tr>", "</tr>\n", InnerHeaderRowTwoHTML)
+ ),
+ InnerHeaderRowThree =
+ string.format("<td colspan=\"%d\"/>", [i(NumCols)]),
+ HeaderRowThreeHTML =
+ wrap_tags("<tr>", "</tr>\n", str_to_html(InnerHeaderRowThree)),
+ HeaderHTML = HeaderRowOneHTML ++ HeaderRowTwoHTML ++ HeaderRowThreeHTML
;
MaybeHeader = no,
MaybeClassMap = no,
- HeaderHTML = ""
+ HeaderHTML = empty_html
),
% Build the table rows.
- map_join_html(table_row_to_html(HTTPContext, MaybeClassMap, NumCols), Rows,
- RowsHTML),
+ map_join_html(table_row_to_html(HTTPContext, MaybeClassMap, NumCols),
+ BodyRows, BodyRowsHTML),
% Construct the table.
- HTML = Open ++ HeaderHTML ++ RowsHTML ++ Close.
+ HTML = wrap_tags(TableStartTag, TableEndTag, HeaderHTML ++ BodyRowsHTML).
%-----------------------------------------------------------------------------%
% Return the HTML entity for a table header cell.
%
-:- pred table_header_cell_to_html_row_1(http_context::in,
- table_header_rows::in, table_header_cell::in, string::out) is det.
+:- func table_header_cell_to_html_row_1(http_context,
+ table_header_rows, table_header_cell) = html.
-table_header_cell_to_html_row_1(HTTPContext, HeaderNumRows, Cell, HTML) :-
+table_header_cell_to_html_row_1(HTTPContext, HeaderNumRows, Cell) = HTML :-
(
Cell = table_header_cell(Contents, Class),
(
- HeaderNumRows = one,
+ HeaderNumRows = one_header_row,
RowSpan = "1"
;
- HeaderNumRows = two,
+ HeaderNumRows = two_header_rows,
RowSpan = "2"
),
ColSpan = "1",
- table_data_to_string(HTTPContext, Contents, ContentsString)
+ ContentsHTML = table_data_to_html(HTTPContext, Contents)
;
Cell = table_header_group(Title, SubHeaderCells, Class),
RowSpan = "1",
- length(SubHeaderCells, NumSubHeaderCells),
- ColSpan = string(NumSubHeaderCells),
- ContentsString = Title
+ list.length(SubHeaderCells, NumSubHeaderCells),
+ ColSpan = string.int_to_string(NumSubHeaderCells),
+ ContentsHTML = str_to_html(Title)
),
table_col_class_to_string(Class, ClassStr),
- string.format("<th rowspan=\"%s\" colspan=\"%s\" class=\"%s\">",
- [s(RowSpan), s(ColSpan), s(ClassStr)], Open),
- HTML = Open ++ ContentsString ++ "</th>".
+ StartTag = string.format("<th rowspan=\"%s\" colspan=\"%s\" class=\"%s\">",
+ [s(RowSpan), s(ColSpan), s(ClassStr)]),
+ EndTag = "</th>",
+ HTML = wrap_tags(StartTag, EndTag, ContentsHTML).
%-----------------------------------------------------------------------------%
-:- pred table_header_cell_to_html_row_2(http_context::in,
- table_header_cell::in, string::out) is det.
+:- func table_header_cell_to_html_row_2(http_context, table_header_cell)
+ = html.
-table_header_cell_to_html_row_2(_, table_header_cell(_, _), "").
-
-table_header_cell_to_html_row_2(HTTPContext,
- table_header_group(_, Cells, Class), HTML) :-
- map_join_html((pred(Cell0::in, Cell::out) is det :-
- table_data_to_string(HTTPContext, Cell0, Cell1),
- wrap_in_th_tags(Class, Cell1, Cell)),
- Cells, HTML).
+table_header_cell_to_html_row_2(HTTPContext, HeaderCell) = HTML :-
+ (
+ HeaderCell = table_header_cell(_, _),
+ HTML = empty_html
+ ;
+ HeaderCell = table_header_group(_, Cells, Class),
+ map_join_html(table_data_to_th_html(HTTPContext, Class), Cells, HTML)
+ ).
%-----------------------------------------------------------------------------%
-:- pred wrap_in_th_tags(table_col_class::in, string::in, string::out) is det.
+:- func table_data_to_th_html(http_context, table_col_class, table_data)
+ = html.
-wrap_in_th_tags(Class, In, Out) :-
+table_data_to_th_html(HTTPContext, Class, TableData) = HTML :-
table_col_class_to_string(Class, ClassStr),
- string.format("<th class\"%s\">%s</th>", [s(ClassStr), s(In)], Out).
+ TableDataHTML = table_data_to_html(HTTPContext, TableData),
+ StartTag = string.format("<th class=\"%s\">", [s(ClassStr)]),
+ EndTag = "</th>",
+ HTML = wrap_tags(StartTag, EndTag, TableDataHTML).
%-----------------------------------------------------------------------------%
@@ -457,9 +501,9 @@
;
Cell = table_header_group(_, Subtitles, Class),
length(Subtitles, NumSubCols),
- !:NumRows = two,
+ !:NumRows = two_header_rows,
table_col_class_to_string(Class, ClassStr),
- % fold_up is inclusive of the higher number,
+ % fold_up is inclusive of the higher number.
fold_up(insert_col_classmap(ClassStr),
!.ColNum, !.ColNum + NumSubCols - 1,
!ClassMap)
@@ -478,64 +522,77 @@
% Build a row of a HTML table from the table_row type.
%
-:- pred table_row_to_html(http_context::in, maybe(col_class_map)::in, int::in,
- table_row::in, string::out) is det.
-
-table_row_to_html(HTTPContext, _, NumCols,
- table_section_header(Content), HTML) :-
- table_data_to_string(HTTPContext, Content, Text),
- string.format("<tr><td colspan=\"%d\">%s</td></tr>",
- [i(NumCols), s(Text)], HTML).
+:- func table_row_to_html(http_context, maybe(col_class_map), int, table_row)
+ = html.
-table_row_to_html(HTTPContext, ColClassMap, _, table_row(Cells), HTML) :-
- map_join_html_count(table_cell_to_html(HTTPContext, ColClassMap), 0, Cells,
- "", HTML0),
- HTML = "<tr>" ++ HTML0 ++ "</tr>".
+table_row_to_html(HTTPContext, MaybeColClassMap, NumCols, TableRow) = HTML :-
+ (
+ TableRow = table_section_header(Contents),
+ ContentsHTML = table_data_to_html(HTTPContext, Contents),
+ StartTag = string.format("<tr><td colspan=\"%d\">", [i(NumCols)]),
+ EndTag = "</td></tr>",
+ HTML = wrap_tags(StartTag, EndTag, ContentsHTML)
+ ;
+ TableRow = table_row(Cells),
+ map_join_html_count(table_cell_to_html(HTTPContext, MaybeColClassMap),
+ 0, Cells, InnerHTML),
+ HTML = wrap_tags("<tr>", "</tr>", InnerHTML)
+ ).
%-----------------------------------------------------------------------------%
-:- pred table_cell_to_html(http_context::in, maybe(col_class_map)::in, int::in,
- table_cell::in, string::out) is det.
+:- func table_cell_to_html(http_context, maybe(col_class_map), int, table_cell)
+ = html.
-table_cell_to_html(_, _, _, table_empty_cell, "<td/>").
-
-table_cell_to_html(HTTPContext, MaybeClassMap, ColNum, table_cell(Data), HTML)
- :-
+table_cell_to_html(HTTPContext, MaybeClassMap, ColNum, Cell) = HTML :-
+ (
+ Cell = table_empty_cell,
+ HTML = str_to_html("<td/>")
+ ;
+ Cell = table_cell(CellData),
(
MaybeClassMap = yes(ClassMap),
- ( map.search(ClassMap, ColNum, ClassPrime) ->
- ClassStr = ClassPrime
+ ( map.search(ClassMap, ColNum, ClassStrPrime) ->
+ ClassStr = ClassStrPrime
;
- throw(software_error(string.format(
+ Msg = string.format(
"Class map had no class for col %d, check table structure",
- [i(ColNum)])))
+ [i(ColNum)]),
+ error(Msg)
)
;
MaybeClassMap = no,
- ( table_data_class(Data, ClassP) ->
- Class = ClassP
+ ( table_data_class(CellData, ClassPrime) ->
+ Class = ClassPrime
;
Class = default_table_col_class
),
table_col_class_to_string(Class, ClassStr)
),
- table_data_to_string(HTTPContext, Data, Text),
- string.format("<td class=\"%s\">%s</td>", [s(ClassStr), s(Text)], HTML).
+ CellHTML = table_data_to_html(HTTPContext, CellData),
+ StartTag = string.format("<td class=\"%s\">", [s(ClassStr)]),
+ EndTag = "</td>",
+ HTML = wrap_tags(StartTag, EndTag, CellHTML)
+ ).
%-----------------------------------------------------------------------------%
-:- pred table_data_to_string(http_context::in, table_data::in, string::out)
- is det.
-
-table_data_to_string(_, f(Float), two_decimal_fraction(Float)).
-table_data_to_string(_, i(Int), commas(Int)).
-table_data_to_string(HTTPCtxt, l(Link), HTML) :-
- link_to_html(HTTPCtxt, Link, HTML).
-table_data_to_string(_, m(Mem, Units, Decimals),
- format_memory(Mem, Units, Decimals)).
-table_data_to_string(_, p(Percent), format_percent(Percent)).
-table_data_to_string(_, s(String), escape_break_html_string(String)).
-table_data_to_string(_, t(Time), format_time(Time)).
+:- func table_data_to_html(http_context, table_data) = html.
+
+table_data_to_html(_, f(Float)) =
+ str_to_html(two_decimal_fraction(Float)).
+table_data_to_html(_, i(Int)) =
+ str_to_html(commas(Int)).
+table_data_to_html(HTTPCtxt, l(Link)) =
+ link_to_html(HTTPCtxt, Link).
+table_data_to_html(_, m(Mem, Units, Decimals)) =
+ str_to_html(format_memory(Mem, Units, Decimals)).
+table_data_to_html(_, p(Percent)) =
+ str_to_html(format_percent(Percent)).
+table_data_to_html(_, s(String)) =
+ str_to_html(escape_break_html_string(String)).
+table_data_to_html(_, t(Time)) =
+ str_to_html(format_time(Time)).
% This predicate is used when a table class map couldn't be built from the
% header of the table (perhaps there was no header). It it provides a
@@ -566,24 +623,14 @@
table_col_class_to_string(table_col_class_proc, "proc").
table_col_class_to_string(table_col_class_ticks_and_times, "ticks_and_times").
-:- pred table_class_to_string(table_class::in, string::out) is det.
-
-table_class_to_string(table_class_menu, "menu").
-table_class_to_string(table_class_top_procs, "top_procs").
+:- func table_class_to_string(table_class) = string.
-%-----------------------------------------------------------------------------%
-%
-% Link Related Predicates.
-%
-
-:- pred link_class_to_string(link_class::in, string::out) is det.
-
-link_class_to_string(link_class_link, "default").
-link_class_to_string(link_class_control, "control").
+table_class_to_string(table_class_menu) = "menu".
+table_class_to_string(table_class_top_procs) = "top_procs".
%-----------------------------------------------------------------------------%
- % Information about the HTTP session. This is used to create HTTP links as
+ % Information about the HTTP session. This is used to create HTTP links
% below.
%
:- type http_context
@@ -597,20 +644,21 @@
% Transform a deep link into HTML.
%
-:- pred link_to_html(http_context::in, deep_link::in, string::out) is det.
+:- func link_to_html(http_context, deep_link) = html.
-link_to_html(HTTPContext, deep_link(Cmd, MaybePrefs, Label, Class), HTML) :-
- link_class_to_string(Class, ClassStr),
+link_to_html(HTTPContext, Link) = HTML :-
+ Link = deep_link(Cmd, MaybePrefs, Label, Class),
deep_cmd_to_url(HTTPContext, Cmd, MaybePrefs, URL),
(
Class = link_class_control,
- FormatString = "<a class=""%s"" href=""%s"">[%s]</a>"
+ FormatString = "<a class=\"control\" href=\"%s\">[%s]</a>"
;
Class = link_class_link,
- FormatString = "<a class=""%s"" href=""%s"">%s</a>"
+ FormatString = "<a class=\"link\" href=\"%s\">%s</a>"
),
string.format(FormatString,
- [ s(ClassStr), s(URL), s(escape_break_html_string(Label)) ], HTML).
+ [s(URL), s(escape_break_html_string(Label))], HTMLStr),
+ HTML = str_to_html(HTMLStr).
%-----------------------------------------------------------------------------%
@@ -636,7 +684,7 @@
(
MaybePrefs = no,
string.format("http://%s%s?%s&%s",
- [ s(HostAndPort), s(Script), s(CmdStr), s(DataFile) ], URL)
+ [s(HostAndPort), s(Script), s(CmdStr), s(DataFile)], URL)
;
MaybePrefs = yes(Prefs),
PrefStr = preferences_to_string(Prefs),
@@ -647,78 +695,85 @@
%-----------------------------------------------------------------------------%
%
-% Generic html helper predicates.
+% Generic HTML helper predicates.
%
- % Join two HTML snippits with the given delimiter.
- %
-:- pred html_join(string::in, string::in, string::in, string::out) is det.
+:- func wrap_tags(string, string, html) = html.
+
+wrap_tags(StartTag, EndTag, InnerHTML) =
+ str_to_html(StartTag) ++ InnerHTML ++ str_to_html(EndTag).
+
+:- func empty_html = html.
+
+empty_html = cord.empty.
+
+:- func nl_html = html.
-html_join(Delim, H1, H2, H) :-
- H = string.append_list([H1, Delim, "\n", H2]).
+nl_html = str_to_html("\n").
+
+:- func str_to_html(string) = html.
+
+str_to_html(Str) = cord.singleton(Str).
%-----------------------------------------------------------------------------%
- % This predicate builds the concatentation of Acc and ASs where each AS
- % is MapPred(A, AS), the Delim is placed between concatentated strings.
+ % For each A, compute S = MapFunc(A), and concatenate all Ss.
%
-:- pred map_join_html_acc(string, pred(A, string), list(A), string, string).
-:- mode map_join_html_acc(in, pred(in, out) is det, in, in, out) is det.
+:- pred map_join_html((func(A) = html)::in, list(A)::in, html::out) is det.
-map_join_html_acc(_, _, [], Result, Result).
-map_join_html_acc(Delim, MapPred, [ X | XS ], Acc0, Out) :-
- MapPred(X, Y),
- html_join(Delim, Acc0, Y, Acc),
- map_join_html_acc(Delim, MapPred, XS, Acc, Out).
+map_join_html(MapFunc, List, HTML) :-
+ sep_map_join_html(empty_html, MapFunc, List, HTML).
- % For each A do MapPred(A, S) and return the concatenation of Ss
- % seperated by Delim.
+ % For each A, compute S = MapFunc(A), and concatenate all Ss
+ % after putting Separator between them.
%
-:- pred map_join_html(string, pred(A, string), list(A), string).
-:- mode map_join_html(in, pred(in, out) is det, in, out) is det.
+:- pred sep_map_join_html(html::in, (func(A) = html)::in,
+ list(A)::in, html::out) is det.
-map_join_html(_, _, [], "").
-map_join_html(Delim, MapPred, [ X | XS ], Result) :-
- MapPred(X, Str),
- map_join_html_acc(Delim, MapPred, XS, Str, Result).
+sep_map_join_html(_, _, [], empty_html).
+sep_map_join_html(Separator, MapFunc, [Head | Tail], HTML) :-
+ HeadHTML = MapFunc(Head),
+ sep_map_join_html_acc(Separator, MapFunc, Tail, HeadHTML, HTML).
- % For each A do MapPred(A, S) and concatenate all Ss.
- %
-:- pred map_join_html(pred(A, string), list(A), string).
-:- mode map_join_html(pred(in, out) is det, in, out) is det.
+:- pred sep_map_join_html_acc(html::in, (func(A) = html)::in, list(A)::in,
+ html::in, html::out) is det.
-map_join_html(MapPred, List, Result) :-
- map_join_html("", MapPred, List, Result).
+sep_map_join_html_acc(_, _, [], !HTML).
+sep_map_join_html_acc(Separator, MapFunc, [Head | Tail], !HTML) :-
+ HeadHTML = MapFunc(Head),
+ !:HTML = !.HTML ++ Separator ++ HeadHTML,
+ sep_map_join_html_acc(Separator, MapFunc, Tail, !HTML).
- % This predicate is the same as above except that it passes an integer
- % to the higher order call, the integer is incremented on each
- % recursion.
+ % For each A, compute S = MapFunc(N, A), and concatenate all Ss.
+ % N is the ordinal number of the element in the list.
%
-:- pred map_join_html_count(pred(int, A, string), int, list(A), string,
- string).
-:- mode map_join_html_count(pred(in, in, out) is det, in, in, in, out)
- is det.
-
-map_join_html_count(_, _, [], Result, Result).
-map_join_html_count(MapPred, N, [ X | XS ], Acc0, Out) :-
- MapPred(N, X, Y),
- html_join("", Acc0, Y, Acc),
- map_join_html_count(MapPred, N+1, XS, Acc, Out).
+:- pred map_join_html_count((func(int, A) = html)::in, int::in, list(A)::in,
+ html::out) is det.
-%-----------------------------------------------------------------------------%
+map_join_html_count(MapFunc, N, List, HTML) :-
+ sep_map_join_html_count(empty_html, MapFunc, N, List, HTML).
- % Format a title for the given website. It will be the common title,
- % followed by an optional subtitle seperated by -
+ % For each A, compute S = MapFunc(N, A), and concatenate all Ss
+ % after putting Separator between them.
+ % N is the ordinal number of the element in the list.
%
-:- pred maybe_title_to_title(deep::in, maybe(string)::in, string::out)
- is det.
+:- pred sep_map_join_html_count(html::in, (func(int, A) = html)::in,
+ int::in, list(A)::in, html::out) is det.
+
+sep_map_join_html_count(_, _, _, [], empty_html).
+sep_map_join_html_count(Separator, MapFunc, N, [Head | Tail], HTML) :-
+ HeadHTML = MapFunc(N, Head),
+ sep_map_join_html_count_acc(Separator, MapFunc, N + 1, Tail,
+ HeadHTML, HTML).
-maybe_title_to_title(Deep, yes(Subtitle), Title) :-
- maybe_title_to_title(Deep, no, MainTitle),
- Title = MainTitle ++ " - " ++ Subtitle.
+:- pred sep_map_join_html_count_acc(html::in, (func(int, A) = html)::in,
+ int::in, list(A)::in, html::in, html::out) is det.
-maybe_title_to_title(Deep, no, Title) :-
- Title = "Mercury Deep Profile for " ++ Deep ^ data_file_name.
+sep_map_join_html_count_acc(_, _, _, [], !HTML).
+sep_map_join_html_count_acc(Separator, MapFunc, N, [Head | Tail], !HTML) :-
+ HeadHTML = MapFunc(N, Head),
+ !:HTML = !.HTML ++ Separator ++ HeadHTML,
+ sep_map_join_html_count_acc(Separator, MapFunc, N + 1, Tail, !HTML).
%-----------------------------------------------------------------------------%
%
@@ -1065,7 +1120,8 @@
CallSeqs1Fields = Fields ^ callseqs_fields := no_callseqs,
CallSeqs1Pref = Pref ^ pref_fields := CallSeqs1Fields,
CallSeqs1Msg = "[No call sequence number info]",
- CallSeqs1Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ CallSeqs1Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
[s(deep_cmd_pref_to_url(CallSeqs1Pref, Deep, Cmd)),
s(CallSeqs1Msg)])
),
@@ -1075,7 +1131,8 @@
CallSeqs2Fields = Fields ^ callseqs_fields := callseqs,
CallSeqs2Pref = Pref ^ pref_fields := CallSeqs2Fields,
CallSeqs2Msg = "[Call sequence numbers]",
- CallSeqs2Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ CallSeqs2Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
[s(deep_cmd_pref_to_url(CallSeqs2Pref, Deep, Cmd)),
s(CallSeqs2Msg)])
),
@@ -1085,7 +1142,8 @@
CallSeqs3Fields = Fields ^ callseqs_fields := callseqs_and_percall,
CallSeqs3Pref = Pref ^ pref_fields := CallSeqs3Fields,
CallSeqs3Msg = "[Call sequence numbers including per-call]",
- CallSeqs3Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ CallSeqs3Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
[s(deep_cmd_pref_to_url(CallSeqs3Pref, Deep, Cmd)),
s(CallSeqs3Msg)])
),
@@ -1122,8 +1180,10 @@
Memory1Fields = Fields ^ memory_fields := no_memory,
Memory1Pref = Pref ^ pref_fields := Memory1Fields,
Memory1Msg = "[No memory info]",
- Memory1Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(deep_cmd_pref_to_url(Memory1Pref, Deep, Cmd)), s(Memory1Msg)])
+ Memory1Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(deep_cmd_pref_to_url(Memory1Pref, Deep, Cmd)),
+ s(Memory1Msg)])
),
( Fields ^ memory_fields = memory(units_words) ->
Memory2Toggle = ""
@@ -1131,8 +1191,10 @@
Memory2Fields = Fields ^ memory_fields := memory(units_words),
Memory2Pref = Pref ^ pref_fields := Memory2Fields,
Memory2Msg = "[Words]",
- Memory2Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(deep_cmd_pref_to_url(Memory2Pref, Deep, Cmd)), s(Memory2Msg)])
+ Memory2Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(deep_cmd_pref_to_url(Memory2Pref, Deep, Cmd)),
+ s(Memory2Msg)])
),
( Fields ^ memory_fields = memory(units_bytes) ->
Memory3Toggle = ""
@@ -1140,8 +1202,10 @@
Memory3Fields = Fields ^ memory_fields := memory(units_bytes),
Memory3Pref = Pref ^ pref_fields := Memory3Fields,
Memory3Msg = "[Bytes]",
- Memory3Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(deep_cmd_pref_to_url(Memory3Pref, Deep, Cmd)), s(Memory3Msg)])
+ Memory3Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(deep_cmd_pref_to_url(Memory3Pref, Deep, Cmd)),
+ s(Memory3Msg)])
),
( Fields ^ memory_fields = memory_and_percall(units_words) ->
Memory4Toggle = ""
@@ -1150,8 +1214,10 @@
memory_and_percall(units_words),
Memory4Pref = Pref ^ pref_fields := Memory4Fields,
Memory4Msg = "[Words and per-call words]",
- Memory4Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(deep_cmd_pref_to_url(Memory4Pref, Deep, Cmd)), s(Memory4Msg)])
+ Memory4Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(deep_cmd_pref_to_url(Memory4Pref, Deep, Cmd)),
+ s(Memory4Msg)])
),
( Fields ^ memory_fields = memory_and_percall(units_bytes) ->
Memory5Toggle = ""
@@ -1160,16 +1226,20 @@
memory_and_percall(units_bytes),
Memory5Pref = Pref ^ pref_fields := Memory5Fields,
Memory5Msg = "[Bytes and per-call bytes]",
- Memory5Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(deep_cmd_pref_to_url(Memory5Pref, Deep, Cmd)), s(Memory5Msg)])
+ Memory5Toggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(deep_cmd_pref_to_url(Memory5Pref, Deep, Cmd)),
+ s(Memory5Msg)])
),
( Fields = default_fields(Deep) ->
DefaultToggle = ""
;
DefaultMsg = "[Restore defaults]",
DefaultPref = Pref ^ pref_fields := default_fields(Deep),
- DefaultToggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(deep_cmd_pref_to_url(DefaultPref, Deep, Cmd)), s(DefaultMsg)])
+ DefaultToggle =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(deep_cmd_pref_to_url(DefaultPref, Deep, Cmd)),
+ s(DefaultMsg)])
),
HTML =
"<strong>Toggle fields:</strong>\n" ++
@@ -1481,7 +1551,8 @@
; CostKind = cost_words
),
MsgCallSeqs = "[Sort by call sequence numbers]",
- ToggleCallSeqs = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ ToggleCallSeqs =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
[s(UpdateCriteria(cost_callseqs, InclDesc, Scope)),
s(MsgCallSeqs)])
;
@@ -1496,8 +1567,10 @@
; CostKind = cost_words
),
MsgAllocs = "[Sort by allocations]",
- ToggleAllocs = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
- [s(UpdateCriteria(cost_allocs, InclDesc, Scope)), s(MsgAllocs)])
+ ToggleAllocs =
+ string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+ [s(UpdateCriteria(cost_allocs, InclDesc, Scope)),
+ s(MsgAllocs)])
;
CostKind = cost_allocs,
ToggleAllocs = ""
Index: deep_profiler/interface.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/interface.m,v
retrieving revision 1.20
diff -u -b -r1.20 interface.m
--- deep_profiler/interface.m 18 Apr 2008 05:57:48 -0000 1.20
+++ deep_profiler/interface.m 3 Aug 2008 13:02:52 -0000
@@ -172,124 +172,155 @@
).
send_term(ToPipeName, Debug, Data, !IO) :-
- io.open_output(ToPipeName, Res, !IO),
+ io.open_output(ToPipeName, ToPipeRes, !IO),
(
- Res = ok(ToStream),
+ ToPipeRes = ok(ToStream),
io.write(ToStream, Data, !IO),
io.write_string(ToStream, ".\n", !IO),
io.close_output(ToStream, !IO)
;
- Res = error(_),
- error("send_term: couldn't open pipe")
+ ToPipeRes = error(ToPipeError),
+ io.error_message(ToPipeError, ToPipeErrorMsg),
+ string.format("send_term: couldn't open pipe %s: %s",
+ [s(ToPipeName), s(ToPipeErrorMsg)], ToPipeMsg),
+ error(ToPipeMsg)
),
(
Debug = yes,
- io.open_output("/tmp/.send_term", Res2, !IO),
+ DebugFileName = "/tmp/.send_term",
+ io.open_output(DebugFileName, DebugRes, !IO),
(
- Res2 = ok(DebugStream),
+ DebugRes = ok(DebugStream),
io.write(DebugStream, Data, !IO),
io.write_string(DebugStream, ".\n", !IO),
io.close_output(DebugStream, !IO)
;
- Res2 = error(_),
- error("send_term: couldn't debug")
+ DebugRes = error(DebugError),
+ io.error_message(DebugError, DebugErrorMsg),
+ string.format("send_term: couldn't open debug file %s: %s",
+ [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+ error(DebugMsg)
)
;
Debug = no
).
send_string(ToPipeName, Debug, Data, !IO) :-
- io.open_output(ToPipeName, Res, !IO),
+ io.open_output(ToPipeName, ToPipeRes, !IO),
(
- Res = ok(ToStream),
+ ToPipeRes = ok(ToStream),
io.write_string(ToStream, Data, !IO),
io.close_output(ToStream, !IO)
;
- Res = error(_),
- error("send_string: couldn't open pipe")
+ ToPipeRes = error(ToPipeError),
+ io.error_message(ToPipeError, ToPipeErrorMsg),
+ string.format("send_term: couldn't open pipe %s: %s",
+ [s(ToPipeName), s(ToPipeErrorMsg)], ToPipeMsg),
+ error(ToPipeMsg)
),
(
Debug = yes,
- io.open_output("/tmp/.send_string", Res2, !IO),
+ DebugFileName = "/tmp/.send_string",
+ io.open_output(DebugFileName, DebugRes, !IO),
(
- Res2 = ok(DebugStream),
+ DebugRes = ok(DebugStream),
io.write_string(DebugStream, Data, !IO),
io.close_output(DebugStream, !IO)
;
- Res2 = error(_),
- error("send_string: couldn't debug")
+ DebugRes = error(DebugError),
+ io.error_message(DebugError, DebugErrorMsg),
+ string.format("send_term: couldn't open debug file %s: %s",
+ [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+ error(DebugMsg)
)
;
Debug = no
).
recv_term(FromPipeName, Debug, Resp, !IO) :-
- io.open_input(FromPipeName, Res0, !IO),
+ io.open_input(FromPipeName, FromPipeRes, !IO),
(
- Res0 = ok(FromStream),
- io.read(FromStream, Res1, !IO),
+ FromPipeRes = ok(FromStream),
+ io.read(FromStream, ReadRes, !IO),
(
- Res1 = ok(Resp0),
- Resp = Resp0
+ ReadRes = ok(Resp)
;
- Res1 = eof,
- error("recv_term: read failed")
+ ReadRes = eof,
+ error("recv_term: read failed: premature eof")
;
- Res1 = error(_, _),
- error("recv_term: read failed")
+ ReadRes = error(ReadErrorMsg, ReadErrorLineNumber),
+ string.format("recv_term: read failed at line %d: %s",
+ [i(ReadErrorLineNumber), s(ReadErrorMsg)], ReadMsg),
+ error(ReadMsg)
),
io.close_input(FromStream, !IO),
(
Debug = yes,
- io.open_output("/tmp/.recv_term", Res2, !IO),
+ DebugFileName = "/tmp/.recv_term",
+ io.open_output(DebugFileName, DebugRes, !IO),
(
- Res2 = ok(DebugStream),
- io.write(DebugStream, Res1, !IO),
+ DebugRes = ok(DebugStream),
+ io.write(DebugStream, ReadRes, !IO),
io.write_string(DebugStream, ".\n", !IO),
io.close_output(DebugStream, !IO)
;
- Res2 = error(_),
- error("recv_term: couldn't debug")
+ DebugRes = error(DebugError),
+ io.error_message(DebugError, DebugErrorMsg),
+ string.format("recv_term: couldn't open debug file %s: %s",
+ [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+ error(DebugMsg)
)
;
Debug = no
)
;
- Res0 = error(_),
- error("recv_term: couldn't open pipe")
+ FromPipeRes = error(FromPipeError),
+ io.error_message(FromPipeError, FromPipeErrorMsg),
+ string.format("recv_term: couldn't open pipe %s: %s",
+ [s(FromPipeName), s(FromPipeErrorMsg)], FromPipeMsg),
+ error(FromPipeMsg)
).
recv_string(FromPipeName, Debug, Resp, !IO) :-
- io.open_input(FromPipeName, Res0, !IO),
+ io.open_input(FromPipeName, FromPipeRes, !IO),
(
- Res0 = ok(FromStream),
- io.read_file_as_string(FromStream, Res1, !IO),
+ FromPipeRes = ok(FromStream),
+ io.read_file_as_string(FromStream, ReadRes, !IO),
(
- Res1 = ok(Resp0),
- Resp = Resp0
+ ReadRes = ok(Resp)
;
- Res1 = error(_, _),
- error("recv_string: read failed")
+ ReadRes = error(_, ReadError),
+ io.error_message(ReadError, ReadErrorMsg),
+ string.format("recv_string: read failed: %s",
+ [s(ReadErrorMsg)], ReadMsg),
+ error(ReadMsg)
),
io.close_input(FromStream, !IO),
(
Debug = yes,
- io.open_output("/tmp/.recv_string", Res2, !IO),
+ DebugFileName = "/tmp/.recv_string",
+ io.open_output(DebugFileName, DebugRes, !IO),
(
- Res2 = ok(DebugStream),
- io.write(DebugStream, Res1, !IO),
+ DebugRes = ok(DebugStream),
+ io.write(DebugStream, ReadRes, !IO),
io.write_string(DebugStream, ".\n", !IO),
io.close_output(DebugStream, !IO)
;
- Res2 = error(_),
- error("recv_string: couldn't debug")
+ DebugRes = error(DebugError),
+ io.error_message(DebugError, DebugErrorMsg),
+ string.format("recv_string: couldn't open debug file %s: %s",
+ [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+ error(DebugMsg)
)
;
Debug = no
)
;
- Res0 = error(_),
- error("recv_term: couldn't open pipe")
+ FromPipeRes = error(FromPipeError),
+ io.error_message(FromPipeError, FromPipeErrorMsg),
+ string.format("recv_string: couldn't open pipe %s: %s",
+ [s(FromPipeName), s(FromPipeErrorMsg)], FromPipeMsg),
+ error(FromPipeMsg)
).
%-----------------------------------------------------------------------------%
Index: deep_profiler/mdprof_cgi.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_cgi.m,v
retrieving revision 1.22
diff -u -b -r1.22 mdprof_cgi.m
--- deep_profiler/mdprof_cgi.m 18 Apr 2008 05:57:48 -0000 1.22
+++ deep_profiler/mdprof_cgi.m 3 Aug 2008 14:09:49 -0000
@@ -378,7 +378,7 @@
release_lock(Debug, MutexFile, !IO),
remove_want_file(WantFile, !IO),
io.set_exit_status(1, !IO),
- io.format("error reading data file: %s\n", [s(Error)], !IO)
+ io.format("error reading %s: %s\n", [s(FileName), s(Error)], !IO)
).
% Become the new server. Delete the mutex and want files when we get out
Index: deep_profiler/mdprof_dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_dump.m,v
retrieving revision 1.9
diff -u -b -r1.9 mdprof_dump.m
--- deep_profiler/mdprof_dump.m 5 Mar 2008 05:05:49 -0000 1.9
+++ deep_profiler/mdprof_dump.m 3 Aug 2008 14:16:29 -0000
@@ -102,7 +102,6 @@
% Option processing
%
-
% Process options and the list of arrays to be dumped.
%
:- pred make_dump_options(option_table(option)::in, maybe(dump_options)::out)
@@ -119,15 +118,12 @@
Restrict = show_complete_dump
),
DumpOptions0 = default_dump_options ^ do_restricted := Restrict,
- (
- dump_array_options(ArrayOptionStrs, ArrayOptions)
- ->
+ ( dump_array_options(ArrayOptionStrs, ArrayOptions) ->
MaybeDumpOptions = yes(DumpOptions0 ^ do_arrays := ArrayOptions)
;
MaybeDumpOptions = no
).
-
:- type option
---> help
; dump_options
@@ -190,7 +186,6 @@
"\t-D prop\n" ++
"\t\tDump propagated measurement information.\n".
-
%----------------------------------------------------------------------------%
:- end_module mdprof_dump.
%----------------------------------------------------------------------------%
Index: deep_profiler/mdprof_feedback.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_feedback.m,v
retrieving revision 1.6
diff -u -b -r1.6 mdprof_feedback.m
--- deep_profiler/mdprof_feedback.m 30 Jul 2008 04:32:08 -0000 1.6
+++ deep_profiler/mdprof_feedback.m 3 Aug 2008 14:16:34 -0000
@@ -40,6 +40,7 @@
:- import_module array.
:- import_module bool.
+:- import_module cord.
:- import_module char.
:- import_module getopt.
:- import_module int.
@@ -76,34 +77,37 @@
->
write_help_message(ProgName, !IO)
;
- ProfileProgName \= "",
- Args = [Input, Output],
+ % XXX What was the point of this test?
+ % ProfileProgName \= "",
+ Args = [InputFileName, OutputFileName],
check_options(Options, RequestedFeedbackInfo)
->
lookup_bool_option(Options, verbose, Verbose),
- read_deep_file(Input, Verbose, MaybeDeep, !IO),
+ read_deep_file(InputFileName, Verbose, MaybeDeep, !IO),
(
MaybeDeep = ok(Deep),
- feedback.read_or_create(Output, Feedback0, !IO),
+ feedback.read_or_create(OutputFileName, Feedback0, !IO),
process_deep_to_feedback(RequestedFeedbackInfo,
Deep, Feedback0, Feedback),
- write_feedback_file(Output, ProfileProgName, Feedback,
+ write_feedback_file(OutputFileName, ProfileProgName, Feedback,
WriteResult, !IO),
(
WriteResult = ok
;
( WriteResult = open_error(Error)
- ; WriteResult = write_error(Error) ),
+ ; WriteResult = write_error(Error)
+ ),
io.error_message(Error, ErrorMessage),
- io.format("%s: %s\n", [s(Output), s(ErrorMessage)], !IO),
+ io.format("%s: %s\n",
+ [s(OutputFileName), s(ErrorMessage)], !IO),
io.set_exit_status(1, !IO)
)
;
MaybeDeep = error(Error),
io.stderr_stream(Stderr, !IO),
io.set_exit_status(1, !IO),
- io.format(Stderr, "%s: error reading deep file: %s\n",
- [s(ProgName), s(Error)], !IO)
+ io.format(Stderr, "%s: error reading %s: %s\n",
+ [s(ProgName), s(InputFileName), s(Error)], !IO)
)
;
io.set_exit_status(1, !IO),
@@ -118,37 +122,48 @@
write_help_message(ProgName, !IO)
).
+:- func help_message = string.
+
+help_message =
+"Usage: %s [<options>] <input> <output>
+ <input> must name a deep profiling data file.
+ <output> is the name of the file to be generated by this program.
+
+ You may specify the following general options:
+
+ --help Generate this help message.
+ --version Report the program's version number.
+ --verbose Generate progress messages.
+ --program-name <name>
+ The name of the program that generated the profiling data.
+ This is stored in the feedback file.
+
+ The following options select sets of feedback information useful
+ for particular compiler optimizations.
+
+ --implicit-parallelism
+ Generate information that the compiler can use for automatic
+ parallelization.
+
+ The following options select specific types of feedback information
+ and parameterise them
+
+ --calls-above-threshold-sorted
+ A list of calls whose typical cost (in call sequence counts)
+ is above a given threshold. The next two options allow you
+ to specify the threshold and what 'typical' means.
+ --calls-above-threshold-sorted-threshold <value>
+ Set the threshold to <value>.
+ --calls-above-threshold-sorted-measure mean|median
+ mean: Use mean(call site dynamic cost) as the typical cost.
+ median: Use median(call site dynamic cost) as the typical cost.
+ The default is 'mean'.
+".
+
:- pred write_help_message(string::in, io::di, io::uo) is det.
write_help_message(ProgName, !IO) :-
- Message0 = [
- "Usage: %s --program-name <ProgName> [<options>] <input> <output>",
- " <input> must name a deep profiling data file.",
- " <output> is the file generated by this program.",
- " You may specify the following options:",
- " --help Generate this help message.",
- " --version Report the program's version number.",
- " --verbose Generate progress messages.",
- " --program-name <name>",
- " The name of the program that generated the",
- " profiling data. This is stored in the",
- " feedback file",
- "\nThe following options select sets of feedback information useful",
- "for particular compiler optimizations",
- " --implicit-parallelism",
- "\nThe following options select specific types of feedback",
- "information and parameterise them",
- " --calls-above-threshold-sorted",
- " A list of calls whose typical cost (in call sequence",
- " counts is above a given threshold, the definition of",
- " 'typical' may be specified.",
- " --calls-above-threshold-sorted-threshold <value>",
- " Set the threshold to <value>.",
- " --calls-above-threshold-sorted-measure mean|median",
- " mean : Use mean(call site dynamic cost), this is the",
- " default.",
- " median : Use median(call site dynamic cost)."],
- string.join_list("\n", Message0) ++ "\n" = Message,
+ Message = help_message,
io.format(Message, [s(ProgName)], !IO).
:- pred write_version_message(string::in, io::di, io::uo) is det.
@@ -163,8 +178,8 @@
% Read a deep profiling data file.
%
-:- pred read_deep_file(string::in, bool::in,
- maybe_error(deep)::out, io::di, io::uo) is det.
+:- pred read_deep_file(string::in, bool::in, maybe_error(deep)::out,
+ io::di, io::uo) is det.
read_deep_file(Input, Verbose, MaybeProfile, !IO) :-
server_name_port(Machine, !IO),
@@ -245,7 +260,7 @@
construct_measure("median", stat_median).
% This type defines the set of feedback_types that are to be calculated and
- % put into the feedback info file, They should correspond with the values
+ % put into the feedback info file. They should correspond with the values
% of feedback_type.
%
:- type requested_feedback_info
@@ -260,7 +275,6 @@
threshold :: int
).
-
% Check all the command line options and return a well-typed representation
% of the user's request. Some command line options imply other options,
% those implications are also handled here.
@@ -302,9 +316,7 @@
option_table(option)::in, option_table(option)::out) is det.
option_implies(Option, ImpliedOption, ImpliedValue, !Options) :-
- (
- lookup_bool_option(!.Options, Option, yes)
- ->
+ ( lookup_bool_option(!.Options, Option, yes) ->
svmap.set(ImpliedOption, bool(ImpliedValue), !Options)
;
true
@@ -343,8 +355,9 @@
css_list_above_threshold(Options, Deep, !Feedback) :-
Options = calls_above_threshold_sorted_opts(MeasureType, Threshold),
compute_css_list_above_threshold(0, Deep, Threshold,
- MeasureType, [], CSSList),
- map(css_to_call(Deep), CSSList, Calls),
+ MeasureType, cord.empty, AboveThresholdCSSCord),
+ AboveThresholdCSSs = cord.list(AboveThresholdCSSCord),
+ list.map(css_to_call(Deep), AboveThresholdCSSs, Calls),
FeedbackData = feedback_data_calls_above_threshold_sorted(Threshold,
MeasureType, Calls),
FeedbackType = feedback_type_calls_above_threshold_sorted,
@@ -354,11 +367,10 @@
% exceed the given threshold.
%
:- pred compute_css_list_above_threshold(int::in, deep::in, int::in,
- stat_measure::in, list(call_site_static)::in,
- list(call_site_static)::out) is det.
+ stat_measure::in,
+ cord(call_site_static)::in, cord(call_site_static)::out) is det.
-compute_css_list_above_threshold(Index, Deep, Threshold, Measure,
- !CSSAcc) :-
+compute_css_list_above_threshold(Index, Deep, Threshold, Measure, !CSSCord) :-
array.size(Deep ^ call_site_statics, Size),
( Index = Size ->
true
@@ -387,12 +399,12 @@
),
( Callseqs >= Threshold ->
CSS = array.lookup(Deep ^ call_site_statics, Index),
- list.append(!.CSSAcc, [CSS], !:CSSAcc),
+ !:CSSCord = snoc(!.CSSCord, CSS),
compute_css_list_above_threshold(Index + 1, Deep, Threshold,
- Measure, !CSSAcc)
+ Measure, !CSSCord)
;
compute_css_list_above_threshold(Index + 1, Deep, Threshold,
- Measure, !CSSAcc)
+ Measure, !CSSCord)
)
).
Index: deep_profiler/mdprof_test.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_test.m,v
retrieving revision 1.16
diff -u -b -r1.16 mdprof_test.m
--- deep_profiler/mdprof_test.m 17 Feb 2008 06:48:38 -0000 1.16
+++ deep_profiler/mdprof_test.m 3 Aug 2008 14:26:24 -0000
@@ -130,8 +130,8 @@
;
Res = error(Error),
io.set_exit_status(1, !IO),
- io.format("%s: error reading data file: %s\n",
- [s(ProgName), s(Error)], !IO)
+ io.format("%s: error reading %s: %s\n",
+ [s(ProgName), s(FileName), s(Error)], !IO)
)
;
io.set_exit_status(1, !IO),
@@ -176,8 +176,8 @@
;
Res = error(Error),
io.set_exit_status(1, !IO),
- io.format("%s: error reading data file: %s\n",
- [s(ProgName), s(Error)], !IO)
+ io.format("%s: error reading %s: %s\n",
+ [s(ProgName), s(FileName), s(Error)], !IO)
).
%-----------------------------------------------------------------------------%
Index: deep_profiler/measurement_units.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/measurement_units.m,v
retrieving revision 1.1
diff -u -b -r1.1 measurement_units.m
--- deep_profiler/measurement_units.m 29 Jul 2008 01:43:00 -0000 1.1
+++ deep_profiler/measurement_units.m 2 Aug 2008 01:55:34 -0000
@@ -9,8 +9,8 @@
% File: measurement_units.m.
% Author: pbone.
%
-% This module contains a memory, time and percentage abstract data types and
-% predicates and functions for using them.
+% This module contains abstract data types for representing memory, time
+% and percentages, and predicates and functions for operating on them.
%
%-----------------------------------------------------------------------------%
@@ -26,7 +26,7 @@
% Memory
%
- % Units avalible for measuring memory in.
+ % Units for measuring memory.
%
:- type memory_units
---> units_words
@@ -51,8 +51,9 @@
%-----------------------------------------------------------------------------%
- % Division for memory units. Use of this function may return continous
+ % Division for memory units. Use of this function may return fractions of
% units.
+ %
:- func (memory) / (int) = (memory) is det.
%-----------------------------------------------------------------------------%
@@ -187,18 +188,20 @@
%-----------------------------------------------------------------------------%
-percent(P) = percent_float(P) :-
- ( (P >= 0.0, P =< 1.0) ->
- true
+percent(P) = PF :-
+ (
+ 0.0 =< P,
+ P =< 1.0
+ ->
+ PF = percent_float(P)
;
- throw(software_error(
- "Percentage value out of range 0.0 to 1.0 (inclusive)"))
+ error("Percentage value out of range 0.0 to 1.0 (inclusive)")
).
%-----------------------------------------------------------------------------%
format_percent(percent_float(P)) = String :-
- string.format("%.2f", [f(P*100.0)], String).
+ string.format("%.2f", [f(P * 100.0)], String).
%-----------------------------------------------------------------------------%
%
@@ -234,7 +237,6 @@
:- func pico = float.
pico = 0.000000000001.
-%
% TODO: When there is no resolution beyond 10ms since there is a clock tick
% every 10ms, the decimal points on some of these numbers should not be shown.
% However it's probably useful to show at least 2 decimal points when the value
@@ -242,7 +244,7 @@
%
% TODO: If the display system supports printing the greek letter mu, then it
% should be used rather than the latin letter u.
-%
+
format_time(time_sec(F)) = String :-
( F < nano ->
% Print in ps.
@@ -267,7 +269,7 @@
%
commas(Num) = Str :-
- string.format("%d", [i(Num)], Str0),
+ string.int_to_string(Num, Str0),
add_commas_intstr(Str0, Str).
%-----------------------------------------------------------------------------%
@@ -281,8 +283,8 @@
add_commas_intstr(WholeString0, WholeString),
Representation = WholeString ++ "." ++ FractionString
;
- % If there are no decimal symbols in the number, try to work with it as
- % an integer.
+ % If there are no decimal symbols in the number, try to work with it
+ % as an integer.
SubStrings = [WholeString]
->
add_commas_intstr(WholeString, Representation)
@@ -296,7 +298,7 @@
add_commas_intstr(Str0, Str) :-
string.to_char_list(Str0, Chars0),
- reverse(Chars0, RevChars0),
+ list.reverse(Chars0, RevChars0),
string.from_char_list(reverse(add_commas(RevChars0)), Str).
:- func add_commas(list(char)) = list(char).
Index: deep_profiler/query.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/query.m,v
retrieving revision 1.21
diff -u -b -r1.21 query.m
--- deep_profiler/query.m 29 Jul 2008 01:43:00 -0000 1.21
+++ deep_profiler/query.m 3 Aug 2008 13:57:22 -0000
@@ -61,9 +61,9 @@
; deep_cmd_module(string)
; deep_cmd_top_procs(display_limit, cost_kind, include_descendants,
measurement_scope)
- %
+
% The following commands are for debugging.
- %
+
; deep_cmd_proc_static(int)
; deep_cmd_proc_dynamic(int)
; deep_cmd_call_site_static(int)
@@ -149,7 +149,6 @@
; time_and_percall
; ticks_and_time_and_percall.
-
:- type callseqs_fields
---> no_callseqs
; callseqs
@@ -301,7 +300,7 @@
:- pred exec(cmd::in, preferences::in, deep::in, string::out,
io::di, io::uo) is det.
-exec(Cmd, Prefs, Deep, HTML, !IO) :-
+exec(Cmd, Prefs, Deep, HTMLStr, !IO) :-
( Cmd = deep_cmd_quit
; Cmd = deep_cmd_timeout(_)
; Cmd = deep_cmd_restart
@@ -309,12 +308,12 @@
; Cmd = deep_cmd_top_procs(_, _, _, _)
),
create_report(Cmd, Deep, Report),
- display_report(Deep, Prefs, Report, Display),
- htmlize_display(Deep, Display, HTML).
+ Display = report_to_display(Deep, Prefs, Report),
+ HTML = htmlize_display(Deep, Display),
+ HTMLStr = html_to_string(HTML).
% Old deep profiler cgi code. This should remain supported until all the deep
-% profiler reports have been updated to use the new datastructures.
-%
+% profiler reports have been updated to use the data structures in report.m.
%exec(Cmd, Pref, Deep, HTML, !IO) :-
% Cmd = deep_cmd_menu,
@@ -667,7 +666,7 @@
"Procedures above 1% threshold: words, self+descendants.")
++
"<li>\n" ++
- % 2M words is chosen arbitrary because it is 8MB on ia32
+ % 2M words is chosen because it is 8MB on ia32
menu_item(Deep, Pref,
deep_cmd_top_procs(threshold_value(float(1024 * 1024 * 2)),
cost_words, self_and_desc, overall),
@@ -763,8 +762,7 @@
table_end(Pref) ++
page_footer(Cmd, Pref, Deep).
-:- func generate_proc_page(cmd, proc_static_ptr, preferences, deep)
- = string.
+:- func generate_proc_page(cmd, proc_static_ptr, preferences, deep) = string.
generate_proc_page(Cmd, PSPtr, Pref, Deep) =
page_banner(Cmd, Pref) ++
Index: deep_profiler/read_profile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/read_profile.m,v
retrieving revision 1.23
diff -u -b -r1.23 read_profile.m
--- deep_profiler/read_profile.m 29 Jul 2008 23:58:00 -0000 1.23
+++ deep_profiler/read_profile.m 3 Aug 2008 14:26:43 -0000
@@ -118,26 +118,35 @@
io::di, io::uo) is det.
read_deep_id_string(Res, !IO) :-
- read_n_byte_string(string.length(deep_id_string), Res0, !IO),
+ read_line(string.length(deep_id_string), LineRes, !IO),
(
- Res0 = ok(String),
- ( String = deep_id_string ->
+ LineRes = ok(Line),
+ ( Line = deep_id_string ->
Res = ok(deep_id_string)
+ ; string.prefix(Line, deep_id_prefix) ->
+ Res = error("version number mismatch")
;
Res = error("not a deep profiling data file")
)
;
- Res0 = error(Err),
+ LineRes = error(Err),
Res = error(Err)
).
+ % Return the string identifying a file as a deep profiling data file.
+ % This must the same string as the one written by the function
+ % MR_write_out_deep_id_string in runtime/mercury_deep_profiling.c.
+ %
:- func deep_id_string = string.
-% This must the same string as the one written by MR_write_out_deep_id_string
-% in runtime/mercury_deep_profiling.c.
-
deep_id_string = "Mercury deep profiler data version 5\n".
+ % Return the part of deep_id_string that is version independent.
+ %
+:- func deep_id_prefix = string.
+
+deep_id_prefix = "Mercury deep profiler data version".
+
:- func init_deep(int, int, int, int, int, int, int, int, int, int, int)
= initial_deep.
@@ -426,7 +435,6 @@
),
Res, !IO).
-
:- func raw_proc_id_to_string(string_proc_label) = string.
raw_proc_id_to_string(str_special_proc_label(TypeName, TypeModule, _DefModule,
@@ -945,6 +953,46 @@
%-----------------------------------------------------------------------------%
+:- pred read_line(int::in, maybe_error(string)::out, io::di, io::uo) is det.
+
+read_line(Limit, Res, !IO) :-
+ read_line_acc(Limit, [], Res, !IO).
+
+:- pred read_line_acc(int::in, list(char)::in, maybe_error(string)::out,
+ io::di, io::uo) is det.
+
+read_line_acc(Limit, !.RevChars, Res, !IO) :-
+ ( Limit > 0 ->
+ read_byte(ByteRes, !IO),
+ (
+ ByteRes = ok(Byte),
+ ( char.to_int(Char, Byte) ->
+ % Include the newline in the string.
+ !:RevChars = [Char | !.RevChars],
+ ( Char = '\n' ->
+ list.reverse(!.RevChars, Chars),
+ string.from_char_list(Chars, Str),
+ Res = ok(Str)
+ ;
+ read_line_acc(Limit - 1, !.RevChars, Res, !IO)
+ )
+ ;
+ Res = error("unexpected end of file")
+ )
+ ;
+ ByteRes = eof,
+ Res = error("unexpected end of file")
+ ;
+ ByteRes = error(Err),
+ io.error_message(Err, Msg),
+ Res = error(Msg)
+ )
+ ;
+ list.reverse(!.RevChars, Chars),
+ string.from_char_list(Chars, Str),
+ Res = ok(Str)
+ ).
+
:- pred read_string(maybe_error(string)::out,
io::di, io::uo) is det.
@@ -966,11 +1014,11 @@
io::di, io::uo) is det.
read_n_byte_string(Length, Res, !IO) :-
- read_n_bytes(Length, Res1, !IO),
+ read_n_bytes(Length, NByteRes, !IO),
(
- Res1 = ok(Bytes),
+ NByteRes = ok(Bytes),
(
- map((pred(I::in, C::out) is semidet :- char.to_int(C, I)),
+ list.map((pred(I::in, C::out) is semidet :- char.to_int(C, I)),
Bytes, Chars)
->
string.from_char_list(Chars, Str),
@@ -979,7 +1027,7 @@
Res = error("string contained bad char")
)
;
- Res1 = error(Err),
+ NByteRes = error(Err),
Res = error(Err)
),
trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
@@ -991,14 +1039,13 @@
:- pred read_ptr(ptr_kind::in, maybe_error(int)::out, io::di, io::uo) is det.
read_ptr(_Kind, Res, !IO) :-
- read_num1(0, Res, !IO),
+ read_num(Res, !IO),
trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
io.write_string("ptr ", !IO),
io.write(Res, !IO),
io.write_string("\n", !IO)
).
-
:- pred read_cp_type(maybe_error(cp_type)::out, io::di, io::uo) is det.
read_cp_type(MaybeRes, !IO) :-
@@ -1012,37 +1059,35 @@
MaybeRes = error(Msg)
).
-
:- pred num_to_cp_type(int::in, cp_type::out) is det.
-:- pragma foreign_proc("C", num_to_cp_type(Int::in, CPType::out),
- [will_not_call_mercury, thread_safe, promise_pure], "
-
+:- pragma foreign_proc("C",
+ num_to_cp_type(Int::in, CPType::out),
+ [will_not_call_mercury, thread_safe, promise_pure],
+"
CPType = Int;
-
- ").
-
+").
:- pred read_num(maybe_error(int)::out, io::di, io::uo) is det.
read_num(Res, !IO) :-
- read_num1(0, Res, !IO),
+ read_num_acc(0, Res, !IO),
trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
io.write_string("num ", !IO),
io.write(Res, !IO),
io.write_string("\n", !IO)
).
-:- pred read_num1(int::in, maybe_error(int)::out,
+:- pred read_num_acc(int::in, maybe_error(int)::out,
io::di, io::uo) is det.
-read_num1(Num0, Res, !IO) :-
+read_num_acc(Num0, Res, !IO) :-
read_byte(Res0, !IO),
(
Res0 = ok(Byte),
Num1 = (Num0 << 7) \/ (Byte /\ 0x7F),
( Byte /\ 0x80 \= 0 ->
- read_num1(Num1, Res, !IO)
+ read_num_acc(Num1, Res, !IO)
;
Res = ok(Num1)
)
@@ -1066,12 +1111,12 @@
io::di, io::uo) is det.
read_fixed_size_int(Res, !IO) :-
- read_fixed_size_int1(fixed_size_int_bytes, 0, 0, Res, !IO).
+ read_fixed_size_int_acc(fixed_size_int_bytes, 0, 0, Res, !IO).
-:- pred read_fixed_size_int1(int::in, int::in, int::in, maybe_error(int)::out,
- io::di, io::uo) is det.
+:- pred read_fixed_size_int_acc(int::in, int::in, int::in,
+ maybe_error(int)::out, io::di, io::uo) is det.
-read_fixed_size_int1(BytesLeft, Num0, ShiftBy, Res, !IO) :-
+read_fixed_size_int_acc(BytesLeft, Num0, ShiftBy, Res, !IO) :-
( BytesLeft =< 0 ->
Res = ok(Num0)
;
@@ -1079,7 +1124,7 @@
(
Res0 = ok(Byte),
Num1 = Num0 \/ ( Byte << ShiftBy),
- read_fixed_size_int1(BytesLeft - 1, Num1, ShiftBy + 8, Res, !IO)
+ read_fixed_size_int_acc(BytesLeft - 1, Num1, ShiftBy + 8, Res, !IO)
;
Res0 = error(Err),
Res = error(Err)
@@ -1090,27 +1135,27 @@
io::di, io::uo) is det.
read_n_bytes(N, Res, !IO) :-
- read_n_bytes(N, [], Res0, !IO),
+ read_n_bytes_acc(N, [], Res0, !IO),
(
Res0 = ok(Bytes0),
- reverse(Bytes0, Bytes),
+ list.reverse(Bytes0, Bytes),
Res = ok(Bytes)
;
Res0 = error(Err),
Res = error(Err)
).
-:- pred read_n_bytes(int::in, list(int)::in, maybe_error(list(int))::out,
+:- pred read_n_bytes_acc(int::in, list(int)::in, maybe_error(list(int))::out,
io::di, io::uo) is det.
-read_n_bytes(N, Bytes0, Res, !IO) :-
+read_n_bytes_acc(N, RevBytes0, Res, !IO) :-
( N =< 0 ->
- Res = ok(Bytes0)
+ Res = ok(RevBytes0)
;
read_deep_byte(Res0, !IO),
(
Res0 = ok(Byte),
- read_n_bytes(N - 1, [Byte | Bytes0], Res, !IO)
+ read_n_bytes_acc(N - 1, [Byte | RevBytes0], Res, !IO)
;
Res0 = error(Err),
Res = error(Err)
Index: deep_profiler/report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/report.m,v
retrieving revision 1.1
diff -u -b -r1.1 report.m
--- deep_profiler/report.m 29 Jul 2008 01:43:00 -0000 1.1
+++ deep_profiler/report.m 3 Aug 2008 13:57:13 -0000
@@ -9,11 +9,11 @@
% File: report.m.
% Author: pbone.
%
-% This module defined deep profiling reports. Deep profiling reports are the
-% result of querying a Deep profile, a different query results in a different
-% type of report. They are processed further by display_report.m and
-% html_format.m in order to create HTML output. Other tools may make use of
-% the information in deep profiling reports.
+% This module defines deep profiling reports. Each report is the result of
+% querying a Deep.data file. Different queries result in different types
+% of reports. Reports can be converted into HTML by display_report.m and
+% html_format.m, but some tools may use the data structures constructed here
+% directly.
%
%-----------------------------------------------------------------------------%
@@ -26,7 +26,7 @@
:- import_module measurement_units.
:- import_module profile.
% TODO: The data structures in query should be moved into a different module,
-% then this module may depend on those datastructures but not the rest of
+% then this module may depend on those data structures but not the rest of
% query.
:- import_module query.
@@ -39,7 +39,7 @@
; report_menu(
% Statistics about the deep profiling data. Gives simple
- % information about the size of the program and it's runtime.
+ % information about the size of the program and its runtime.
% These statistics are displayed on the menu of the mdprof_cgi
% program.
@@ -54,31 +54,30 @@
num_clique :: int
)
; report_top_procs(
- % Information about the most expensive procedures. ordering
- % defines what measurements are used to select and order the
- % procedures in this report.
+ % Information about the most expensive procedures. The ordering
+ % field defines what measurements are used to select and order
+ % the procedures in this report.
ordering :: report_ordering,
- top_procs :: list(row_data(report_proc))
+ top_procs :: list(perf_row_data(report_proc))
).
-
-:- type row_data(T)
- ---> row_data(
+:- type perf_row_data(T)
+ ---> perf_row_data(
% The item represented by this data row.
subject :: T,
- % Port counts
+ % Port counts.
calls :: int,
exits :: int,
fails :: int,
redos :: int,
excps :: int,
- % Clock ticks and times, Ticks are 'countable' so int is
- % used. Time is discrete and has units so a time type is
- % used. When percent is NaN because the total time for the
- % program is close to zero the percent type will represent
+ % Clock ticks and times. We always use simple integers to
+ % represent clock ticks, whereas for time, we use more
+ % user-friendly units. When the total time for the program
+ % is close to zero, the percentage may be NaN representing
% 'not_applicable' or 'do not know'.
self_ticks :: int,
self_time :: time,
@@ -90,7 +89,7 @@
time_percent :: percent,
time_percall :: time,
- % Call sequence counts,
+ % Call sequence counts.
self_callseqs :: int,
self_callseqs_percent :: percent,
self_callseqs_percall :: float,
@@ -99,7 +98,7 @@
callseqs_percent :: percent,
callseqs_percall :: float,
- % Memory allocations,
+ % Memory allocations.
self_allocs :: int,
self_allocs_percent :: percent,
self_allocs_percall :: float,
@@ -108,9 +107,10 @@
allocs_percent :: percent,
allocs_percall :: float,
- % Memory used. Since memory has a scale it's stored in a
- % memory type. Memory per call might not be an integer,
- % perhaps a new type should be used here.
+ % Memory used. We try to use the most appropriate units
+ % for representing each given amount of memory.
+ % XXX Memory per call might not be an integer, so we should
+ % make sure that the memory type can represent fractions.
bytes_per_word :: int,
self_mem :: memory,
self_mem_percent :: percent,
@@ -134,9 +134,8 @@
scope :: measurement_scope
).
-
% The representation of a procedure in the report structure, including
- % information about its location in mercury source code.
+ % information about its location in Mercury source code.
%
:- type report_proc
---> report_proc(
Index: deep_profiler/startup.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/startup.m,v
retrieving revision 1.18
diff -u -b -r1.18 startup.m
Index: deep_profiler/timeout.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/timeout.m,v
retrieving revision 1.18
diff -u -b -r1.18 timeout.m
--- deep_profiler/timeout.m 1 Dec 2006 15:03:47 -0000 1.18
+++ deep_profiler/timeout.m 3 Aug 2008 14:34:24 -0000
@@ -23,6 +23,7 @@
% created, but we don't want the parent process after the fork to delete them
% while they are still in use by the child process. This is prevented by the
% boolean flag process_is_detached_server.
+%
%-----------------------------------------------------------------------------%
:- module timeout.
Index: deep_profiler/top_procs.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/top_procs.m,v
retrieving revision 1.13
diff -u -b -r1.13 top_procs.m
--- deep_profiler/top_procs.m 18 Apr 2008 05:57:48 -0000 1.13
+++ deep_profiler/top_procs.m 3 Aug 2008 14:34:50 -0000
@@ -13,6 +13,7 @@
%
% For comparisons on costs, we sort highest first. For comparisons on names and
% contexts, we sort lowest first. This is consistently what users want.
+%
%-----------------------------------------------------------------------------%
:- module top_procs.
Index: deep_profiler/util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/util.m,v
retrieving revision 1.7
diff -u -b -r1.7 util.m
--- deep_profiler/util.m 1 Dec 2006 15:03:47 -0000 1.7
+++ deep_profiler/util.m 3 Aug 2008 14:35:26 -0000
@@ -10,6 +10,7 @@
% Authors: conway, zs.
%
% This module defines utility predicates for the CGI program.
+%
%-----------------------------------------------------------------------------%
:- module util.
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
Index: mdbcomp/feedback.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/feedback.m,v
retrieving revision 1.1
diff -u -b -r1.1 feedback.m
--- mdbcomp/feedback.m 23 Jul 2008 23:20:34 -0000 1.1
+++ mdbcomp/feedback.m 3 Aug 2008 14:56:49 -0000
@@ -37,28 +37,32 @@
%-----------------------------------------------------------------------------%
% This type is used as a key for the data that may be fed back into the
- % compiler. When making changes to this structure be sure to increment the
- % file format version number towards the bottom of this file.
+ % compiler.
+ %
+ % NOTE: When making changes to this structure, be sure to increment
+ % the file format version number towards the bottom of this file.
%
:- type feedback_type
---> feedback_type_calls_above_threshold_sorted.
- % Feedback data of this type represents a list of
- % calli sites sorted in decending order of mean/median
- % call cost where that cost is greater than a given
- % threshold. Mean or median costs are used.
-
+ % Feedback data of this type represents a list of call sites
+ % sorted in descending order of mean or median call cost where
+ % that cost is greater than a given threshold.
%-----------------------------------------------------------------------------%
- % This type stores the data that may be fed back into the compiler. Each
- % constructor here corresponds to a value of the above type. When making
- % changes to this structure or structures in mdbcomp.program_representation
- % be sure to increment the file format version number towards the bottom of
- % this file.
+ % This type stores the data that may be fed back into the compiler.
+ % Each constructor here corresponds to a constructor of the feedback_type
+ % type.
+ %
+ % TODO: We need a mechanism to ensure that the answer for a given query
+ % (a value of type feedback_type) is always the corresponding value
+ % in this type. The right solution would be to represent a query as
+ % a partially instantiated data structure that we later fill in,
+ % but Mercury doesn't yet let us do that.
%
- % TODO: Somehow need to constrain the instantiations of this type so that
- % they are always paired with instantitations of the above type, and
- % hopefuly the compiler can assert this.
+ % NOTE: When making changes to this structure or structures in
+ % mdbcomp.program_representation, be sure to increment the file format
+ % version number towards the bottom of this file.
%
:- type feedback_data
---> feedback_data_calls_above_threshold_sorted(
@@ -98,8 +102,8 @@
% read_feedback_file(Path, FeedbackState, !IO)
%
- % This predicate reads in feedback data from a specified file. It should
- % be called once per compiler invocation.
+ % This predicate reads in feedback data from a specified file.
+ % It should be called once per compiler invocation.
%
:- pred read_feedback_file(string::in,
feedback_read_result(feedback_info)::out, io::di, io::uo) is det.
@@ -113,7 +117,8 @@
; read_error(io.error)
; parse_error(
message :: string,
- line_no :: int)
+ line_no :: int
+ )
; unexpected_eof
; incorrect_version
; incorrect_first_line
@@ -178,9 +183,7 @@
get_feedback_data(Type, MaybeData, Info) :-
Info = feedback_info(Map),
- (
- map.search(Map, Type, Data)
- ->
+ ( map.search(Map, Type, Data) ->
MaybeData = yes(Data)
;
MaybeData = no
@@ -205,10 +208,9 @@
%
IOResStream = ok(Stream),
some [!Result] (
- %
% Read each part of the file and continue reading of this is
% succesful. read_cont takes care of this logic.
- %
+
read_check_line(feedback_first_line, incorrect_first_line, Stream,
unit, !:Result, !IO),
maybe_read(
@@ -226,9 +228,9 @@
ReadResultFeedbackInfo = error(open_error(ErrorCode))
).
- % If the result so far is successful, call the colsure and return it's
+ % If the result so far is successful, call the closure and return its
% result. Otherwise return the accumulated result without calling the
- % colsure.
+ % closure.
%
:- pred maybe_read(pred(A, feedback_read_result(B), io, io),
feedback_read_result(A), feedback_read_result(B), io, io).
@@ -256,7 +258,8 @@
IOResultLine = ok(Line),
(
( Line = TestLine
- ; Line = TestLine ++ "\n")
+ ; Line = TestLine ++ "\n"
+ )
->
Result = ok(unit)
;
@@ -324,7 +327,8 @@
read_error_message_string(File, Error, Message) :-
(
( Error = open_error(Code)
- ; Error = read_error(Code) ),
+ ; Error = read_error(Code)
+ ),
error_message(Code, MessagePart)
;
Error = parse_error(ParseMessage, Line),
@@ -340,7 +344,8 @@
MessagePart = "Incorrect file format"
;
Error = incorrect_program_name,
- MessagePart = "Program name didn't match, is this the right feedback file?"
+ MessagePart =
+ "Program name didn't match, is this the right feedback file?"
),
string.format("%s: %s\n", [s(File), s(MessagePart)], Message).
@@ -363,20 +368,18 @@
io.open_output(Path, OpenRes, !IO),
(
OpenRes = ok(Stream),
- promise_equivalent_solutions [!:IO, ExcpRes]
- try_io(write2(Stream, ProgName, Feedback), ExcpRes, !IO),
+ promise_equivalent_solutions [!:IO, ExcpRes] (
+ try_io(write_feedback_file_2(Stream, ProgName, Feedback),
+ ExcpRes, !IO)
+ ),
(
ExcpRes = succeeded(_),
Res = ok
;
ExcpRes = exception(ExcpUniv),
- %
- % If the exception is not a type we exected then re-throw it.
- %
- (
- univ_to_type(ExcpUniv, Excp)
- ->
+ % If the exception is not of a type we expected, then re-throw it.
+ ( univ_to_type(ExcpUniv, Excp) ->
Res = write_error(Excp)
;
rethrow(ExcpRes)
@@ -387,13 +390,14 @@
Res = open_error(ErrorCode)
).
- % Write out the data. This is called by try IO to catch any exceptions
- % that close_output and other predicates may throw.
+ % Write out the data. This is called by try_io to catch any exceptions
+ % that close_output and the other predicates we call here (e.g. io.write)
+ % may throw.
%
-:- pred write2(output_stream::in, string::in, feedback_info::in, unit::out,
- io::di, io::uo) is det.
+:- pred write_feedback_file_2(output_stream::in, string::in, feedback_info::in,
+ unit::out, io::di, io::uo) is det.
-write2(Stream, ProgName, Feedback, unit, !IO) :-
+write_feedback_file_2(Stream, ProgName, Feedback, unit, !IO) :-
io.write_string(Stream, feedback_first_line, !IO),
io.nl(Stream, !IO),
io.write_string(Stream, feedback_version, !IO),
Index: mdbcomp/prim_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/prim_data.m,v
retrieving revision 1.29
diff -u -b -r1.29 prim_data.m
Index: mdbcomp/trace_counts.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/trace_counts.m,v
retrieving revision 1.22
diff -u -b -r1.22 trace_counts.m
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list