Common Lisp Macro Generating Macros,用于评估参数

时间:2018-03-27 21:12:29

标签: macros common-lisp

意向:

我正在尝试使用宏窗体生成宏:

(make-type "int32" 32)

会产生:

(defmacro make-int32t (name)
  `(quote (:type 'int32t :bit-length 32 :name ,name)))

这个生成的宏产生类似的东西:

(make-int32t "myvar")

(:TYPE 'INT32T :BIT-LENGTH 32 :NAME "myvar")

问题:

我正在努力解决如何使宏产生引导的反引号和逗号。

这就是我所拥有的:

(defmacro make-type (type-name bit-length)
  (let*
      ((make-name  (concatenate 'string "make-" type-name))
       (mac-name (intern make-name)))
       `(defmacro ,mac-name (name)
     '(quote (:type ,type-name :bit-length ,bit-length :name "substitued")))))
 ; "substituted" ideally is something like ,name

如果我宏观扩展我得到:

 (macroexpand-1 '(make-type "int32" 32))

(DEFMACRO |make-int32| (NAME)
  ''(:TYPE "int32" :BIT-LENGTH 32 :NAME "substitued"))

如果我尝试使用宏,我会得到:

(make-type "int44" 44)
; in: MAKE-TYPE "int44"
;     (SB-INT:NAMED-DS-BIND (:MACRO |make-int44| . DEFMACRO)
;         (NAME)
;         (CDR #:EXPR)
;       (BLOCK |make-int44| ''(:TYPE "int44" :BIT-LENGTH 44 :NAME "substitued")))
; --> SB-INT:BINDING* 
; ==>
;   (LET* ((#:G0 (SB-C::CHECK-DS-LIST (CDR #:EXPR) 1 1 '(# NAME)))
;          (NAME (POP #:G0)))
;     (BLOCK |make-int44| ''(:TYPE "int44" :BIT-LENGTH 44 :NAME "substitued")))
; 
; caught STYLE-WARNING:
;   The variable NAME is defined but never used.
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition
WARNING: redefining COMMON-LISP-USER::|make-int44| in DEFMACRO

|make-int44|

但是如果我尝试使用宏,则不会定义它。

(make-int44 "myvar")
The function COMMON-LISP-USER::MAKE-INT44 is undefined.

问题

1)如何用"substituted"

替换,name

2)如何正确地做到这一点?

编辑:我有一个错字:MARCO - >宏,所以我相应地改变了问题

1 个答案:

答案 0 :(得分:1)

谢谢大家的意见。为了结束这一点,我将根据您的意见发布问题的答案:

(defmacro make-type (type-name bit-length)
  (let* ((make-name (concatenate 'string "DEFINE-" (string-upcase type-name)))
         (mac-name  (intern make-name)))
      `(defmacro ,mac-name (name)
         `(quote (:type       ,,type-name
                  :bit-length ,,bit-length
                  :name       ,name)))))

可以用作:

* (define-type "int16" 16)

DEFINE-INT16
* (DEFINE-int16 "myvar")

(:TYPE "int16" :BIT-LENGTH 16 :NAME "myvar")