mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 23:35:25 +00:00
Estimated hours taken: 26
Implement the following improvements:
- Pass mdb variable bindings to the interactive query processor,
allowing queries to make use of live values.
- Catch exceptions thrown by queries, rather than crashing mdb.
- Write outputs using io.write_cc/3.
- Don't output underscore variables, avoiding spurious warnings.
- More protection of the user's namespace.
- Updated the cleanup code.
browser/interactive_query.m:
The interface now accepts corresponding lists of names and values,
which are matched up with variables occurring in the queries.
Replace the code generator with one that supports passing data
to and from the query, and catching exceptions from the query.
Pass the appropriate data at the time the query predicate is called.
Distinguish between failure of the query and failure of the dynamic
casts used to instantiate the query inputs.
Use module qualifiers to avoid clashing with user imports. (Should the
generated code use use_module, just in case?)
Perform I/O, failure handling and exception handling in the caller
instead of in the generated code. This is faster, more maintainable,
and means that errors are caught earlier.
Place source_file and line directives more carefully so as to ensure
more consistent error messages, and to help distinguish errors in the
template from errors in the query.
Factor out the query command parser to avoid double maintenance.
browser/debugger_interface.m:
Conform to above changes.
trace/mercury_trace_vars.[ch]:
Export MR_trace_return_bindings, which constructs Mercury lists
of the variable names and values in the current environment.
trace/mercury_trace_browse.c:
Pass bindings from trace/mercury_trace_vars through to the interactive
query processor.
tests/debugger/interactive.{m,inp,exp}:
Update for changes to existing functionality. Additionally test the
new functionality.
doc/user_guide.texi:
Document the new behaviour.
NEWS:
Announce the new behaviour.
376 lines
14 KiB
C
376 lines
14 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1999-2008, 2011 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.
|
|
*/
|
|
|
|
/*
|
|
** This module looks after the debugger's information about the variables
|
|
** that are live at a given program point.
|
|
**
|
|
** When execution arrives at an event, the debugger should call the function
|
|
** MR_trace_init_point_vars to initialize this module's data structures
|
|
** to reflect the variables that are live at that event. During the processing
|
|
** of the various debugger commands while at that event, the debugger may
|
|
** call MR_trace_set_level or its MR_trace_set_level_from_layout variant
|
|
** zero or more times to change this module's notion of the "current" set
|
|
** of variables to refer instead to the variables that are live at the
|
|
** return address in a given ancestor. This module maintains its own record
|
|
** of what the current ancestor level is; the enquiry function
|
|
** MR_trace_current_level returns this information, while enquiry function
|
|
** MR_trace_current_level_details returns information about this level.
|
|
** Ancestor level 0 means the environment of the procedure call that generated
|
|
** the event.
|
|
**
|
|
** The debugger partitions the variables at a program point into three sets
|
|
** based on their type: those which are always printed, those which are always
|
|
** ignored (saved succips, void variables etc), and those which are optionally
|
|
** printed (typeinfos and typeclassinfos). The print_optionals argument of
|
|
** the following functions should be MR_TRUE iff you wish to print variables
|
|
** in the third set.
|
|
**
|
|
** The functions MR_trace_var_count, MR_trace_list_vars,
|
|
** MR_trace_return_var_info, MR_trace_headvar_num, MR_trace_parse_var_path,
|
|
** MR_trace_parse_browse_one, MR_trace_browse_one and MR_trace_browse_all
|
|
** all work in the context established by MR_trace_init_point_vars and
|
|
** possibly MR_trace_set_level.
|
|
**
|
|
** This context may say that there is no information available about
|
|
** the variables live at the current location (this is possible if the
|
|
** relevant module was not compiled with the right debugging flags).
|
|
** If this is the case, or if some other reason prevents these functions
|
|
** from carrying out their assigned tasks, most of these functions return
|
|
** a non-NULL string describing the problem; they return NULL if everything
|
|
** went OK. (MR_trace_set_level also returns a pointer to an error message
|
|
** -and refuses to change levels- if something goes wrong.)
|
|
*/
|
|
|
|
#ifndef MERCURY_TRACE_VARS_H
|
|
#define MERCURY_TRACE_VARS_H
|
|
|
|
#include "mercury_types.h" /* for MR_Word etc */
|
|
#include "mercury_stack_layout.h" /* for MR_LabelLayout etc */
|
|
#include "mercury_type_info.h" /* for MR_TypeInfo */
|
|
#include "mercury_trace_base.h" /* for MR_TracePort */
|
|
#include "mercury_trace_browse.h" /* for MR_Browser */
|
|
#include "mercury_trace_completion.h" /* for MR_CompleterList */
|
|
#include <stdio.h>
|
|
|
|
typedef void (*MR_Browser)(MR_Word type_info, MR_Word value,
|
|
MR_BrowseCallerType caller, MR_BrowseFormat format);
|
|
|
|
typedef void (*MR_GoalBrowser)(MR_ConstString name, MR_Word arg_list,
|
|
MR_Word is_func, MR_BrowseCallerType caller,
|
|
MR_BrowseFormat format);
|
|
|
|
typedef enum {
|
|
MR_VAR_SPEC_NUMBER,
|
|
MR_VAR_SPEC_NAME,
|
|
MR_VAR_SPEC_HELD_NAME,
|
|
MR_VAR_SPEC_ATTRIBUTE
|
|
} MR_VarSpecKind;
|
|
|
|
typedef struct {
|
|
MR_VarSpecKind MR_var_spec_kind;
|
|
MR_Unsigned MR_var_spec_number; /* valid if NUMBER */
|
|
const char *MR_var_spec_name; /* valid if NAME, HELD_NAME */
|
|
/* or ATTRIBUTE */
|
|
} MR_VarSpec;
|
|
|
|
/*
|
|
** This function converts a variable name or variable number to MR_VarSpec
|
|
** format.
|
|
*/
|
|
|
|
extern void MR_convert_arg_to_var_spec(const char *word_spec,
|
|
MR_VarSpec *var_spec);
|
|
|
|
/*
|
|
** Print the given MR_VarSpec.
|
|
*/
|
|
|
|
extern void MR_print_var_spec(FILE *fp, MR_VarSpec *var_spec);
|
|
|
|
/*
|
|
** These functions are documented near the top of this file.
|
|
*/
|
|
|
|
extern void MR_trace_init_point_vars(const MR_LabelLayout *top_layout,
|
|
MR_Word *saved_regs, MR_Float *saved_f_regs,
|
|
MR_TracePort port, MR_bool print_optionals);
|
|
extern const char *MR_trace_set_level(int ancestor_level,
|
|
MR_bool print_optionals);
|
|
extern const char *MR_trace_set_level_from_layout(
|
|
const MR_LabelLayout *level_layout,
|
|
MR_Word *base_sp, MR_Word *base_curfr,
|
|
int ancestor_level, MR_bool print_optionals);
|
|
extern int MR_trace_current_level(void);
|
|
extern void MR_trace_current_level_details(
|
|
const MR_ProcLayout **entry_ptr,
|
|
const char **filename_ptr, int *linenumber_ptr,
|
|
MR_Word **base_sp_ptr, MR_Word **base_curfr_ptr);
|
|
|
|
/*
|
|
** Return the number of live variables at the current point. If the required
|
|
** information is missing, return a negative number.
|
|
*/
|
|
|
|
extern int MR_trace_var_count(void);
|
|
|
|
/*
|
|
** Print the list of the names of variables live at the current point
|
|
** on the given file.
|
|
*/
|
|
|
|
extern const char *MR_trace_list_vars(FILE *out);
|
|
|
|
/*
|
|
** Print all the information this module has on the variables live
|
|
** at the current point on the given file. Intended only for debugging
|
|
** the debugger itself.
|
|
*/
|
|
|
|
extern const char *MR_trace_list_var_details(FILE *out);
|
|
|
|
/*
|
|
** Return as a side effect the name, type and value of the variable with the
|
|
** specified HLDS number, in the specified locations, all of which must be
|
|
** non-NULL. If the variable isn't live or isn't known, return a non-null
|
|
** string giving the problem.
|
|
*/
|
|
|
|
extern const char *MR_trace_return_hlds_var_info(int hlds_num,
|
|
MR_TypeInfo *type_info_ptr, MR_Word *value_ptr);
|
|
|
|
/*
|
|
** Return as a side effect the name, type and value of the specified
|
|
** variable in the specified locations, except those which are NULL.
|
|
** Variable number n must be in the range 1..MR_trace_var_count().
|
|
*/
|
|
|
|
extern const char *MR_trace_return_var_info(int n, const char **name_ptr,
|
|
MR_TypeInfo *type_info_ptr, MR_Word *value_ptr);
|
|
|
|
/*
|
|
** If the variable specified by n is a head variable, then store
|
|
** its argument position in *num and return NULL, otherwise return an error.
|
|
*/
|
|
|
|
extern const char *MR_trace_headvar_num(int n, int *num);
|
|
|
|
/*
|
|
** Print the call of the current level as a goal.
|
|
**
|
|
** The goal is printed to the given file if the file pointer is non-NULL.
|
|
** The goal is printed by giving it to the specified browser.
|
|
**
|
|
** XXX Actually, the "out" parameter is currently ignored.
|
|
*/
|
|
|
|
extern const char *MR_trace_browse_one_goal(FILE *out,
|
|
MR_GoalBrowser browser, MR_BrowseCallerType caller,
|
|
MR_BrowseFormat format);
|
|
|
|
/*
|
|
** Print I/O action <action_number> as a goal.
|
|
**
|
|
** The goal is printed to the given file if the file pointer is non-NULL.
|
|
** The goal is printed by giving it to the specified browser.
|
|
**
|
|
** XXX Actually, the "out" parameter is currently ignored.
|
|
*/
|
|
|
|
extern const char *MR_trace_browse_action(FILE *out,
|
|
MR_IoActionNum action_number,
|
|
MR_GoalBrowser browser, MR_BrowseCallerType caller,
|
|
MR_BrowseFormat format);
|
|
|
|
/*
|
|
** Parse the given word into a variable specification and the specification
|
|
** of a path within that variable. The variable is specified by either its name
|
|
** or its sequence number in the set of live variables at the current point;
|
|
** the desired part is specified by zero or more suffixes of the form
|
|
** ^argnum or /argnum.
|
|
*/
|
|
|
|
extern const char *MR_trace_parse_var_path(char *word_spec,
|
|
MR_VarSpec *var_spec, char **path);
|
|
|
|
/*
|
|
** Parse the given word into a variable specification and the specification
|
|
** of a path within that variable, as with MR_trace_parse_var_path, then
|
|
** look up and record the term at that path in *type_info and *value,
|
|
** and return NULL. If there is a problem with changing to a specified subterm,
|
|
** then return the term path of the problematic subterm and set *bad_subterm
|
|
** to true. If there is some other problem, return a description of the problem
|
|
** and set *bad_subterm to false.
|
|
*/
|
|
|
|
extern const char *MR_trace_parse_lookup_var_path(char *word_spec,
|
|
MR_TypeInfo *type_info, MR_Word *value,
|
|
MR_bool *bad_subterm);
|
|
|
|
/*
|
|
** Print the (names and) values of (the specified parts of) the specified
|
|
** variable. (The variable is specified by either its name or its sequence
|
|
** number in the set of live variables at the current point; the desired part
|
|
** is specified by zero or more suffixes of the form ^argnum or /argnum.
|
|
**
|
|
** The names are printed to the file specified by the out parameter if
|
|
** print_var_name is set, which requires out to be non-NULL.
|
|
** The values are printed by giving them to the specified browser.
|
|
** The last argument governs whether this function returns an error
|
|
** if the given variable specification is ambiguous.
|
|
**
|
|
** XXX Actually, the "out" parameter is currently ignored by the browser.
|
|
*/
|
|
|
|
extern const char *MR_trace_parse_browse_one(FILE *out,
|
|
MR_bool print_var_name, char *word_spec,
|
|
MR_Browser browser, MR_BrowseCallerType caller,
|
|
MR_BrowseFormat format, MR_bool must_be_unique);
|
|
|
|
/*
|
|
** Print the (name and) value of the specified variable.
|
|
** The name is printed to the given file if print_var_name is set.
|
|
** The values are printed by giving them to the specified browser.
|
|
** The last argument governs whether this function returns an error
|
|
** if the given variable specification is ambiguous.
|
|
**
|
|
** XXX Actually, the "out" parameter is currently ignored by the browser.
|
|
*/
|
|
|
|
extern const char *MR_trace_browse_one(FILE *out, MR_bool print_var_name,
|
|
MR_VarSpec var_spec, MR_Browser browser,
|
|
MR_BrowseCallerType caller, MR_BrowseFormat format,
|
|
MR_bool must_be_unique);
|
|
|
|
|
|
extern const char *MR_trace_browse_one_path(FILE *out,
|
|
MR_bool print_var_name, MR_VarSpec var_spec,
|
|
char *path, MR_Browser browser,
|
|
MR_BrowseCallerType caller, MR_BrowseFormat format,
|
|
MR_bool must_be_unique);
|
|
|
|
/*
|
|
** Print the list of the names and values of all variables live at the current
|
|
** point. The variables names are printed directly to the given file, but
|
|
** only if the given file pointer is not NULL; the variable values are
|
|
** printed by calling the given browser function on them.
|
|
**
|
|
** XXX Actually, the "out" parameter is currently ignored by the browser.
|
|
*/
|
|
|
|
extern const char *MR_trace_browse_all(FILE *out, MR_Browser browser,
|
|
MR_BrowseFormat format);
|
|
|
|
|
|
/*
|
|
** Sets the current set of variables to be ones live at the program point
|
|
** referred to by level_layout, base_sp and base_curfr arguments, and then
|
|
** prints them all.
|
|
**
|
|
** XXX Actually, the "out" parameter is currently ignored by the browser.
|
|
*/
|
|
|
|
extern const char *MR_trace_browse_all_on_level(FILE *out,
|
|
const MR_LabelLayout *level_layout,
|
|
MR_Word *base_sp, MR_Word *base_curfr,
|
|
int ancestor_level, MR_bool print_optionals);
|
|
|
|
/*
|
|
** If the given variable specification is unambiguous, then set *type_info
|
|
** to the type of the specified variable, set *value to its value, and set
|
|
** *name to its name (the storage name points to will remain valid only until
|
|
** the next call to MR_lookup_unambiguous_var_spec). Return a non-NULL error
|
|
** message if this is not possible.
|
|
*/
|
|
|
|
extern const char *MR_lookup_unambiguous_var_spec(MR_VarSpec var_spec,
|
|
MR_TypeInfo *type_info, MR_Word *value,
|
|
const char **name);
|
|
|
|
/*
|
|
** *value and type_info describe a term, and path specifies a subterm of that
|
|
** term. If the path is valid, return NULL and put the specified subterm in
|
|
** *sub_value and **sub_type_info. If it is not valid, return the invalid part
|
|
** of the path specification. This can be turned into an error message with
|
|
** MR_trace_bad_path.
|
|
*/
|
|
|
|
extern char *MR_select_specified_subterm(char *path,
|
|
MR_TypeInfo type_info, MR_Word *value,
|
|
MR_TypeInfo *sub_type_info, MR_Word **sub_value);
|
|
|
|
/*
|
|
** Given an invalid path specification, return an error message for that error.
|
|
**
|
|
** The returned string is valid only until the next call to MR_trace_bad_path
|
|
** or MR_trace_bad_path_in_var.
|
|
*/
|
|
|
|
extern const char *MR_trace_bad_path(char *fullpath, char *badpath);
|
|
|
|
/*
|
|
** Given a path specification that does not exist within the specified
|
|
** variable, return an error message for that error.
|
|
**
|
|
** The returned string is valid only until the next call to MR_trace_bad_path
|
|
** or MR_trace_bad_path_in_var.
|
|
*/
|
|
|
|
extern const char *MR_trace_bad_path_in_var(MR_VarSpec *var_spec,
|
|
char *fullpath, char *badpath);
|
|
|
|
/*
|
|
** Print the size of the specified variable(s) to the specified file.
|
|
** Return a non-NULL error message if this is not possible.
|
|
*/
|
|
|
|
extern const char *MR_trace_print_size_one(FILE *out, char *word_spec);
|
|
|
|
/*
|
|
** Print the size of all the variables at the current program point to the
|
|
** specified file. Return a non-NULL error message if this is not possible.
|
|
*/
|
|
|
|
extern const char *MR_trace_print_size_all(FILE *out);
|
|
|
|
/*
|
|
** Return the current goal as the components of a synthetic term.
|
|
*/
|
|
|
|
extern void MR_convert_goal_to_synthetic_term(const char **functor_ptr,
|
|
MR_Word *arg_list_ptr, MR_bool *is_func_ptr);
|
|
|
|
/*
|
|
** Return lists of names and univ values in the current environment.
|
|
*/
|
|
|
|
extern void MR_trace_return_bindings(MR_Word *names_ptr,
|
|
MR_Word *values_ptr);
|
|
|
|
/*
|
|
** A Readline completer for variable names.
|
|
*/
|
|
|
|
extern MR_CompleterList *MR_trace_var_completer(const char *word,
|
|
size_t word_len);
|
|
|
|
#ifdef MR_TRACE_CHECK_INTEGRITY
|
|
|
|
/*
|
|
** Checks whether any stack frame at the current program point contains
|
|
** references to terms with corrupted representations.
|
|
*/
|
|
|
|
extern void MR_trace_check_integrity(const MR_LabelLayout *layout,
|
|
MR_TracePort port);
|
|
|
|
#endif /* MR_TRACE_CHECK_INTEGRITY */
|
|
|
|
#endif /* MERCURY_TRACE_VARS_H */
|