mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 16:31:04 +00:00
Estimated hours taken: 25 Enhance the configuration parameters of the browser. The browser is now sensitive to the type of caller (print, browse, or print *) and can have different settings for each type. E.g., the default line limit per variable can be made shorter for `print *' than for `print'. The browser also allows different settings for each format. The browser also accepts an optional format, which overrides the current setting for the duration of the call. To make use of these features, mdb has a new `set' command that allows the settings to be updated in various ways. The browser version of `set' still works, although it doesn't yet accept the options that the former does. Also, `print' and `browse' can now take options that override the default format. browser/browser_info.m: New module which defines the key browser data structures. The `browser_state' previously used by browse.m has been split into two parts: the transient state (browser_info) and the persistent state (browser_persistent_state). The persistent state is created when the browser is first called, and is saved between calls to the browser, whereas a new transient state is created each time the browser is called, and lasts for the duration of the call. The persistent state contains settings for each possible combination of format and caller type. This module exports C functions that update the persistent state. browser/browse.m: Move the browser_state into the new module. Change the interface so that it allows optional format and caller type input arguments. This allows its behaviour to vary depending on whether the caller is implementing `print', `browse', or `print *'. It also allows the default format to be overridden by options to these commands. General rearrangement of the browser code to avoid code duplication. This addresses the following comment from the module: % XXX: could abstract out the code common to the following preds. along with other similar problems. The code for testing the size of a term and deciding between `io__write' and a depth limited printer has been moved from `print' to `portray_flat'. This allows `print' to be used with formats other than flat. TODO: allow browser commands to take format options; currently only mdb commands can. browser/declarative_user.m: Update this for the changed interfaces. browser/mdb.m: Add the new module. browser/parse.m: Move the definitions of `dir', `setting', and `portray_format' to the interface of the new module. The argument to the `<' command, which sets the depth limit, is no longer optional. The default used to be to use the system default, but now there are multiple system defaults and no way to select which one. browser/*.m: tests/debugger/browse_pretty.inp: tests/debugger/browse_pretty.exp: s/clipx/width/g s/clipy/lines/g The reason for this change is that the names are used in the context of all formats, but only verbose format actually clips the output, so `clipx' and `clipy' are misleading. tests/debugger/browser_test.inp: tests/debugger/browser_test.exp: Test the new features. doc/user_guide.texi: Document the new features. trace/mercury_trace_browse.c: trace/mercury_trace_browse.h: Allow extra arguments for the print and browse functions, to specify the format and the caller type (in the case of print). Export the function MR_trace_set_browser_param, which calls the browser to do the work of mdb's set command. Export the types MR_Browse_Caller_Type and MR_Browse_Format, which mirror two of the types in the new browser module. trace/mercury_trace_external.c: Update for the change to MR_trace_browse_one: pass `browse' as the caller type, and always use the default format. trace/mercury_trace_internal.c: Add functions to parse the format and caller type options. Update the print and browse commands to expect format options. Add the `set' command. Replace MR_trace_print_var and MR_trace_browse_var with one function, MR_trace_browse_internal. This function takes the caller type as an argument, so there is no need for two functions. Remove occurrences of: /* XXX should use MR_mdb_in and MR_mdb_out */ since we already do this. trace/mercury_trace_vars.c: trace/mercury_trace_vars.h: Change the function type MR_Browser so that it also expects a caller type and a format. These arguments are now required by the browser. This means that some of the functions that take an MR_Browser argument needed to be updated to also take a caller and/or format, so they can pass this on to the browser function when it is called.
435 lines
9.4 KiB
Mathematica
435 lines
9.4 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1998-2000 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% file: parse.m:
|
|
% author: aet
|
|
|
|
% This file contains the parser for the term browser command language.
|
|
% If the term browser is called from mdb, it parses the stuff you type
|
|
% at the "browser> " prompt after typing "browse" from the mdb prompt.
|
|
% If it is called from the external debugger, then it parses the stuff
|
|
% contained in a term `external_request(<string to parse>)' send by the
|
|
% external debugger.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% The Command Language
|
|
%
|
|
% commandline:
|
|
% "?" // SICstus help
|
|
% "^" [numlist] // SICstus cd
|
|
% "d" // SICstus display
|
|
% "w" // SICstus write
|
|
% "help"
|
|
% "cd" [path]
|
|
% "pwd"
|
|
% "ls"
|
|
% "display"
|
|
% "write"
|
|
% "set" [varvalue]
|
|
% "quit"
|
|
%
|
|
% varvalue:
|
|
% "depth" num
|
|
% "size" num
|
|
% "clipx" num
|
|
% "clipy" num
|
|
% "format" fmt
|
|
%
|
|
% numlist:
|
|
% num
|
|
% num numlist
|
|
%
|
|
% fmt:
|
|
% "flat"
|
|
% "pretty"
|
|
% "verbose"
|
|
%
|
|
% path:
|
|
% ["/"] [dirs]
|
|
%
|
|
% dirs:
|
|
% dir ["/" dirs]
|
|
%
|
|
% dir:
|
|
% num
|
|
% ".."
|
|
%
|
|
|
|
:- module mdb__parse.
|
|
|
|
:- interface.
|
|
|
|
:- import_module io, string, list.
|
|
:- import_module mdb__browser_info.
|
|
|
|
:- type command
|
|
---> ls(path)
|
|
; ls
|
|
; cd(path)
|
|
; cd
|
|
; pwd
|
|
; help
|
|
; set(setting)
|
|
; set
|
|
; quit
|
|
; print
|
|
; display
|
|
; write
|
|
; unknown
|
|
.
|
|
|
|
:- type path
|
|
---> root_rel(list(dir))
|
|
; dot_rel(list(dir)).
|
|
|
|
|
|
% If the term browser is called from the external debugger, the term browser
|
|
% commands are send through the socket via terms of type external_request.
|
|
:- type external_request
|
|
---> external_request(string).
|
|
|
|
:- pred parse__read_command(string, command, io__state, io__state).
|
|
:- mode parse__read_command(in, out, di, uo) is det.
|
|
|
|
:- pred parse__read_command_external(command, io__state, io__state).
|
|
:- mode parse__read_command_external(out, di, uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- implementation.
|
|
|
|
:- import_module list, char, int, std_util.
|
|
:- import_module mdb__util.
|
|
|
|
|
|
:- type token
|
|
---> (.)
|
|
; (..)
|
|
; (/)
|
|
; (?)
|
|
; (^)
|
|
; (<)
|
|
; num(int)
|
|
; name(string)
|
|
; unknown(char)
|
|
.
|
|
|
|
parse__read_command(Prompt, Comm) -->
|
|
util__trace_get_command(Prompt, Line),
|
|
{ string__to_char_list(Line, Cs) },
|
|
{ lexer(Cs, Tokens) },
|
|
( { parse(Tokens, Comm2) } ->
|
|
{ Comm = Comm2 }
|
|
;
|
|
{ Comm = unknown }
|
|
).
|
|
|
|
parse__read_command_external(Comm) -->
|
|
io__read(Result),
|
|
(
|
|
{ Result = ok(external_request(StringToParse)) }
|
|
->
|
|
{ string__to_char_list(StringToParse, Cs) },
|
|
{ lexer(Cs, Tokens) },
|
|
( { parse(Tokens, Comm2) } ->
|
|
{ Comm = Comm2 }
|
|
;
|
|
{ Comm = unknown }
|
|
)
|
|
; { Result = eof } ->
|
|
{ Comm = quit }
|
|
;
|
|
{ Comm = unknown }
|
|
).
|
|
|
|
:- pred lexer(list(char), list(token)).
|
|
:- mode lexer(in, out) is det.
|
|
lexer([], []).
|
|
lexer([C | Cs], Toks) :-
|
|
( C = ('.') ->
|
|
lexer_dots(Cs, Toks)
|
|
; C = ('/') ->
|
|
Toks = [(/) | Toks2],
|
|
lexer(Cs, Toks2)
|
|
; C = ('?') ->
|
|
Toks = [(?) | Toks2],
|
|
lexer(Cs, Toks2)
|
|
; C = ('^') ->
|
|
Toks = [(^) | Toks2],
|
|
lexer(Cs, Toks2)
|
|
; C = ('<') ->
|
|
Toks = [(<) | Toks2],
|
|
lexer(Cs, Toks2)
|
|
; char__is_digit(C) ->
|
|
dig_to_int(C, N),
|
|
lexer_num(N, Cs, Toks)
|
|
; char__is_alpha(C) ->
|
|
lexer_name(C, Cs, Toks)
|
|
; char__is_whitespace(C) ->
|
|
lexer(Cs, Toks)
|
|
;
|
|
Toks = [unknown(C) | Toks2],
|
|
lexer(Cs, Toks2)
|
|
).
|
|
|
|
:- pred lexer_dots(list(char), list(token)).
|
|
:- mode lexer_dots(in, out) is det.
|
|
lexer_dots([], []).
|
|
lexer_dots([C | Cs], Toks) :-
|
|
( C = ('.') ->
|
|
Tok = (..),
|
|
lexer(Cs, Toks2),
|
|
Toks = [Tok | Toks2]
|
|
;
|
|
Tok = (.),
|
|
lexer([C | Cs], Toks2),
|
|
Toks = [Tok | Toks2]
|
|
).
|
|
|
|
:- pred dig_to_int(char, int).
|
|
:- mode dig_to_int(in, out) is det.
|
|
dig_to_int(C, N) :-
|
|
char__to_int('0', Zero),
|
|
char__to_int(C, CN),
|
|
N is CN - Zero.
|
|
|
|
:- pred lexer_num(int, list(char), list(token)).
|
|
:- mode lexer_num(in, in, out) is det.
|
|
lexer_num(N, Cs, Toks) :-
|
|
list__takewhile(char__is_digit, Cs, Digits, Rest),
|
|
digits_to_int_acc(N, Digits, Num),
|
|
Toks = [num(Num) | Toks2],
|
|
lexer(Rest, Toks2).
|
|
|
|
|
|
:- pred digits_to_int_acc(int, list(char), int).
|
|
:- mode digits_to_int_acc(in, in, out) is det.
|
|
digits_to_int_acc(Acc, [], Acc).
|
|
digits_to_int_acc(Acc, [C | Cs], Num) :-
|
|
dig_to_int(C, D),
|
|
Acc2 is 10 * Acc + D,
|
|
digits_to_int_acc(Acc2, Cs, Num).
|
|
|
|
|
|
:- pred lexer_name(char, list(char), list(token)).
|
|
:- mode lexer_name(in, in, out) is det.
|
|
lexer_name(C, Cs, Toks) :-
|
|
list__takewhile(char__is_alpha, Cs, Letters, Rest),
|
|
string__from_char_list([C | Letters], Name),
|
|
lexer(Rest, Toks2),
|
|
Toks = [name(Name) | Toks2].
|
|
|
|
|
|
:- pred parse(list(token), command).
|
|
:- mode parse(in, out) is semidet.
|
|
parse(Toks, Comm) :-
|
|
start(Toks, Comm).
|
|
|
|
:- pred start(list(token), command).
|
|
:- mode start(in, out) is semidet.
|
|
start([Tok | Toks], Comm) :-
|
|
( (Tok = name("help") ; Tok = (?) ; Tok = name("h")) ->
|
|
Toks = [],
|
|
Comm = help
|
|
; (Tok = name("cd") ; Tok = (^)) ->
|
|
( Toks = [] ->
|
|
Comm = cd
|
|
;
|
|
parse_path(Toks, Path),
|
|
Comm = cd(Path)
|
|
)
|
|
; Tok = name("pwd") ->
|
|
Toks = [],
|
|
Comm = pwd
|
|
; Tok = name("ls") ->
|
|
( Toks = [] ->
|
|
Comm = ls
|
|
;
|
|
parse_path(Toks, Path),
|
|
Comm = ls(Path)
|
|
)
|
|
; Tok = name("set") ->
|
|
( Toks = [] ->
|
|
Comm = set
|
|
;
|
|
parse_setting(Toks, Setting),
|
|
Comm = set(Setting)
|
|
)
|
|
; Tok = name("quit") ->
|
|
Toks = [],
|
|
Comm = quit
|
|
; (Tok = name("display") ; Tok = name("d")) ->
|
|
Toks = [],
|
|
Comm = display
|
|
; (Tok = name("write") ; Tok = name("w")) ->
|
|
Toks = [],
|
|
Comm = write
|
|
; (Tok = name("print") ; Tok = name("p")) ->
|
|
Toks = [],
|
|
Comm = print
|
|
;
|
|
Tok = (<),
|
|
Toks = [num(Depth)],
|
|
Comm = set(depth(Depth))
|
|
).
|
|
|
|
:- pred parse_path(list(token), path).
|
|
:- mode parse_path(in, out) is semidet.
|
|
% SICStus is forgiving in the syntax of paths, hence so are we.
|
|
% XXX: Be less forgiving?
|
|
parse_path([Tok | Toks], Path) :-
|
|
( Tok = (/) ->
|
|
Path = root_rel(Dirs),
|
|
parse_dirs(Toks, Dirs)
|
|
;
|
|
Path = dot_rel(Dirs),
|
|
parse_dirs([Tok | Toks], Dirs)
|
|
).
|
|
|
|
:- pred parse_dirs(list(token), list(dir)).
|
|
:- mode parse_dirs(in, out) is semidet.
|
|
parse_dirs([], []).
|
|
parse_dirs([Tok | Toks], Dirs) :-
|
|
(
|
|
Tok = num(Subdir),
|
|
Dirs = [child(Subdir) | RestDirs],
|
|
parse_dirs(Toks, RestDirs)
|
|
;
|
|
Tok = (..),
|
|
Dirs = [parent | RestDirs],
|
|
parse_dirs(Toks, RestDirs)
|
|
;
|
|
% We can effectively ignore slashes (for Unix-style
|
|
% pathnames) and carets (for SICStus-style pathnames),
|
|
% but anything else is not allowed.
|
|
Tok = (/),
|
|
parse_dirs(Toks, Dirs)
|
|
;
|
|
Tok = (^),
|
|
parse_dirs(Toks, Dirs)
|
|
).
|
|
|
|
:- pred parse_setting(list(token), setting).
|
|
:- mode parse_setting(in, out) is semidet.
|
|
parse_setting([Tok | Toks], Setting) :-
|
|
( Tok = name("depth") ->
|
|
Toks = [num(Depth)],
|
|
Setting = depth(Depth)
|
|
; Tok = name("size") ->
|
|
Toks = [num(Size)],
|
|
Setting = size(Size)
|
|
; Tok = name("width") ->
|
|
Toks = [num(X)],
|
|
Setting = width(X)
|
|
; Tok = name("lines") ->
|
|
Toks = [num(Y)],
|
|
Setting = lines(Y)
|
|
; Tok = name("format") ->
|
|
Toks = [Fmt],
|
|
( Fmt = name("flat") ->
|
|
Setting = format(flat)
|
|
; Fmt = name("pretty") ->
|
|
Setting = format(pretty)
|
|
;
|
|
Fmt = name("verbose"),
|
|
Setting = format(verbose)
|
|
)
|
|
;
|
|
fail
|
|
).
|
|
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred show_command(command, io__state, io__state).
|
|
:- mode show_command(in, di, uo) is det.
|
|
show_command(ls(Path)) -->
|
|
io__write_string("ls "),
|
|
show_path(Path),
|
|
io__nl.
|
|
show_command(ls) -->
|
|
io__write_string("ls\n").
|
|
show_command(cd(Path)) -->
|
|
io__write_string("cd "),
|
|
show_path(Path),
|
|
io__nl.
|
|
show_command(cd) -->
|
|
io__write_string("cd\n").
|
|
show_command(pwd) -->
|
|
io__write_string("pwd\n").
|
|
show_command(help) -->
|
|
io__write_string("help\n").
|
|
show_command(set(Setting)) -->
|
|
io__write_string("set "),
|
|
show_setting(Setting),
|
|
io__nl.
|
|
show_command(set) -->
|
|
io__write_string("set\n").
|
|
show_command(quit) -->
|
|
io__write_string("quit\n").
|
|
show_command(print) -->
|
|
io__write_string("print\n").
|
|
show_command(display) -->
|
|
io__write_string("display\n").
|
|
show_command(write) -->
|
|
io__write_string("write\n").
|
|
show_command(unknown) -->
|
|
io__write_string("unknown\n").
|
|
|
|
:- pred show_path(path, io__state, io__state).
|
|
:- mode show_path(in, di, uo) is det.
|
|
show_path(root_rel(Dirs)) -->
|
|
io__write_string("/"),
|
|
show_dirs(Dirs).
|
|
show_path(dot_rel(Dirs)) -->
|
|
show_dirs(Dirs).
|
|
|
|
:- pred show_dirs(list(dir), io__state, io__state).
|
|
:- mode show_dirs(in, di, uo) is det.
|
|
show_dirs([]) -->
|
|
io__nl.
|
|
show_dirs([child(Num) | Dirs]) -->
|
|
io__write_int(Num),
|
|
io__write_string("/"),
|
|
show_dirs(Dirs).
|
|
show_dirs([parent | Dirs]) -->
|
|
io__write_string("../"),
|
|
show_dirs(Dirs).
|
|
|
|
:- pred show_setting(setting, io__state, io__state).
|
|
:- mode show_setting(in, di, uo) is det.
|
|
show_setting(depth(Depth)) -->
|
|
io__write_string("depth "),
|
|
io__write_int(Depth),
|
|
io__nl.
|
|
show_setting(size(Size)) -->
|
|
io__write_string("size "),
|
|
io__write_int(Size),
|
|
io__nl.
|
|
show_setting(width(X)) -->
|
|
io__write_string("width "),
|
|
io__write_int(X),
|
|
io__nl.
|
|
show_setting(lines(Y)) -->
|
|
io__write_string("lines "),
|
|
io__write_int(Y),
|
|
io__nl.
|
|
show_setting(format(Fmt)) -->
|
|
io__write_string("format "),
|
|
show_format(Fmt),
|
|
io__nl.
|
|
|
|
:- pred show_format(portray_format, io__state, io__state).
|
|
:- mode show_format(in, di, uo) is det.
|
|
show_format(flat) -->
|
|
io__write_string("flat").
|
|
show_format(pretty) -->
|
|
io__write_string("pretty").
|
|
show_format(verbose) -->
|
|
io__write_string("verbose").
|
|
|
|
%---------------------------------------------------------------------------%
|