diff options
| author | Gemini Lasswell | 2017-10-01 09:12:29 -0700 |
|---|---|---|
| committer | Gemini Lasswell | 2017-10-08 16:08:49 -0700 |
| commit | 06e452a57287c797cb96a6d4b45220358daab379 (patch) | |
| tree | a6f70550cec840c08b6d95dc039991d67757de20 /lisp | |
| parent | 85b4e88194cae541a0093a9166f4306e6fd3109e (diff) | |
| download | emacs-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.el | 154 |
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. | ||
| 1072 | Each function is called with one argument, a form which has just | ||
| 1073 | been instrumented for Edebugging.") | ||
| 1074 | |||
| 1075 | (defvar edebug-new-definition-functions '(edebug-announce-definition) | ||
| 1076 | "Abnormal hook run after Edebug wraps a new definition. | ||
| 1077 | After Edebug has initialized its own data, each hook function is | ||
| 1078 | called with one argument, the symbol associated with the | ||
| 1079 | definition, which may be the actual symbol defined or one | ||
| 1080 | generated 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. | ||
| 1085 | Each definition instrumented by Edebug will have a | ||
| 1086 | `edebug-behavior' property which is a key to this alist. When | ||
| 1087 | the instrumented code is running, Edebug will look here for the | ||
| 1088 | implementations of `edebug-enter', `edebug-before', and | ||
| 1089 | `edebug-after'. Edebug's instrumentation may be used for a new | ||
| 1090 | purpose by adding an entry to this alist and a hook to | ||
| 1091 | `edebug-new-definition-functions' which sets `edebug-behavior' | ||
| 1092 | for 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. | ||
| 2203 | FUNC should be the symbol with the Edebug information, ARGS is | ||
| 2204 | the list of arguments and BODY is the code. | ||
| 2205 | |||
| 2206 | Look up the `edebug-behavior' for FUNC in `edebug-behavior-alist' | ||
| 2207 | and 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. | ||
| 2382 | See `edebug-behavior-alist' for implementations.") | ||
| 2383 | (defalias 'edebug-after nil | ||
| 2384 | "Function called by Edebug after a form is evaluated. | ||
| 2385 | See `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))) |