aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorGemini Lasswell2017-10-01 09:12:29 -0700
committerGemini Lasswell2017-10-08 16:08:49 -0700
commit06e452a57287c797cb96a6d4b45220358daab379 (patch)
treea6f70550cec840c08b6d95dc039991d67757de20 /lisp
parent85b4e88194cae541a0093a9166f4306e6fd3109e (diff)
downloademacs-06e452a57287c797cb96a6d4b45220358daab379.tar.gz
emacs-06e452a57287c797cb96a6d4b45220358daab379.zip
Allow Edebug's instrumentation to be used for other purposes
* lisp/emacs-lisp/edebug.el: (edebug-after-instrumentation-functions) (edebug-new-definition-functions): New hook variables. (edebug-behavior-alist): New variable. (edebug-read-and-maybe-wrap-form): Run a hook after a form is wrapped. (edebug-make-form-wrapper): Run a hook after a definition is wrapped. Remove message for each definition. (edebug-announce-definition): New function. (edebug-enter): Rewritten to change behavior of Edebug based on symbol property `edebug-behavior' and `edebug-behavior-alist'. (edebug-default-enter): New function which does what `edebug-enter' used to do. (edebug-run-slow, edebug-run-fast): Modify edebug-behavior-alist. (edebug-before, edebug-after): Function definitions are now set by `edebug-enter'.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/emacs-lisp/edebug.el154
1 files changed, 102 insertions, 52 deletions
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index dbc56e272fd..a070ff25d17 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -1065,6 +1065,31 @@ circular objects. Let `read' read everything else."
1065(defvar edebug-error-point nil) 1065(defvar edebug-error-point nil)
1066(defvar edebug-best-error nil) 1066(defvar edebug-best-error nil)
1067 1067
1068;; Hooks which may be used to extend Edebug's functionality. See
1069;; Testcover for an example.
1070(defvar edebug-after-instrumentation-functions nil
1071 "Abnormal hook run on code after instrumentation for debugging.
1072Each function is called with one argument, a form which has just
1073been instrumented for Edebugging.")
1074
1075(defvar edebug-new-definition-functions '(edebug-announce-definition)
1076 "Abnormal hook run after Edebug wraps a new definition.
1077After Edebug has initialized its own data, each hook function is
1078called with one argument, the symbol associated with the
1079definition, which may be the actual symbol defined or one
1080generated by Edebug.")
1081
1082(defvar edebug-behavior-alist
1083 '((edebug edebug-default-enter edebug-slow-before edebug-slow-after))
1084 "Alist describing the runtime behavior of Edebug's instrumented code.
1085Each definition instrumented by Edebug will have a
1086`edebug-behavior' property which is a key to this alist. When
1087the instrumented code is running, Edebug will look here for the
1088implementations of `edebug-enter', `edebug-before', and
1089`edebug-after'. Edebug's instrumentation may be used for a new
1090purpose by adding an entry to this alist and a hook to
1091`edebug-new-definition-functions' which sets `edebug-behavior'
1092for the definition.")
1068 1093
1069(defun edebug-read-and-maybe-wrap-form () 1094(defun edebug-read-and-maybe-wrap-form ()
1070 ;; Read a form and wrap it with edebug calls, if the conditions are right. 1095 ;; Read a form and wrap it with edebug calls, if the conditions are right.
@@ -1124,47 +1149,48 @@ circular objects. Let `read' read everything else."
1124 (eq 'symbol (edebug-next-token-class))) 1149 (eq 'symbol (edebug-next-token-class)))
1125 (read (current-buffer)))))) 1150 (read (current-buffer))))))
1126;;;(message "all defs: %s all forms: %s" edebug-all-defs edebug-all-forms) 1151;;;(message "all defs: %s all forms: %s" edebug-all-defs edebug-all-forms)
1127 (cond 1152 (let ((result
1128 (defining-form-p 1153 (cond
1129 (if (or edebug-all-defs edebug-all-forms) 1154 (defining-form-p
1130 ;; If it is a defining form and we are edebugging defs, 1155 (if (or edebug-all-defs edebug-all-forms)
1131 ;; then let edebug-list-form start it. 1156 ;; If it is a defining form and we are edebugging defs,
1132 (let ((cursor (edebug-new-cursor 1157 ;; then let edebug-list-form start it.
1133 (list (edebug-read-storing-offsets (current-buffer))) 1158 (let ((cursor (edebug-new-cursor
1134 (list edebug-offsets)))) 1159 (list (edebug-read-storing-offsets (current-buffer)))
1135 (car 1160 (list edebug-offsets))))
1136 (edebug-make-form-wrapper 1161 (car
1137 cursor 1162 (edebug-make-form-wrapper
1138 (edebug-before-offset cursor) 1163 cursor
1139 (1- (edebug-after-offset cursor)) 1164 (edebug-before-offset cursor)
1140 (list (cons (symbol-name def-kind) (cdr spec)))))) 1165 (1- (edebug-after-offset cursor))
1141 1166 (list (cons (symbol-name def-kind) (cdr spec))))))
1142 ;; Not edebugging this form, so reset the symbol's edebug 1167
1143 ;; property to be just a marker at the definition's source code. 1168 ;; Not edebugging this form, so reset the symbol's edebug
1144 ;; This only works for defs with simple names. 1169 ;; property to be just a marker at the definition's source code.
1145 (put def-name 'edebug (point-marker)) 1170 ;; This only works for defs with simple names.
1146 ;; Also nil out dependent defs. 1171 (put def-name 'edebug (point-marker))
1147 '(mapcar (function 1172 ;; Also nil out dependent defs.
1148 (lambda (def) 1173 '(mapcar (function
1149 (put def-name 'edebug nil))) 1174 (lambda (def)
1150 (get def-name 'edebug-dependents)) 1175 (put def-name 'edebug nil)))
1151 (edebug-read-sexp))) 1176 (get def-name 'edebug-dependents))
1152 1177 (edebug-read-sexp)))
1153 ;; If all forms are being edebugged, explicitly wrap it. 1178
1154 (edebug-all-forms 1179 ;; If all forms are being edebugged, explicitly wrap it.
1155 (let ((cursor (edebug-new-cursor 1180 (edebug-all-forms
1156 (list (edebug-read-storing-offsets (current-buffer))) 1181 (let ((cursor (edebug-new-cursor
1157 (list edebug-offsets)))) 1182 (list (edebug-read-storing-offsets (current-buffer)))
1158 (edebug-make-form-wrapper 1183 (list edebug-offsets))))
1159 cursor 1184 (edebug-make-form-wrapper
1160 (edebug-before-offset cursor) 1185 cursor
1161 (edebug-after-offset cursor) 1186 (edebug-before-offset cursor)
1162 nil))) 1187 (edebug-after-offset cursor)
1163 1188 nil)))
1164 ;; Not a defining form, and not edebugging. 1189
1165 (t (edebug-read-sexp))) 1190 ;; Not a defining form, and not edebugging.
1166 )) 1191 (t (edebug-read-sexp)))))
1167 1192 (run-hook-with-args 'edebug-after-instrumentation-functions result)
1193 result)))
1168 1194
1169(defvar edebug-def-args) ; args of defining form. 1195(defvar edebug-def-args) ; args of defining form.
1170(defvar edebug-def-interactive) ; is it an emacs interactive function? 1196(defvar edebug-def-interactive) ; is it an emacs interactive function?
@@ -1332,7 +1358,6 @@ expressions; a `progn' form will be returned enclosing these forms."
1332 1358
1333 ;; (message "defining: %s" edebug-def-name) (sit-for 2) 1359 ;; (message "defining: %s" edebug-def-name) (sit-for 2)
1334 (edebug-make-top-form-data-entry form-data-entry) 1360 (edebug-make-top-form-data-entry form-data-entry)
1335 (message "Edebug: %s" edebug-def-name)
1336 ;;(debug edebug-def-name) 1361 ;;(debug edebug-def-name)
1337 1362
1338 ;; Destructively reverse edebug-offset-list and make vector from it. 1363 ;; Destructively reverse edebug-offset-list and make vector from it.
@@ -1358,9 +1383,15 @@ expressions; a `progn' form will be returned enclosing these forms."
1358 edebug-offset-list 1383 edebug-offset-list
1359 edebug-top-window-data 1384 edebug-top-window-data
1360 )) 1385 ))
1386 (put edebug-def-name 'edebug-behavior 'edebug)
1387 (run-hook-with-args 'edebug-new-definition-functions edebug-def-name)
1361 result 1388 result
1362 ))) 1389 )))
1363 1390
1391(defun edebug-announce-definition (def-name)
1392 "Announce Edebug's processing of DEF-NAME."
1393 (message "Edebug: %s" def-name))
1394
1364 1395
1365(defun edebug-clear-frequency-count (name) 1396(defun edebug-clear-frequency-count (name)
1366 ;; Create initial frequency count vector. 1397 ;; Create initial frequency count vector.
@@ -2167,7 +2198,21 @@ error is signaled again."
2167 2198
2168;;; Entering Edebug 2199;;; Entering Edebug
2169 2200
2170(defun edebug-enter (function args body) 2201(defun edebug-enter (func args body)
2202 "Enter Edebug for a function.
2203FUNC should be the symbol with the Edebug information, ARGS is
2204the list of arguments and BODY is the code.
2205
2206Look up the `edebug-behavior' for FUNC in `edebug-behavior-alist'
2207and run its entry function, and set up `edebug-before' and
2208`edebug-after'."
2209 (cl-letf* ((behavior (get func 'edebug-behavior))
2210 (functions (cdr (assoc behavior edebug-behavior-alist)))
2211 ((symbol-function #'edebug-before) (nth 1 functions))
2212 ((symbol-function #'edebug-after) (nth 2 functions)))
2213 (funcall (nth 0 functions) func args body)))
2214
2215(defun edebug-default-enter (function args body)
2171 ;; Entering FUNC. The arguments are ARGS, and the body is BODY. 2216 ;; Entering FUNC. The arguments are ARGS, and the body is BODY.
2172 ;; Setup edebug variables and evaluate BODY. This function is called 2217 ;; Setup edebug variables and evaluate BODY. This function is called
2173 ;; when a function evaluated with edebug-eval-top-level-form is entered. 2218 ;; when a function evaluated with edebug-eval-top-level-form is entered.
@@ -2198,7 +2243,7 @@ error is signaled again."
2198 edebug-initial-mode 2243 edebug-initial-mode
2199 edebug-execution-mode) 2244 edebug-execution-mode)
2200 edebug-next-execution-mode nil) 2245 edebug-next-execution-mode nil)
2201 (edebug-enter function args body)))) 2246 (edebug-default-enter function args body))))
2202 2247
2203 (let* ((edebug-data (get function 'edebug)) 2248 (let* ((edebug-data (get function 'edebug))
2204 (edebug-def-mark (car edebug-data)) ; mark at def start 2249 (edebug-def-mark (car edebug-data)) ; mark at def start
@@ -2317,22 +2362,27 @@ MSG is printed after `::::} '."
2317 value 2362 value
2318 (edebug-debugger after-index 'after value) 2363 (edebug-debugger after-index 'after value)
2319 ))) 2364 )))
2320
2321(defun edebug-fast-after (_before-index _after-index value) 2365(defun edebug-fast-after (_before-index _after-index value)
2322 ;; Do nothing but return the value. 2366 ;; Do nothing but return the value.
2323 value) 2367 value)
2324 2368
2325(defun edebug-run-slow () 2369(defun edebug-run-slow ()
2326 (defalias 'edebug-before 'edebug-slow-before) 2370 "Set up Edebug's normal behavior."
2327 (defalias 'edebug-after 'edebug-slow-after)) 2371 (setf (cdr (assq 'edebug edebug-behavior-alist))
2372 '(edebug-default-enter edebug-slow-before edebug-slow-after)))
2328 2373
2329;; This is not used, yet. 2374;; This is not used, yet.
2330(defun edebug-run-fast () 2375(defun edebug-run-fast ()
2331 (defalias 'edebug-before 'edebug-fast-before) 2376 "Disable Edebug without de-instrumenting code."
2332 (defalias 'edebug-after 'edebug-fast-after)) 2377 (setf (cdr (assq 'edebug edebug-behavior-alist))
2333 2378 '(edebug-default-enter edebug-fast-before edebug-fast-after)))
2334(edebug-run-slow) 2379
2335 2380(defalias 'edebug-before nil
2381 "Function called by Edebug before a form is evaluated.
2382See `edebug-behavior-alist' for implementations.")
2383(defalias 'edebug-after nil
2384 "Function called by Edebug after a form is evaluated.
2385See `edebug-behavior-alist' for implementations.")
2336 2386
2337(defun edebug--update-coverage (after-index value) 2387(defun edebug--update-coverage (after-index value)
2338 (let ((old-result (aref edebug-coverage after-index))) 2388 (let ((old-result (aref edebug-coverage after-index)))