unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Proposal: make prog2 a macro
@ 2016-10-07  4:16 Wilfred Hughes
  2016-10-07  5:04 ` Tino Calancha
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Wilfred Hughes @ 2016-10-07  4:16 UTC (permalink / raw)
  To: emacs-devel

I was looking at a list of Emacs' special forms, and noticed that
prog2 is implemented in C. Is there any interest in moving this to a
simple macro?

I think this makes the implementation easier to understand for users
who are less familiar with the C parts of Emacs. I've brought up an
Emacs instance with the patch, and 'make check' passes.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
From 569a8b3b9c3aee677fef9a574d99727a68f86fa5 Mon Sep 17 00:00:00 2001
From: Wilfred Hughes <me@wilfred.me.uk>
Date: Thu, 6 Oct 2016 23:58:36 -0400
Subject: [PATCH] Make prog2 a macro rather than a special form

* src/eval.c (Sprog2): Remove.
* lisp/subr.el (prog2): Define a prog2 macro.
* doc/lispref/control.texi (Sequencing): prog2 is now a macro.
* doc/lispref/functions.texi (Function Safety): prog2 is no longer a
  special form.
---
 doc/lispref/control.texi   |  2 +-
 doc/lispref/functions.texi |  2 +-
 lisp/subr.el               | 11 +++++++++++
 src/eval.c                 | 12 ------------
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 0cdb035..bdcbd19 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -125,7 +125,7 @@ Sequencing
 @end defspec

 @defspec prog2 form1 form2 forms@dots{}
-This special form evaluates @var{form1}, @var{form2}, and all of the
+This macro evaluates @var{form1}, @var{form2}, and all of the
 following @var{forms}, in textual order, returning the result of
 @var{form2}.

diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index fff4ac0..37f3a18 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -2294,7 +2294,7 @@ Function Safety
 safe expressions.
 @item
 One of the special forms @code{and}, @code{catch}, @code{cond},
-@code{if}, @code{or}, @code{prog1}, @code{prog2}, @code{progn},
+@code{if}, @code{or}, @code{prog1}, @code{progn},
 @code{while}, and @code{unwind-protect}], if all its arguments are
 safe.
 @item
diff --git a/lisp/subr.el b/lisp/subr.el
index b143812..f1aecf3 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -174,6 +174,17 @@ pop
          (macroexp-let2 macroexp-copyable-p x getter
            `(prog1 ,x ,(funcall setter `(cdr ,x))))))))

+(defmacro prog2 (form1 form2 &rest body)
+  "Eval FORM1, FORM2 and BODY sequentially; return value from FORM2.
+The value of FORM2 is saved during the evaluation of the
+remaining args, whose values are discarded.
+
+\(fn FORM1 FORM2 BODY...)"
+  (declare (indent 2) (debug t))
+  `(prog1
+       (progn ,form1 ,form2)
+     ,@body))
+
 (defmacro when (cond &rest body)
   "If COND yields non-nil, do BODY, else return nil.
 When COND yields non-nil, eval BODY forms sequentially and return
diff --git a/src/eval.c b/src/eval.c
index 2fedbf3..c823530 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -465,17 +465,6 @@ usage: (prog1 FIRST BODY...)  */)
   return val;
 }

-DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
-       doc: /* Eval FORM1, FORM2 and BODY sequentially; return value
from FORM2.
-The value of FORM2 is saved during the evaluation of the
-remaining args, whose values are discarded.
-usage: (prog2 FORM1 FORM2 BODY...)  */)
-  (Lisp_Object args)
-{
-  eval_sub (XCAR (args));
-  return Fprog1 (XCDR (args));
-}
-
 DEFUN ("setq", Fsetq, Ssetq, 0, UNEVALLED, 0,
        doc: /* Set each SYM to the value of its VAL.
 The symbols SYM are variables; they are literal (not evaluated).
@@ -3917,7 +3906,6 @@ alist of active lexical bindings.  */);
   defsubr (&Scond);
   defsubr (&Sprogn);
   defsubr (&Sprog1);
-  defsubr (&Sprog2);
   defsubr (&Ssetq);
   defsubr (&Squote);
   defsubr (&Sfunction);
-- 
2.10.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-07  4:16 Proposal: make prog2 a macro Wilfred Hughes
@ 2016-10-07  5:04 ` Tino Calancha
  2016-10-07  7:46 ` John Wiegley
  2016-10-07  8:08 ` Tino Calancha
  2 siblings, 0 replies; 9+ messages in thread
From: Tino Calancha @ 2016-10-07  5:04 UTC (permalink / raw)
  To: Wilfred Hughes; +Cc: emacs-devel


On Fri, 7 Oct 2016, Wilfred Hughes wrote:

> I was looking at a list of Emacs' special forms, and noticed that
> prog2 is implemented in C. Is there any interest in moving this to a
> simple macro?
I don't have opinion about if this is worth or not, but i think is
safer to avoid the use of backquote:  prog2 could be used in an
early stage of the bootstrap.

Instead of:
> +  `(prog1
> +       (progn ,form1 ,form2)
> +     ,@body))

Better use:
   (cons 'prog1
         (cons (list 'progn form1 form2)
               body)))






^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-07  4:16 Proposal: make prog2 a macro Wilfred Hughes
  2016-10-07  5:04 ` Tino Calancha
@ 2016-10-07  7:46 ` John Wiegley
  2016-10-07 20:34   ` Richard Stallman
  2016-10-07  8:08 ` Tino Calancha
  2 siblings, 1 reply; 9+ messages in thread
From: John Wiegley @ 2016-10-07  7:46 UTC (permalink / raw)
  To: Wilfred Hughes; +Cc: emacs-devel

>>>>> "WH" == Wilfred Hughes <me@wilfred.me.uk> writes:

WH> I was looking at a list of Emacs' special forms, and noticed that prog2 is
WH> implemented in C. Is there any interest in moving this to a simple macro?

It seems it has always been in C, since the beginning of version history for
that file. I can't think of a reason it shouldn't be changed to a Lisp macro.
My desire is to move as much functionality into Emacs Lisp as is feasible.

-- 
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-07  4:16 Proposal: make prog2 a macro Wilfred Hughes
  2016-10-07  5:04 ` Tino Calancha
  2016-10-07  7:46 ` John Wiegley
@ 2016-10-07  8:08 ` Tino Calancha
  2016-10-08  2:12   ` Wilfred Hughes
  2 siblings, 1 reply; 9+ messages in thread
From: Tino Calancha @ 2016-10-07  8:08 UTC (permalink / raw)
  To: Wilfred Hughes; +Cc: emacs-devel



On Fri, 7 Oct 2016, Wilfred Hughes wrote:

> I think this makes the implementation easier to understand for users
> I've brought up an Emacs instance with the patch,
> and 'make check' passes.
You might want to update other files doing the special form treatment,
for instance, without trying to be exhaustive,
bytecomp.el, byte-opt.el, cl-macs.el.

Maybe you could also replace any mention of prog2 as a special form,
again without being exhaustive, for instance,
unsafep.el.




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-07  7:46 ` John Wiegley
@ 2016-10-07 20:34   ` Richard Stallman
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Stallman @ 2016-10-07 20:34 UTC (permalink / raw)
  To: John Wiegley; +Cc: me, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I initially defined prog2 and NOT prog1,
because prog2 subsumes prog1 nicely as in (prog2 nil ...).
Back then, I was trying in every way to keep Emacs small.

This change will cause increased inconvenience in the Lisp debugger
for interpreted code.  That is the only effect that the change will
have on users, and it is negative.

I suggest not changing it.  It works fine.  It compiles into good
code.  Changing it could break something.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-07  8:08 ` Tino Calancha
@ 2016-10-08  2:12   ` Wilfred Hughes
  2016-10-08  2:35     ` Noam Postavsky
  2016-10-08  3:40     ` Tino Calancha
  0 siblings, 2 replies; 9+ messages in thread
From: Wilfred Hughes @ 2016-10-08  2:12 UTC (permalink / raw)
  To: Tino Calancha; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 680 bytes --]

On 7 October 2016 at 04:08, Tino Calancha <tino.calancha@gmail.com> wrote:
>
> Maybe you could also replace any mention of prog2 as a special form,
> again without being exhaustive, for instance,
> unsafep.el.

OK, here's an updated patch. I've removed the usage of backquote as
suggested, and updated unsafep.el, bytecomp.el and cl-macs.el. I've
grepped through Emacs for other references to prog2, I think I've
covered everything.

> This change will cause increased inconvenience in the Lisp debugger
> for interpreted code.

I don't see how: I've added a debug declaration so you can step
through with edebug as normal. It's no different from `when' in this
respect.

Wilfred

[-- Attachment #2: 0001-Make-prog2-a-macro-rather-than-a-special-form.patch --]
[-- Type: text/x-patch, Size: 7183 bytes --]

From 5e9d390c3a5c4ac2b3ddabeab77bd6e2e9319c7b Mon Sep 17 00:00:00 2001
From: Wilfred Hughes <me@wilfred.me.uk>
Date: Thu, 6 Oct 2016 23:58:36 -0400
Subject: [PATCH] Make prog2 a macro rather than a special form

* src/eval.c (Sprog2): Remove.
* lisp/subr.el (prog2): Define a prog2 macro.
* lisp/emacs-lisp/generator.el (cps--transform-1): prog2 no longer
  exists after macro expansion, so we don't need to transform it
* lisp/emacs-lisp/bytecomp.el: Remove special treatment of prog2 in
  byte-compilation, as it's macro-expanded away.
* lisp/emacs-lisp/unsafep.el: Update comments to reflect that prog2 is
  now a macro.
* lisp/emacs-lisp/cl-macs.el (cl--simple-funcs): prog2 is no longer
  special form and does not need special treatment

* doc/lispref/control.texi (Sequencing): prog2 is now a macro.
* doc/lispref/functions.texi (Function Safety): prog2 is no longer a
  special form.
---
 doc/lispref/control.texi     |  2 +-
 doc/lispref/functions.texi   |  2 +-
 lisp/emacs-lisp/bytecomp.el  |  1 -
 lisp/emacs-lisp/cl-macs.el   |  2 +-
 lisp/emacs-lisp/generator.el |  7 -------
 lisp/emacs-lisp/unsafep.el   |  9 +++++----
 lisp/subr.el                 | 11 +++++++++++
 src/eval.c                   | 12 ------------
 8 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 0cdb035..bdcbd19 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -125,7 +125,7 @@ Sequencing
 @end defspec
 
 @defspec prog2 form1 form2 forms@dots{}
-This special form evaluates @var{form1}, @var{form2}, and all of the
+This macro evaluates @var{form1}, @var{form2}, and all of the
 following @var{forms}, in textual order, returning the result of
 @var{form2}.
 
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index fff4ac0..37f3a18 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -2294,7 +2294,7 @@ Function Safety
 safe expressions.
 @item
 One of the special forms @code{and}, @code{catch}, @code{cond},
-@code{if}, @code{or}, @code{prog1}, @code{prog2}, @code{progn},
+@code{if}, @code{or}, @code{prog1}, @code{progn},
 @code{while}, and @code{unwind-protect}], if all its arguments are
 safe.
 @item
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index c34ec5c..8d90aa7 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2406,7 +2406,6 @@ byte-compile-file-form-require
 
 (put 'progn 'byte-hunk-handler 'byte-compile-file-form-progn)
 (put 'prog1 'byte-hunk-handler 'byte-compile-file-form-progn)
-(put 'prog2 'byte-hunk-handler 'byte-compile-file-form-progn)
 (defun byte-compile-file-form-progn (form)
   (mapc 'byte-compile-file-form (cdr form))
   ;; Return nil so the forms are not output twice.
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index f5b7b82..33a9f65 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -82,7 +82,7 @@ 'cl--compiler-macro-cXXr
 ;; macro expanders to optimize the results in certain common cases.
 
 (defconst cl--simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max
-			    car-safe cdr-safe progn prog1 prog2))
+                           car-safe cdr-safe progn prog1))
 (defconst cl--safe-funcs '(* / % length memq list vector vectorp
 			  < > <= >= = error))
 
diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el
index 49af240..f326b8e 100644
--- a/lisp/emacs-lisp/generator.el
+++ b/lisp/emacs-lisp/generator.el
@@ -379,13 +379,6 @@ cps--transform-1
                       `(setf ,cps--value-symbol ,temp-var-symbol
                              ,cps--state-symbol ,next-state))))))))
 
-    ;; Process `prog2'.
-
-    (`(prog2 ,form1 ,form2 . ,body)
-      (cps--transform-1
-       `(progn ,form1 (prog1 ,form2 ,@body))
-       next-state))
-
     ;; Process `unwind-protect': If we're inside an unwind-protect, we
     ;; have a block of code UNWINDFORMS which we would like to run
     ;; whenever control flows away from the main piece of code,
diff --git a/lisp/emacs-lisp/unsafep.el b/lisp/emacs-lisp/unsafep.el
index 584684f..bfdd58d 100644
--- a/lisp/emacs-lisp/unsafep.el
+++ b/lisp/emacs-lisp/unsafep.el
@@ -33,8 +33,9 @@
 ;;  1.  It's an atom.
 ;;  2.  It's a function call to a safe function and all arguments are safe
 ;;      formulas.
-;;  3.  It's a special form whose arguments are like a function's (and,
-;;	catch, if, or, prog1, prog2, progn, while, unwind-protect).
+;;  3.  It's a special form or macro whose arguments are like a
+;;	function's (and, catch, if, or, prog1, prog2, progn, while,
+;;	unwind-protect).
 ;;  4.  It's a special form or macro that creates safe temporary bindings
 ;;      (condition-case, dolist, dotimes, lambda, let, let*).
 ;;  4.  It's one of (cond, quote) that have special parsing.
@@ -99,13 +100,13 @@ unsafep-vars
 
 ;;Other safe functions
 (dolist (x '(;;Special forms
-	     and catch if or prog1 prog2 progn while unwind-protect
+	     and catch if or prog1 progn while unwind-protect
 	     ;;Safe subrs that have some side-effects
 	     ding error random signal sleep-for string-match throw
 	     ;;Defsubst functions from subr.el
 	     caar cadr cdar cddr
 	     ;;Macros from subr.el
-	     save-match-data unless when
+	     prog2 save-match-data unless when
 	     ;;Functions from subr.el that have side effects
 	     split-string replace-regexp-in-string play-sound-file))
   (put x 'safe-function t))
diff --git a/lisp/subr.el b/lisp/subr.el
index b143812..47e2050 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -174,6 +174,17 @@ pop
          (macroexp-let2 macroexp-copyable-p x getter
            `(prog1 ,x ,(funcall setter `(cdr ,x))))))))
 
+(defmacro prog2 (form1 form2 &rest body)
+  "Eval FORM1, FORM2 and BODY sequentially; return value from FORM2.
+The value of FORM2 is saved during the evaluation of the
+remaining args, whose values are discarded.
+
+\(fn FORM1 FORM2 BODY...)"
+  (declare (indent 2) (debug t))
+  (cons 'prog1
+        (cons (list 'progn form1 form2)
+              body)))
+
 (defmacro when (cond &rest body)
   "If COND yields non-nil, do BODY, else return nil.
 When COND yields non-nil, eval BODY forms sequentially and return
diff --git a/src/eval.c b/src/eval.c
index 2fedbf3..c823530 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -465,17 +465,6 @@ usage: (prog1 FIRST BODY...)  */)
   return val;
 }
 
-DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
-       doc: /* Eval FORM1, FORM2 and BODY sequentially; return value from FORM2.
-The value of FORM2 is saved during the evaluation of the
-remaining args, whose values are discarded.
-usage: (prog2 FORM1 FORM2 BODY...)  */)
-  (Lisp_Object args)
-{
-  eval_sub (XCAR (args));
-  return Fprog1 (XCDR (args));
-}
-
 DEFUN ("setq", Fsetq, Ssetq, 0, UNEVALLED, 0,
        doc: /* Set each SYM to the value of its VAL.
 The symbols SYM are variables; they are literal (not evaluated).
@@ -3917,7 +3906,6 @@ alist of active lexical bindings.  */);
   defsubr (&Scond);
   defsubr (&Sprogn);
   defsubr (&Sprog1);
-  defsubr (&Sprog2);
   defsubr (&Ssetq);
   defsubr (&Squote);
   defsubr (&Sfunction);
-- 
2.10.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-08  2:12   ` Wilfred Hughes
@ 2016-10-08  2:35     ` Noam Postavsky
  2016-10-08  6:11       ` Eli Zaretskii
  2016-10-08  3:40     ` Tino Calancha
  1 sibling, 1 reply; 9+ messages in thread
From: Noam Postavsky @ 2016-10-08  2:35 UTC (permalink / raw)
  To: Wilfred Hughes; +Cc: emacs-devel, Tino Calancha

On Fri, Oct 7, 2016 at 10:12 PM, Wilfred Hughes <me@wilfred.me.uk> wrote:
>
>> This change will cause increased inconvenience in the Lisp debugger
>> for interpreted code.
>
> I don't see how: I've added a debug declaration so you can step
> through with edebug as normal. It's no different from `when' in this
> respect.

The "Lisp debugger" may be referring to `debug', not `edebug'. See bug
#3466 - "have `d' in debugger treat macro expansion like `c' does".
That said, I think prog2 is rare enough (a quick M-x rgrep over Emacs'
lisp code found only 66 matches vs 874 for prog1 and 8585 for progn)
that it wouldn't really matter that much.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-08  2:12   ` Wilfred Hughes
  2016-10-08  2:35     ` Noam Postavsky
@ 2016-10-08  3:40     ` Tino Calancha
  1 sibling, 0 replies; 9+ messages in thread
From: Tino Calancha @ 2016-10-08  3:40 UTC (permalink / raw)
  To: Wilfred Hughes; +Cc: emacs-devel, Tino Calancha



On Fri, 7 Oct 2016, Wilfred Hughes wrote:

> On 7 October 2016 at 04:08, Tino Calancha <tino.calancha@gmail.com> wrote:
>>
>> Maybe you could also replace any mention of prog2 as a special form,
>> again without being exhaustive, for instance,
>> unsafep.el.
>
> OK, here's an updated patch. I've removed the usage of backquote as
> suggested, and updated unsafep.el, bytecomp.el and cl-macs.el. I've
> grepped through Emacs for other references to prog2, I think I've
> covered everything.
Thank you very much.
I have one question regarding following file:

* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):

Do we still need to byte optimize the `prog2' forms arguments
after you changed it to a macro?




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Proposal: make prog2 a macro
  2016-10-08  2:35     ` Noam Postavsky
@ 2016-10-08  6:11       ` Eli Zaretskii
  0 siblings, 0 replies; 9+ messages in thread
From: Eli Zaretskii @ 2016-10-08  6:11 UTC (permalink / raw)
  To: Noam Postavsky; +Cc: me, tino.calancha, emacs-devel

> From: Noam Postavsky <npostavs@users.sourceforge.net>
> Date: Fri, 7 Oct 2016 22:35:04 -0400
> Cc: emacs-devel <emacs-devel@gnu.org>, Tino Calancha <tino.calancha@gmail.com>
> 
> The "Lisp debugger" may be referring to `debug', not `edebug'. See bug
> #3466 - "have `d' in debugger treat macro expansion like `c' does".
> That said, I think prog2 is rare enough (a quick M-x rgrep over Emacs'
> lisp code found only 66 matches vs 874 for prog1 and 8585 for progn)
> that it wouldn't really matter that much.

Sorry, but I don't find that small number to be negligible.  Debugging
Emacs Lisp code in core is already too hard; e.g., too frequently I
need to resort to "printf debugging".  I object to any further
difficulties in this area, so if we want to make this a macro, that
bug needs to be fixed first.

In any case, this issue is no more than a nice-to-have, whereas
debugging difficulties are much more important to solve, for a project
which long ago entered the maintenance phase of its life cycle.

Thanks.



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-10-08  6:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-07  4:16 Proposal: make prog2 a macro Wilfred Hughes
2016-10-07  5:04 ` Tino Calancha
2016-10-07  7:46 ` John Wiegley
2016-10-07 20:34   ` Richard Stallman
2016-10-07  8:08 ` Tino Calancha
2016-10-08  2:12   ` Wilfred Hughes
2016-10-08  2:35     ` Noam Postavsky
2016-10-08  6:11       ` Eli Zaretskii
2016-10-08  3:40     ` Tino Calancha

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).