Lisp source code rewriting system

I would like to take the Emacs Lisp code, which was extended by a macro, and unmacro extends it. I requested this on the Emacs forum without success. See: https://emacs.stackexchange.com/questions/35913/program-rewriting-systems-unexpanded-a-defmacro-given-a-list-of-macros-to-undo

However, one would think that such a conversion of S-expressions is similar to up Lisp alley. And defmacro, I believe, is available in Lisp, as in Emacs Lisp.

So, of course, there are program conversion systems or term rewrite systems that can be adapted here.

Ideally, in certain situations, such a tool could work directly with defmacroto search for and replace its template. However, even if I need to come up with a specific search and replace the templates manually to add transformations to the system, the presence of such a structure for work would still be useful

Summary of the results so far: Although there have been a few answers that explore interesting possibilities, there is nothing final right now. Therefore, I believe that it is better to leave it open. I will summarize some suggestions. (I supported all the answers, which were actually answers, not a comment about complexity.)

Firstly, many people believe that a special form of macro only makes an extension, or, as Drew put it:

(.. , Lisp). - - .

-, , phils post, , Emacs: pcase. . - , , .

FTOC, Franz Lisp Common Lisp; googling comp.lang.lisp

Lisp optima fare-quasiquote. , , , , . , , .)

: , . ( , , , .)

, , . , , Emacs Lisp. ( , , Emacs Lisp, ). Emacs Lisp , clojure Lisp. , Sylwester, , , , . , - Emacs Lisp "" "".

+4
6

30- - , macrolet.

( defmacro, Common Lisp, macrolet. macrolet - .)

- , , . , , .

( ) Franz Lisp Common Lisp, Lisp + Prolog-machine. Lisp , Common Lisp ( ) .

, , Lisp (), , , , . , - , , , .

, , .

, . , , .., , , , (, , ). Franz Common - .

Common Lisp. , . , , Franz Lisp Common Lisp.

(.. , Lisp). - - .

Franz- Lisp - Common- Lisp. , , ( ) /, .

FTOC. , , , , (ftoc lisp). ( Lisp, , . Lisp Lisp .)

!

+4

, , . lisp Turing, , .

, . defmacros backquoted . , , .

, , . ( emacs- lisp -) .

+3

Emacs Lisp, , unmacro .

, . , .

, .

, , . , , , . .

, . , , , ; , , . , , .

, . , , .

, , - . , , , , :

  • (if (not <cond>) <expr>) (if (not <cond>) (progn <&expr>)) (unless <cond> <&expr>) , null not. nil - , . , , , .. , , Lisp , , Emacs, .

  • (if <cond> <expr>) (if <cond> (progn <&expr>)) (when <cond> <&expr>)

  • , cond . cond .

, , , () ().

- optima , , , .

optima , , , , .

, , , , , . , ( , ), , , , (s-).

, , , , , , .

, , , .

: trie .

- , . , , , , -, .

, , , - . , , , , - , - .

, S- up Lisp alley. defmacro, , Lisp, Emacs Lisp.

, , , .

defmacro . Lisp , , .

1 , ( macrolet) .. .


1.

Lisp , , , , .

:

(defmacro my-macro-1 ()
  `1)

(defmacro my-macro-2 ()
  `(my-function (my-macro-1)))

(defun my-function (n)
  (* n 100))

(macrolet ((my-macro-1 ()
             `2))
  (flet ((my-function (n)
           (* n 1000)))
    (my-macro-2)))

(my-function (my-macro-2)), (my-function 2). 2000.

- :

(defmacro my-macro-2 ()
  ;; capture global bindings of my-macro-1 and my-function-1 by name
  (flet ((my-macro-1-global (form env)
           (funcall (macro-function 'my-macro-1) form env))
         (my-function-global (&rest args)
           ;; hope the compiler can optimize this
           (apply 'my-function args)))
    ;; store them globally in uninterned symbols
    ;; hopefully, no one will mess with them
    (let ((my-macro-1-symbol (gensym (symbol-name 'my-macro-1)))
          (my-function-symbol (gensym (symbol-name 'my-function))))
      (setf (macro-function my-macro-1-symbol) #'my-macro-1-global)
      (setf (symbol-function my-function-symbol) #'my-function-global)
      `(,my-function-symbol (,my-macro-1-symbol)))))

100.

Common Lisp , , , undefined, (re) common-lisp, . .

+2

, , . : , , , , - , , . , sha, SHA- , . , - - , . , , . git, .

, , , , .

, (, ), , (, cond vs if) , , , (, loop, do backquote). , - , , , ). , (, Id), - , , . save-excursion with-XXXX. , , , ( gensym), . , defmacro , , . , , , (I.e. begin/end) . . , , ( ) .

, , , , -. elisp, , , , . , , let let, - goto, elisp .

, , , , -, Emacs, , , . , , elisp, , Emacs . Emacs , Emacs , Emacs . , , - Emacs , .

, , elisp, , , . , Lisp , Lisp, , , , , , . C. , , .

, , , ( Lisp , ) , , , . , , , . , . , , . !

: , Lisp, , , - . , , , .

+2

, , , unmacroing. , cond if, if, if cond, , . , .

, if cond, , , progn, , cond , . , .

+1

, , , , , , ; pcase Emacs .

Here is a simple example that I might think:

Regarding the definition when:

(defmacro when (cond &rest body)
  (list 'if cond (cons 'progn body)))

We can transform the code using a template pcase, for example:

(let ((form '(if (and foo bar baz) (progn do (all the) things))))
  (pcase form
    (`(if ,cond (progn . ,body))
     `(when ,cond ,@body))
    (_ form)))

=> (when (and foo bar baz) do (all the) things)

Obviously, if macro definitions change, then your templates will stop working (but this is a pretty safe kind of failure).

Caution: this is the first time I wrote a form pcaseand I don’t know what I don’t know. It seems to be working as intended.

+1
source

Source: https://habr.com/ru/post/1688837/


All Articles