;;; -*- Mode: LISP; Package: USER; Base: 10 -*- ;;; $Header: /ct/debug/dianades.l,v 1.1 85/06/27 10:10:24 bill Exp $ (putprop 'dianades "$Revision: 1.1 $" 'rcs_revision) ;;; ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; ;;; dianades.l ;;; ;;; ;;; ;;; William Brew 8-22-83 ;;; ;;; ;;; ;;; Code for the Ada dianades. ;;; ;;; ;;; ;;; This file is part of a proprietary software project. Source ;;; ;;; code and documentation describing implementation details are ;;; ;;; available on a confidential, non-disclosure basis only. These ;;; ;;; materials, including this file in particular, are trade secrets ;;; ;;; of Computer * Thought Corporation. ;;; ;;; ;;; ;;; (c) Copyright 1982 and 1983, Computer * Thought Corporation. ;;; ;;; All Rights Reserved. ;;; ;;; ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Ensure presence of needed files. (comment Assumes ct_load and some suitable file_map are present) (eval-when (compile load eval) (ct_load 'aip)) ;AIP macros pkg. (eval-when (compile load eval) (ct_load 'compat)) ;Franz/LM compat pkg. (eval-when (compile load eval) (ct_load 'ctstrl)) ;New strings (eval-when (compile load eval) (ct_load 'dlist)) ;The double linked lists (eval-when (compile load eval) (ct_load 'ctio)) ;Compatable io (eval-when (compile load eval) (ct_load 'dbutils)) ; Debugger utilities (eval-when (compile load eval) (ct_load 'dianatags)) ; Tag flavor (eval-when (load eval) (ct_load 'point)) ; Diana pointing utils (eval-when (load eval) (ct_load 'datades)) ; Data desciption #+franz (eval-when (load eval) (ct_load 'screens)) ; Windows, asks #+lispm (eval-when (load eval) (ct_load 'lmscreens)) ; Windows, asks (eval-when (compile load eval) (ct_load 'adabe)) ; Activation rec flavor (eval-when (compile load eval) (ct_load 'ferec)) ; Interpretter records (eval-when (compile load eval) (ct_load 'dsmacs)) ; Dynamic semantics utilities (eval-when (compile load eval) (ct_load 'diana)) ; Diana node utiliies (eval-when (load eval) (ct_load 'dynsem)) ; Dynamic semantics (numval) (eval-when (load eval) (ct_load 'envirwalk)) ; Environment walker (curr act) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Compiler Declarations and Global Variables -- #+franz (declare (macros t)) #+franz (setq *flavor-expand-macros* t) (defvar *db%describable_ids* nil "A list of diana id like node types which are describable.") (defvar *db%describable_statements* nil "A list of diana statement like node types which are describable.") (defvar *db%latest_description* nil "A circular dlist of tags for nodes which the dianades has described. The list acts as a finite depth stack of the latest descriptions.") (defconst *db%description_depth* 3 "The number of descriptions which are remembered.") (defconst *db%modify_ada_constants* t "A flag used to control whether we will allow Ada constants to be modified.") ; Specials used here and delared elsewhere. (declare (special *db%user_window*)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Macro definitions -- ; Macro to make a diana id node type able to print its lexical representation. (defmacro db%make_diana_printable (node_type body) `(cond (,body (putprop ,node_type ,body 'printself_program)) (t (remprop ,node_type 'printself_program)))) ; Macro to make a diana id node type able to describe its static semantics. (defmacro db%make_diana_describable (node_type body) `(cond (,body (putprop ,node_type ,body 'describeself_program)) (t (remprop ,node_type 'describeself_program)))) ; Macro to make a diana id node type able to determine its defining occurrence. (defmacro db%make_diana_defineable (node_type body) `(cond (,body (putprop ,node_type ,body 'defineself_program)) (t (remprop ,node_type 'defineself_program)))) ; Format a string on the indicated stream. (ala format) (defmacro db%formstring (stream string) `(let ((str ,string)) (ct_if ,stream (ct_princ str ,stream) str))) ; Get the node tag from an description stack cell. (defmacro db%dl_node_tag (dl) `(first (dlval ,dl))) ; Get the definition tag from an description stack cell. (defmacro db%dl_def_tag (dl) `(second (dlval ,dl))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Flavor definitions -- ; ; A new tag flavor for the diana describer. Add an instance variable to remember ; the list of nodes that we found. ; (ct_defflavor db%describer_tag ((node_list nil)) ; The nodes found () (:included-flavors db%vanilla_tag_flavor) :gettable-instance-variables :settable-instance-variables #+lispm :initable-instance-variables) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Externally Callable Functions/Methods -- ; ; Initialize the describer ; (defun db%init_dianades () (db%init_id_describables) (db%init_statement_describables) (db%init_misc)) ; ; Startup the describer ; (defun db%start_dianades () (db%start_describer_tags)) ; ; A function for describing diana nodes. Used to describe any kind of id ; node. First we find the node we are interested in by finding the node the ; user is pointing at. Then call the node describe function. Finally put the ; node in the described node stack. Features is a list of features to control ; how things are described. Current features are refine and modify. Refine implies ; that the user should be given a chance to refine composite objects. (e.g. arrays) ; Modify impies that the user should be given a chance to modify the value of an ; object. ; (defun db%describe_id (&optional (features '(refine modify))) (let* ((nodes (db%get_best_nodes *db%describable_ids*)) (node (first nodes)) (activation (cond ((null nodes) nil) ((eq (length nodes) 1) (db%current_activation)) (t 'multiple_nodes)))) (cond ((diana_nodep node) (unwind-protect (db%describe_id_node node activation *db%user_window* features) (ct_terpri *db%user_window*)) (setq *db%latest_description* (dlsucc *db%latest_description*)) (set-iv db%describer_tag (db%dl_node_tag *db%latest_description*) 'node_list nodes) (set-iv db%describer_tag (db%dl_node_tag *db%latest_description*) 'node node)) (t (db%message "What you are pointing at is not describable."))))) ; ; Describe a diana id node. Just format up the strings generated by the ; various diana utilities. Note, the valueself part of the description must be ; called after the rest of the line has gone out because valueself can ; potenially ask the user some questions based on what has been shown so far. ; For this reason, stream should be an interactive stream if the valueself ; prog can ask questions. Activation is the activation record (runtime stack) ; which is used as the root for finding values. ; (defun db%describe_id_node (node activation stream &optional (features '(refine modify))) (let ((descrip (db%diana_describeself node nil features)) (valueable (db%diana_valueselfp node activation)) string1 string2 string3) (cond ((not (ct_string_equal descrip "")) (setq string1 (ct_format stream "~a is ~a ~a" (db%diana_printself node nil features) (db%proper_article_for descrip) descrip)) (cond ((eq valueable 'normal) (setq string2 (ct_format stream " with value ")) (setq string3 (db%diana_valueself node activation stream features))) ((eq valueable 'multiple_nodes) (setq string2 (ct_format stream " with value ")) (setq string3 (ct_format stream "*GENERIC AMBIGUITY*"))) (t (setq string2 "" string3 "")))) (t (setq string1 (ct_format stream "")) (setq string2 "" string3 ""))) (ct_if (null stream) (ct_string_append string1 string2 string3)))) ; ; Describe a diana node. Just format up the strings generated by the ; various diana utilities. ; (defun db%describe_node (node stream &optional features) (let ((descrip (db%diana_describeself node nil features)) string1) (cond ((not (ct_string_equal descrip "")) (setq string1 (ct_format stream "~a is ~a ~a" (db%diana_printself node nil features) (db%proper_article_for descrip) descrip))) (t (setq string1 (ct_format stream "")))) (ct_if (null stream) string1))) ; ; The following are a sequence of utilities for getting various properties ; of diana nodes. ; ; Print the lexical representation of a diana node. Check to see if the ; node type has a printself program. If not then try its defintion. If still ; no luck then return the null string. ; (defun db%diana_printself (node stream &optional features) (let (dnode (program (and node (get (diana_nodetype_get node) 'printself_program)))) (cond (program (apply (car program) (cons node (cons stream (cons features (cdr program)))))) ((neq node (setq dnode (db%diana_defineself node))) (db%diana_printself dnode stream features)) (t "")))) ; ; Print a description of the static semantics of a diana node. Check to see ; if the node type has a descibe program. If not then check for a defining ; occurrence. If not then return the null string. ; (defun db%diana_describeself (node stream &optional features) (let (dnode (program (get (diana_nodetype_get node) 'describeself_program))) (cond (program (apply (car program) (cons node (cons stream (cons features (cdr program)))))) ((neq node (setq dnode (db%diana_defineself node))) (db%diana_describeself dnode stream features)) (t "")))) ; ; A simple predicate to tell if we know how to describe a particular diana node type. ; (defun db%diana_describable_p (node stream) (neq "" (db%diana_describeself node stream))) ; ; Get the defining occurrence of a id like diana node. Check for a defining ; program. If there is one then call it. If not return the node itself. If we get a ; new node, then try getting the defining occurrence of it. ; (defun db%diana_defineself (node) (let* ((program (and node (get (diana_nodetype_get node) 'defineself_program))) (dnode (ct_if program (apply (car program) (cons node (cdr program))) node))) (ct_if (neq node dnode) (db%diana_defineself dnode) dnode))) ; ; A predicate to check whether the runtime "value" of a diana node exist. ; Look first to see if this is for a generic defintion. If so then no value. ; Look for a value self program. ; If none, then try for a defining occurrence. If none then return nil. ; (defun db%diana_valueselfp (node activation) (let (dnode) ;;hack for now until we have a better scheme for generics (cond ;((eq (db%classify_node node) 'generic_definition) nil) ((and node (get (diana_nodetype_get node) 'valueself_program)) (ct_if (eq activation 'multiple_nodes) 'multiple_nodes 'normal)) ((neq node (setq dnode (db%diana_defineself node))) (db%diana_valueselfp dnode activation)) (t nil)))) ; ; Print the runtime "value" of a diana node. Look for a value self program. ; If none, then try for a defining occurrence. If none then return the null ; string. Activation is the activation record which is used to derive a value ; for variables. ; (defun db%diana_valueself (node activation stream &optional (features nil)) (let (dnode (program (and node (get (diana_nodetype_get node) 'valueself_program)))) (cond (program (apply (car program) (cons node (cons activation (cons stream (cons features (cdr program))))))) ((neq node (setq dnode (db%diana_defineself node))) (db%diana_valueself dnode activation stream features)) (t "")))) ; ; A function to return a list of describer tags. Run around the description stack ; and collect up all the tags. ; (defun db%describer_tags () (loop for cell = *db%latest_description* then (dlpred cell) if (get-iv *db%describer_tag (first (dlval cell)) 'node) append (dlval cell) until (eq (dlpred cell) *db%latest_description*))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Internal Use Only Functions/Methods -- ; ; The following code is used for building the network of diana node ; type property list programs ; which are used by the describer to do its job. ; ; First we handle the id like nodes. ; ; ; Make a diana id like node type describable. We put programs on the property ; list of the node type to print the nodes lexical representation, descibe the ; the node, to find the nodes defining occurrence and ; to give the node a run time value. ; (defun db%make_id_describable (node_type &optional pbody dbody vbody dfbody) (db%make_diana_printable node_type pbody) (db%make_diana_describable node_type dbody) (db%make_diana_valueable node_type vbody) (db%make_diana_defineable node_type dfbody) node_type) ; ; A function to initialize all the describable node types. We do so by ; calling the appropriate functions to set up the programs on the property ; lists and to add the node types to the list of describable nodes. ; (defun db%init_id_describables () (setq *db%describable_ids* (list (db%make_id_describable 'dn_argument_id '(db%lx_symrep_prog) '(db%string_prog "argument to a pragma")) (db%make_id_describable 'dn_attr_id '(db%lx_symrep_prog) '(db%string_prog "attribute")) (db%make_id_describable 'dn_comp_id '(db%lx_symrep_prog) '(db%string_prog "component of a record")) (db%make_id_describable 'dn_const_id '(db%lx_symrep_prog) '(db%string_prog "constant") '(db%const_value_prog) '(db%definition_prog sm_first)) (db%make_id_describable 'dn_def_char '(db%lx_symrep_prog) '(db%string_prog "character literal")) (db%make_id_describable 'dn_def_op '(db%lx_symrep_prog) '(db%proc_like_prog "operator") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_dscrmt_id '(db%lx_symrep_prog) '(db%string_prog "descriminant") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_entry_id '(db%lx_symrep_prog) '(db%proc_like_prog "task entry")) (db%make_id_describable 'dn_enum_id '(db%lx_symrep_prog) '(db%string_prog "enumeration element")) (db%make_id_describable 'dn_exception_id '(db%lx_symrep_prog) '(db%string_prog "exception condition") '(db%exception_value_prog)) (db%make_id_describable 'dn_function_id '(db%lx_symrep_prog) '(db%proc_like_prog "function") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_generic_id '(db%lx_symrep_prog) '(db%string_prog "generic") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_in_id '(db%lx_symrep_prog) '(db%string_prog "input parameter") '(db%variable_value_prog) '(db%definition_prog sm_first)) (db%make_id_describable 'dn_in_out_id '(db%lx_symrep_prog) '(db%string_prog "input output parameter") '(db%variable_value_prog) '(db%definition_prog sm_first)) (db%make_id_describable 'dn_iteration_id '(db%lx_symrep_prog) '(db%string_prog "iteration variable") '(db%variable_value_prog)) (db%make_id_describable 'dn_l_private_type_id '(db%lx_symrep_prog) '(db%string_prog "limited privated type")) (db%make_id_describable 'dn_label_id '(db%lx_symrep_prog) '(db%string_prog "label")) (db%make_id_describable 'dn_null_access '(db%string_prog "null") '(db%string_prog "null access")) (db%make_id_describable 'dn_number_id '(db%lx_symrep_prog) '(db%string_prog "defined number") '(db%number_value_prog)) (db%make_id_describable 'dn_numeric_literal '(db%lx_numrep_prog) '(db%string_prog "numeric literal")) (db%make_id_describable 'dn_out_id '(db%lx_symrep_prog) '(db%string_prog "output parameter") '(db%variable_value_prog) '(db%definition_prog sm_first)) (db%make_id_describable 'dn_package_id '(db%lx_symrep_prog) '(db%string_prog "package") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_pragma_id '(db%lx_symrep_prog) '(db%string_prog "pragma")) (db%make_id_describable 'dn_private_type_id '(db%lx_symrep_prog) '(db%string_prog "private type")) (db%make_id_describable 'dn_proc_id '(db%lx_symrep_prog) '(db%proc_like_prog "procedure") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_string_literal '(db%lx_symrep_prog) '(db%string_prog "string literal")) (db%make_id_describable 'dn_subtype_id '(db%lx_symrep_prog) '(db%string_prog "subtype")) (db%make_id_describable 'dn_task_body_id '(db%lx_symrep_prog) '(db%string_prog "task body") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_type_id '(db%lx_symrep_prog) '(db%string_prog "type") nil '(db%definition_prog sm_first)) (db%make_id_describable 'dn_var_id '(db%lx_symrep_prog) '(db%string_prog "variable") '(db%variable_value_prog)) (db%make_id_describable 'dn_used_bltn_id '(db%lx_symrep_prog) nil nil '(db%definition_prog sm_operator)) (db%make_id_describable 'dn_used_bltn_op '(db%lx_symrep_prog) nil nil '(db%definition_prog sm_operator)) (db%make_id_describable 'dn_used_char '(db%lx_symrep_prog) nil nil '(db%definition_prog sm_defn)) (db%make_id_describable 'dn_used_name_id '(db%lx_symrep_prog) nil nil '(db%definition_prog sm_defn)) (db%make_id_describable 'dn_used_object_id '(db%lx_symrep_prog) nil nil '(db%definition_prog sm_defn)) (db%make_id_describable 'dn_used_op '(db%lx_symrep_prog) nil nil '(db%definition_prog sm_defn)) ; ; NON STANDARD DIANA NODE TYPES ; ; like a dn_attr_id (db%make_id_describable 'dn_predefined_attribute '(db%lx_symrep_prog) '(db%string_prog "attribute")) ; like an dn_exception_id (db%make_id_describable 'dn_predefined_exception '(db%lx_symrep_prog) '(db%string_prog "exception condition") '(db%exception_value_prog)) ; like a dn_pragma_id (db%make_id_describable 'dn_predefined_pragma '(db%lx_symrep_prog) '(db%string_prog "pragma")) ; like an dn_argument_id (db%make_id_describable 'dn_predefined_pragma_parameter '(db%lx_symrep_prog) '(db%string_prog "argument to a pragma")) ;like a dn_integer or dn_float of dn_fixed type (db%make_id_describable 'dn_predefined_type '(db%lx_symrep_prog) '(db%string_prog "predefined type"))))) ; ; The following are the programs which are put on the property list of the ; various diana id node types. The functions all end in _prog. The first ; argument to each function should be the node to be examined. This argument ; is consed in to the value obtained from the property list by the accessor ; functions. ; ; ; Returns a string with the lexical representation of a symbol. (if any). ; (defun db%lx_symrep_prog (node stream features) features (db%formstring stream (apply #'ct_string_append (cadr (diana_get node 'lx_symrep))))) ; ; Returns a string with the lexical representation of a number (if any). ; Used for numeric literals and named numbers. ; (defun db%lx_numrep_prog (node stream features) features (db%formstring stream (ct_format nil "~a" (numval (diana_get node 'lx_numrep))))) ; ; A function which just evaluates to a string. ; (defun db%string_prog (node stream features string) node features (db%formstring stream string)) ; ; Describe "procedure like" diana nodes. This includes procedures, functions, ; entries, and operators. Look to see if they have a lisp function ; implementation. If so then desribe them as built in. If we cannot find a body ; then it must be an entry id. ; (defun db%proc_like_prog (node stream features string) features (let* ((def (db%diana_defineself node)) (body (db%diana_defineself (and (diana_node_accepts_attributep def 'sm_body) (diana_get def 'sm_body))))) (ct_format stream "~a~a" (ct_if (and body (diana_node_accepts_attributep body 'ct_lisp_func) (diana_get body 'ct_lisp_func)) "built in " "") string))) ; ; Get the value string of an Ada variable value object. (var_id, ; iteration_id, parameters etc.). First find the object then refine it if ; appropriate. If we cannot find an instance ; of the object then it is ambiguous defined because it is outside the scope of ; the current activation. ; (defun db%variable_value_prog (node activation stream features) (let ((instance (db%look_up_ident node activation)) final_instance string) (cond (instance (setq string (ct_send (setq final_instance (ct_if (memq 'refine features) (ct_send instance 'refine_value node features stream) instance)) 'describe_value features stream)) (cond ((memq 'modify features) (ct_send final_instance 'modify_value node features stream)) (t string))) (t (db%formstring stream "*OUT OF SCOPE*"))))) ; ; Get the value string of an exception condition. ; ; --NB flesh this out:value = the handler which would catch this or maybe raised/not raised (defun db%exception_value_prog (node activation stream features) node activation features (db%formstring stream "*NOT IMPLEMENTED YET*")) ; ; Get the value string of a constant. For now, just treat them like variables. ; (defun db%const_value_prog (node activation stream features) (ct_if *db%modify_ada_constants* (db%variable_value_prog node activation stream features) (db%variable_value_prog node activation stream (remq 'modify features)))) ; ; Get the value string of a named number. ; (defun db%number_value_prog (node activation stream features) activation features (let ((value (diana_get node 'sm_value))) (db%formstring stream (cond ((fixp value) (ct_format nil "~f" value)) ((floatp value) (ct_format nil "~d" value)) (t "bad named number"))))) ; ; Get the definition of a node. Follow the indicated attribute ; and then ask the definition to define itself. Special case for sm_first ; since our interpretter does not build a correct diana tree. Follow sm_firsts ; until it is nil, then you have the definition. ; (defun db%definition_prog (node attr) (let ((dnode (diana_get node attr))) (cond ((and (null dnode) (eq attr 'sm_first)) node) (dnode (db%diana_defineself dnode)) (t (lose 'db%insp_no_def 'db%definition_prog '("Can't get diana node definition")))))) ; ; Now set up the properties for describing statement like nodes. ; ; Make a diana statement node type describable. We put programs on the property ; list of the node type to print the nodes lexical representation, descibe the ; the node. ; (defun db%make_statement_describable (node_type &optional dbody) (db%make_diana_printable node_type '(db%string_prog "***")) (db%make_diana_describable node_type dbody) node_type) ; ; A function to initialize all the describable node types. We do so by ; calling the appropriate functions to set up the programs on the property ; lists and to add the node types to the list of describable nodes. ; ; --NB these descriptions need to be elaborated at some point (defun db%init_statement_describables () (setq *db%describable_statements* (list ;Statements (db%make_statement_describable 'dn_abort '(db%string_prog "abort statement")) (db%make_statement_describable 'dn_accept '(db%string_prog "accept statement")) (db%make_statement_describable 'dn_assign '(db%string_prog "assignment statement")) (db%make_statement_describable 'dn_block '(db%string_prog "block statement")) (db%make_statement_describable 'dn_case '(db%string_prog "case statement")) (db%make_statement_describable 'dn_code '(db%string_prog "code statement")) (db%make_statement_describable 'dn_delay '(db%string_prog "delay statement")) (db%make_statement_describable 'dn_entry_call '(db%string_prog "entry call statement")) (db%make_statement_describable 'dn_exit '(db%string_prog "exit statement")) (db%make_statement_describable 'dn_function_call '(db%string_prog "function call expression")) (db%make_statement_describable 'dn_goto '(db%string_prog "goto statement")) (db%make_statement_describable 'dn_if '(db%string_prog "if statement")) (db%make_statement_describable 'dn_loop '(db%string_prog "loop statement")) (db%make_statement_describable 'dn_null_stm '(db%string_prog "null statement")) (db%make_statement_describable 'dn_procedure_call '(db%proc_like_call_prog)) (db%make_statement_describable 'dn_raise '(db%string_prog "raise statement")) (db%make_statement_describable 'dn_return '(db%string_prog "return statement")) (db%make_statement_describable 'dn_select '(db%string_prog "select statement")) (db%make_statement_describable 'dn_terminate '(db%string_prog "terminate statement")) ; Declarations (db%make_statement_describable 'dn_comp_unit '(db%string_prog "Ada compilation unit")) ; ; Make dn_compilation describable for the benifit of the ; environment walker. (used when showing the top of stack while ; we are still looking for the main program) ; (db%make_statement_describable 'dn_compilation '(db%string_prog "Ada program")) (db%make_statement_describable 'dn_constant '(db%string_prog "constant declaration")) (db%make_statement_describable 'dn_exception '(db%string_prog "exception declaration")) (db%make_statement_describable 'dn_number '(db%string_prog "number declaration")) (db%make_statement_describable 'dn_package_decl '(db%string_prog "package declaration")) (db%make_statement_describable 'dn_subprogram_decl '(db%proc_like_decl_prog)) (db%make_statement_describable 'dn_subtype '(db%string_prog "subtype declaration")) (db%make_statement_describable 'dn_task_decl '(db%string_prog "task declaration")) (db%make_statement_describable 'dn_type '(db%string_prog "type declaration")) (db%make_statement_describable 'dn_var '(db%string_prog "variable declaration"))))) ; ; Build up a string describing procedure call like things. For now this includes ; real procedure calls as well as entry calls because the interpreter cheats. Further, ; apparently, the describe_self doesn't work with entries because they put a ; dn_selected as the sm_defn of a dn_used_name_id. Urgh. ; (defun db%proc_like_call_prog (node stream features) features (let ((def_name_type (diana_nodetype_get (db%diana_defineself (diana_get node 'as_name))))) (cond ((eq def_name_type 'dn_proc_id) (db%formstring stream "procedure call statement")) ((eq def_name_type 'dn_entry_id) (db%formstring stream "entry call statement")) ((eq def_name_type 'dn_selected) (db%formstring stream "entry call statement")) (t (db%formstring stream "unknown call"))))) ; ; Build a string describing a subprogram decl. Special case for entry decls. ; (defun db%proc_like_decl_prog (node stream features) features (cond ((eq 'dn_entry_id (diana_nodetype_get (diana_get node 'as_designator))) (db%formstring stream "entry declaration")) (t (db%formstring stream "subprogram declaration")))) ; ; Finally, set up a few miscellaneous nodes. ; (defun db%init_misc () (db%make_diana_defineable 'dn_rename '(db%definition_prog as_name)) (db%make_diana_printable 'dn_ct_task_handler '(db%string_prog "***")) (db%make_diana_describable 'dn_ct_task_handler '(db%string_prog "task handler"))) ; ; A function to get the instance (if any) which is associated with an ; identifier node. This is very similar to the look_up_ident function which the ; interpretter uses except it has been modified for the debuggers purposes. ; (mainly it can resolve a binding with respect to any activation and not ; just *activation*. Also we allow for the possiblity that we may try to ; follow the alinks beyond the bottom of the stack) The ; procedure is to find the activation record with the ; correct program nesting level by following the alinks from the current ; activation. Then we assq down the locals looking for the correct node. ; If we find something then return it. (a flavor instance for the ; identifier) If not then the identifier is either unelaborated as yet or is ; not visible from the current activation. Return nil in this case. ; (defun db%look_up_ident (id_node cur_act) (let ((dfn_node (db%diana_defineself id_node)) distance id_act) (and dfn_node cur_act (not (< (setq distance (- (get-iv adabe_activation cur_act 'pnl) (diana_get dfn_node 'ct_pnl))) 0)) (setq id_act (db%follow_alink cur_act distance)) (car (errset (cdr (assq id_node (get-iv adabe_activation id_act 'locals))) nil))))) (defun db%follow_alink (act n) (ct_if (not (> n 0)) act (let ((next_up (get-iv adabe_activation act 'alink))) (ct_if next_up (db%follow_alink next_up (1- n)) (lose 'db%insp_bad_alink 'db%follow_alink '("Bad alinks")))))) ; ; The following code is used to build and manipulate the description stack. ; ; ; Build the stack of described nodes. The stack is implemented as a circular dlist. ; *db%latest_description* always points to the most recently described node. Each ; cell of the stack constains a list of two tags. The first is the node that was ; described. The second tag is the defining occurrence of the described node. We ; build the stack by adding successive elements to the end of a dlist and then ; joining the two ends. ; (defun db%start_describer_tags () (setq *db%latest_description* (dlinfirst nil (db%make_fresh_description_tags))) (dlappend (loop for length from 1 to *db%description_depth* for cell = *db%latest_description* then (dlinlast cell (db%make_fresh_description_tags)) finally (return cell)) *db%latest_description*)) ; ; Make a pair of fresh description tags. Two tags are created and returned in a ; list. The first tag has a nil node association. The second tag has a node ; hook function which gets the defining occurrence of the node which will be ; associated with the first tag. ; (defun db%make_fresh_description_tags () (let ((node_tag (ct_make_instance 'db%describer_tag 'node nil))) (list node_tag (ct_make_instance 'db%describer_tag 'node `(db%get_tag_def_node ,node_tag) 'pname `(db%get_tag_def_pname ,node_tag) 'description `(db%get_tag_def_description ,node_tag))))) ; ; Get the defining occurrence of the node associated with a tag. This function ; is used by the describer tags to get the defining occurrence of an described ; node. ; (defun db%get_tag_def_node (tag) (db%diana_defineself (ct_csend db%describer_tag tag 'node))) ; ; Build a print representation for the tag which represents the defining occurrence ; of a node. ; (defun db%get_tag_def_pname (tag) (ct_string_append "Defining occurrence of " (db%diana_printself (db%get_tag_def_node tag) nil))) ; ; Build a print representation for the description of the tag which represents ; the defining occurrence of a node. ; (defun db%get_tag_def_description (tag) (ct_string_append "definition of " (db%diana_printself (db%get_tag_def_node tag) nil))) ;;; eof ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;