From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: =?UTF-8?Q?Cl=c3=a9ment_Pit--Claudel?= Newsgroups: gmane.emacs.devel Subject: Lisp-friendly backtraces [was: Lispy backtraces] Date: Mon, 5 Dec 2016 01:02:23 -0500 Message-ID: <27574c57-658c-c87b-4ddc-b24f83e2867c@gmail.com> References: <20160922231447.GA3833@odonien.localdomain> <98fbb582-3da4-bd83-a2e9-e341dd7f6140@gmail.com> <20160923075116.GA612@odonien.localdomain> <82e39377-f31b-698c-5a9a-343868686799@gmail.com> <20161202005226.GA4215@odonien.localdomain> <0a69afa7-e9e6-e75f-8e90-6438683db98d@gmail.com> <53ba4534-1ec3-4e4f-d929-1a72f79c1abe@gmail.com> <83mvgblniy.fsf@gnu.org> <143c480c-a9db-7053-4b70-175633197981@gmail.com> <83a8cbl94w.fsf@gnu.org> <233f14a0-7542-5d0c-d8da-209e7e5e54f7@gmail.com> <838trvkq72.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="gtPCpNb7SgkwEB4e34jJeGRXk9DirkA1g" X-Trace: blaine.gmane.org 1480917800 22179 195.159.176.226 (5 Dec 2016 06:03:20 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 5 Dec 2016 06:03:20 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 Cc: Alan Mackenzie , emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Dec 05 07:03:16 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cDmMt-0005Dq-Om for ged-emacs-devel@m.gmane.org; Mon, 05 Dec 2016 07:03:15 +0100 Original-Received: from localhost ([::1]:37077 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cDmMx-0000Kx-JO for ged-emacs-devel@m.gmane.org; Mon, 05 Dec 2016 01:03:19 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:35425) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cDmMM-0000Kr-L1 for emacs-devel@gnu.org; Mon, 05 Dec 2016 01:02:43 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cDmML-0001vV-EG for emacs-devel@gnu.org; Mon, 05 Dec 2016 01:02:42 -0500 Original-Received: from mout.kundenserver.de ([217.72.192.73]:59102) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cDmMG-0001uf-Ka; Mon, 05 Dec 2016 01:02:36 -0500 Original-Received: from [18.189.106.208] ([18.189.106.208]) by mrelayeu.kundenserver.de (mreue103 [212.227.15.184]) with ESMTPSA (Nemesis) id 0Mh6vJ-1c0OKm1Yqv-00MLrq; Mon, 05 Dec 2016 07:02:33 +0100 In-Reply-To: <838trvkq72.fsf@gnu.org> X-Provags-ID: V03:K0:b/GH5pDeg8xf5z68BuupDm+Jr1OuN/i8XZXTrtQeOHlbYWC0vnU EprGiXNue/58ZR+SPVXgClxww8hItFbEKavmKHvT6M9xw0WYN1K0jKdB0sW3QVRSKioEOgx wFhcryNEPbduNwKZdeaOVo7JS13aiYQQpGWJa5b8I5BCZCR+qal8MlWNlZZ/jNgdBIuCJcp Gge7cJmvis7f/MF5OEt0A== X-UI-Out-Filterresults: notjunk:1;V01:K0:ve+0QYOprKE=:OEa0K2o4z2Cd217qd1bvym yEMhtie3CpYNnnyId0YQkzQmh6arg4EUyWZ9TQR6CCWNAYlAGvHG4rI6OsY8q2DWihcIZSvn7 VuRnoTC3x70N13SA/TKP2wBmmufPLtrMomM4WsK5ewkKcDXsZnjhsUGXwaJSR8Lrgb571ovrX w9YMvQtab7jHghmXRl9rqbNIKGRVRNr3wKplNE8enEOZy7j9mSZW3BzXYm3s8bSMhBE999Fyv 3z8EwuqIIpes0cTnGR9Xw3+grg1puDd1Ze4loffXcUodUJoAfLk0C9+xw3pfJTFhGF+ZjSLw7 8SOVjn3AGGFqXOHFhc2G++N+MhyQYcICBY/tuktO3c9oC1NOPnWLZ16D4IfMq/ut2M8YQkglK w7FL6NT3kXRJAeZayn6vsL+BLXzd3AdySkFKqnO/riN9oq6wxF/ETK4oazBLt6S1G1LBC9pYg dTygwu08NHgtRKng/L0JRwpuVVCDDBjckCSLmSsq5G4PixykiJTWnoJ+S8D6Gc1vh24sZPicy Q+WQdw4ksV5IcCcMXMH1Rkw2QlEMu+ZxKPjVJesX4Ozo3Di1QvltLBsRdH+8mNNzZPtfpKsFD sZeLPppSYkYm4nFNK7T1cz4iCOJ1DfIN0ib1W8542bWGZ+LpnqjK5tZBajQcMeriSJijvnnME +2mjHBoJKl35ye5uJ35uAW7lxkkN6Fd9HqZSzZYyLD3aqsAnWFSAatSTOLXUx9eqMiPQ= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.73 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:210050 Archived-At: This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --gtPCpNb7SgkwEB4e34jJeGRXk9DirkA1g Content-Type: multipart/mixed; boundary="XCrmQcUeWKW4Kh9hIdmoqgxRctjo7Pp0I"; protected-headers="v1" From: =?UTF-8?Q?Cl=c3=a9ment_Pit--Claudel?= To: Eli Zaretskii Cc: emacs-devel@gnu.org, Alan Mackenzie Message-ID: <27574c57-658c-c87b-4ddc-b24f83e2867c@gmail.com> Subject: Lisp-friendly backtraces [was: Lispy backtraces] References: <20160922231447.GA3833@odonien.localdomain> <98fbb582-3da4-bd83-a2e9-e341dd7f6140@gmail.com> <20160923075116.GA612@odonien.localdomain> <82e39377-f31b-698c-5a9a-343868686799@gmail.com> <20161202005226.GA4215@odonien.localdomain> <0a69afa7-e9e6-e75f-8e90-6438683db98d@gmail.com> <53ba4534-1ec3-4e4f-d929-1a72f79c1abe@gmail.com> <83mvgblniy.fsf@gnu.org> <143c480c-a9db-7053-4b70-175633197981@gmail.com> <83a8cbl94w.fsf@gnu.org> <233f14a0-7542-5d0c-d8da-209e7e5e54f7@gmail.com> <838trvkq72.fsf@gnu.org> In-Reply-To: <838trvkq72.fsf@gnu.org> --XCrmQcUeWKW4Kh9hIdmoqgxRctjo7Pp0I Content-Type: multipart/mixed; boundary="------------C1B511C5833B5E5EA51097EE" This is a multi-part message in MIME format. --------------C1B511C5833B5E5EA51097EE Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable On 2016-12-04 22:30, Eli Zaretskii wrote: >>> So would it perhaps make sense to rename 'backtrace' into something >>> like 'backtrace--internal', and make it accept one more argument, the= >>> function to apply to each frame, which is now hard-coded as 'prin1'? >>> Would that allow you to implement 'backtrace' in Lisp and also >>> implement whatever application you had in mind, by calling >>> 'backtrace--internal' passing it your own function instead of 'prin1'= ? >> >> Quite possibly! > > Will you be working on this idea at some point? Yup. I've attached a rough patch, and an ELisp file showing what calling= the new function (mapbacktrace) looks like. Let me know if this direction makes sense. If so, I will write the corre= sponding documentation, a Changelog entry, and a proper commit message. (CC Alan, since you recently expressed frustration with the contents of t= he *Backtrace* buffer; hopefully this new function will help with impleme= nting a more flexible *Backtrace* buffer?) Cheers, Cl=E9ment. --------------C1B511C5833B5E5EA51097EE Content-Type: text/x-diff; name="0001-New-function-mapbacktrace.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-New-function-mapbacktrace.patch" =46rom 861c841eb242c474c66421ce4d9964940033ff31 Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Cl=3DC3=3DA9ment=3D20Pit--Claudel?=3D Date: Mon, 5 Dec 2016 00:52:14 -0500 Subject: [PATCH] New function mapbacktrace --- src/eval.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index 724f001..dcda51c 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3420,6 +3420,53 @@ The debugger is entered when that frame exits, if = the flag is non-nil. */) return flag; } =20 +DEFUN ("mapbacktrace", Fmapbacktrace, Smapbacktrace, 1, 2, 0, + doc: /* Call FUNCTION for each frame in backtrace. +FUNCTION is called with 4 arguments EVALD FUNC ARGS FLAGS. If a frame +has not evaluated its arguments yet or is a special form, EVALD is nil +and ARGS is a list of forms. If a frame has evaluated its arguments +and called its function already, EVALD is t and ARGS is a list of +values. FLAGS is a plist of properties of the current frame: +currently, the only supported property is :debug-on-exit. +If NSKIP is non-nil, the top NSKIP frames are skipped. +`mapbacktrace' always returns nil. */) + (Lisp_Object function, Lisp_Object nskip) +{ + union specbinding *pdl =3D backtrace_top (); + + if (!NILP (nskip)) + { + CHECK_NUMBER(nskip); + EMACS_INT to_skip =3D XINT(nskip); + while (to_skip > 0 && backtrace_p (pdl)) { + to_skip--; + pdl =3D backtrace_next (pdl); + } + } + + while (backtrace_p (pdl)) + { + Lisp_Object flags =3D Qnil; + if (backtrace_debug_on_exit (pdl)) + { + flags =3D Fcons (QCdebug_on_exit, Fcons (Qt, Qnil)); + } + + if (backtrace_nargs (pdl) =3D=3D UNEVALLED) + { + call4 (function, Qnil, backtrace_function (pdl), *backtrace_ar= gs (pdl), flags); + } + else + { + Lisp_Object tem =3D Flist (backtrace_nargs (pdl), backtrace_ar= gs (pdl)); + call4 (function, Qt, backtrace_function (pdl), tem, flags); + } + pdl =3D backtrace_next (pdl); + } + + return Qnil; +} + DEFUN ("backtrace", Fbacktrace, Sbacktrace, 0, 0, "", doc: /* Print a trace of Lisp function calls currently active. Output stream used is value of `standard-output'. */) @@ -3973,7 +4020,8 @@ alist of active lexical bindings. */); defsubr (&Srun_hook_wrapped); defsubr (&Sfetch_bytecode); defsubr (&Sbacktrace_debug); - defsubr (&Sbacktrace); + DEFSYM (QCdebug_on_exit, ":debug-on-exit"); + defsubr (&Smapbacktrace); defsubr (&Sbacktrace_frame); defsubr (&Sbacktrace_eval); defsubr (&Sbacktrace__locals); --=20 2.7.4 --------------C1B511C5833B5E5EA51097EE Content-Type: text/x-emacs-lisp; name="bt.el" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="bt.el" ;; -*- lexical-binding: t -*- (defun backtrace-1 (evald func args flags) "Print a trace of a single stack frame to `standard-output'. EVALD, FUNC, ARGS, FLAGS are as in `mapbacktrace'." (let ((print-level (or print-level 8))) (princ (if (plist-get flags :debug-on-exit) "* " " ")) (cond ((and evald (not debugger-stack-frame-as-list)) (prin1 func) (if args (prin1 args) (princ "()"))) (t (prin1 (cons func args)))) (princ "\n"))) (defun backtrace () "Print a trace of Lisp function calls currently active. Output stream used is value of `standard-output'." (mapbacktrace #'~/backtrace-1 1)) (defun backtrace-frames () "Collect all frames of current backtrace into a list." (let ((frames nil)) (mapbacktrace (lambda (&rest frame) (push frame frames)) 2) (nreverse frames))) (defun ~/backtrace-frame (nframes &optional base) "Return the function and arguments NFRAMES up from current execution po= int. If that frame has not evaluated the arguments yet (or is a special form),= the value is (nil FUNCTION ARG-FORMS...). If that frame has evaluated its arguments and called its function already= , the value is (t FUNCTION ARG-VALUES...). A &rest arg is represented as the tail of the list ARG-VALUES. FUNCTION is whatever was supplied as car of evaluated list, or a lambda expression for macro calls. If NFRAMES is more than the number of frames, the value is nil. If BASE is non-nil, it should be a function and NFRAMES counts from its nearest activation frame." (let ((frame nil)) (mapbacktrace (lambda (evald func args _) (when (and base (eq func base)) (setq base nil)) (unless base (when (eq nframes 0) (setq frame `(,evald ,func ,@args))) (setq nframes (1- nframes))))) frame)) --------------C1B511C5833B5E5EA51097EE-- --XCrmQcUeWKW4Kh9hIdmoqgxRctjo7Pp0I-- --gtPCpNb7SgkwEB4e34jJeGRXk9DirkA1g Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJYRQLvAAoJEPqg+cTm90wjS9AP/3PUePEzygCRXsq7vzPeaVRY VIJ+Icutfj5YVOljh9fmIGpfReh676eONTSqvdnxnX8uphiezfGrz3XfdCegaMRv 4ATXFP32vL2xvdD3oQJLWs0CxkXS0tWov/HcCsCWsnqECyEqqNyZ6djgUuCLP3ik xOX1f7vvbC+7E29jlZGXUPLf6jPkzDjcLxI1IdB7bx2ZN+HFgfUxCwk9AHOScAyW 1C0T5Q6LonCgurA/08T4Q9blv6L+ogR4zYxA5rzyrbWhbglN+LDdtvYqUBKjPfA6 Ty86myfvkPyMGKDdJPfiDBpPNOGnHHSV560CM65OevBo+UrRK7sBCFtS8z1a053E bEVSxbv7SYsI4vf4tcEvc9hxNqxYJpUzbihZcxV8ogaawViHCJ674CXujhENpGAl aUCi9wcz6An15rdy6z7Se4OEkJcrjnLNrvGxxWXjGsgOxAiu8A7+dUWN80tH8RyZ qxzwd5YpQ5/jM1eLvJuMqRnsyq+514UA+tBSNv3RkKTZPRSVPOGotxld+xyrs/KP /shwoA9qM4VnQbeoyn2aqwu9NwrS2ZVnETmWfz5duH6Zrm2GBeJtkrUait2+Vkm9 6TnGosrY3pD1Kdt62K51HUtWgJz1k4T+fHOJ9MWXahHUzaaClBq/589MyfZdULcG qFvtlC+UBai5m3ALQVxH =oiwc -----END PGP SIGNATURE----- --gtPCpNb7SgkwEB4e34jJeGRXk9DirkA1g--