macro's strange error and messages

26 views
Skip to first unread message

Minoru

unread,
Jun 27, 2026, 1:00:40 AM (3 days ago) Jun 27
to Extempore
Hi Ben,

Since ver 0.9.4, I have been struggling with strange error and messages for macro functions.

These are very simplified funcs for explanations ....

;; this is ok without any troubles.
(define-macro (mmt1 . args)
  `(list ',args))

(mmt1 10 20) ;->((10 20))

;; this is it !
;; mmt2 is defined, then, it works well without error !
;; but moving the cursor onto "mmt2" in definition or execution/evaluation S-exp,
;; "error" is shown in message place, and warning?? messages in the shell window, too.

(define-macro (mmt2 . args)
  (let ((v1 (gensym)))
    `(list ',args)))

(mmt2 10 2 3) ; -> ((10 2 3))

;; warning messages

;cadadr argument, (let ((v1 (gensym))) (#_list-values 'list (#_list-values #_quote args))), is a pair but should be a pair whose cdadr is also a pair
;    mmt2
;    , line 0, position: 85
;xtmdoc-scheme-macro-handler: (cons 'args ... ; name-sym: mmt2
;xtmdoc-scheme-macro-handler: ((list 'type...
;xtmdoc-documentation-function: (cons 'xtm... ; sym: mmt2
;(caddr (get-closure-code (eval name-sym)))
; ..... and so on .....


;; then evaluating this returns error, but,
;; (#_list-values #_quote args) should be
;; (#_list-values (#_quote args))

;; this causes an error
(cdadr (let ((v1 (gensym))) (#_list-values 'list (#_list-values #_quote args))))

;; this returns NIL without error because fixed
(cdadr (let ((v1 (gensym))) (#_list-values 'list (#_list-values (#_quote args)))))

;; If this mmt2 is expanded like above, it doesn't work !
;; Howerver, mmt2 works without no error !
;; So, what is this warning ????  

(macro-expand '(mmt2 10 2 3))
;; returns ok,  (list (#_quote (10 2 3)))

(list (#_quote (10 2 3)))
;; -> (10 2 3)

(mmt2 10 2 3)
;; -> ((10 2 3))


;; but the next mmt2-b func has no trouble, no error, no warning when the cursor moves onto it.
;; just shows "scheme macro mmt2-b let" as usual ...
;; I think xtmdoc funcs work has some ......
;;
;; the difference is the place of quasiquote,
;; but comparing with not a few funcs, there is one that has no this strange phenomenon, though
;; it has the quqsiquote start position at not the head of body.

(define-macro (mmt2-b . args)
  `(let ((v1 (gensym)))
     (list ',args)))

(mmt2-b 10 2 3)


;; your some macro funcs as belows, too .....
;; Moving the cursor on to macro func name atom after we defined it,
;; it shows error and warning messages ...

(define-macro (cosr . __cosr-rest)
  (let ((args (cons 'cosr __cosr-rest)))
    (if (> (length args) 4)
        `(+ ,(caddr args) (* ,(cadddr args) (cos (* TWOPI (+ beat ,(cadr args)) ,(car (cddddr args))))))
        `(+ ,(cadr args) (* ,(caddr args) (cos (* TWOPI beat ,(cadddr args))))))))


(define-macro (dotill predicate expression . args)
   (let ((max-iterations (if (null? args) 100000000 (car args))))
      `(let impsym38479k ((cnt 0))
    (let ((value ,expression))
       (if ,predicate
     value
     (if (> cnt ,max-iterations)
         (begin (log-info "Dropping out after max-iterations")
          'failed)
         (impsym38479k (+ cnt 1))))))))

(define-macro (:> tag . args)
  (let ((tagtime (string->symbol (string-append (symbol->string tag) "_tagtime"))))
    (if (not (defined? tagtime)) (eval `(define ,tagtime (now)) (interaction-environment)))
    (if (< (eval tagtime) (- (now) (* 2 *second*)))
        (eval `(define ,tag #f) (interaction-environment)))
    (if (and (defined? tag) (closure? (eval tag)))
        `(rmap-loop-runner ,tag ,tagtime modify ,@args)
        `(rmap-loop-runner ,tag ,tagtime start ,@args))))

;; of course there are not a few others that show this phenomenon, too

;; What's going on ????
;; xtmdoc funcs can't work well since s7 ?????

;; xtmdoc funcs are in  .../extempore-aarch64-v0.10.0/runtime/xtc-bind.xtm

(define mm1
  (lambda (x1 x2) x1))

(mm1 10 20)

(xtmdoc-builtin-handler 'mm1) ;error
(xtmdoc-builtin-handler "mm1") ;error
(xtmdoc-builtin-handler mm1) ;error

(xtmdoc-closure-handler mm1) ;error

(xtmdoc-scheme-function-handler 'mm1)
;; -> ((category . "scheme closure") (name . "mm1") (args x1 x2) (type) (docstring))

(xtmdoc-documentation-function "mm1")
;; -> scheme closure mm1 (x1 x2)
;; usually displayed one, when moving the cursor onto "mm1" in definition or S-exp like
(mm1 1 2)

(xtmdoc-scheme-function-handler 'mmt2)
;; -> ((category . "scheme closure") (name . "mmt2") (args . #f) (type) (docstring))

;; oh this is it!
(xtmdoc-documentation-function "mmt2")
;; -> error
;cadadr argument, (let ((v1 (gensym))) (#_list-values 'list (#_list-values #_quote args))), is a pair but should be a pair whose cdadr is also a pair
;    mmt2
;    , line 0, position: 38
;; xtmdoc-scheme-macro-handler: (cons 'args ... ; name-sym: mmt2
;; xtmdoc-scheme-macro-handler: ((list 'type...
;; xtmdoc-documentation-function: (cons 'xtm... ; sym: mmt2

Minoru

unread,
Jun 27, 2026, 1:01:36 AM (3 days ago) Jun 27
to Extempore
Hi Ben,

This is macro func that works without any trouble in ver 0.7, 0.8.9, but it has been showing above "error and messeges" since 0.9.4 ..... when the cursor is moved onto the macro func name.

(sys:load "libs/core/pc_ivl.xtm")

(define-macro (mkchordlist . lis)
  (let ((p (gensym)))
    `(map (lambda (,p)
            (set! ,p (cadr ,p))
            (eval (list 'pc:make-chord (car ,p) (cadr ,p) (caddr ,p) (cadddr ,p))))
          ',lis)))

(define *scl1* '(0 4 7))
(define *scl2* '(2 5 9))
(define *low* '(random '(36 60)))
(mkchordlist '(48 60 2 '(0 4 7))) ;ok
(mkchordlist '(60 72 (random 1 5) *scl1*) '(60 72 2 *scl2*)) ;ok
(mkchordlist '(60 72 (random '(1 3)) '(0 4 7)) '(60 72 (random 1 4) *scl1*)) ;ok
(mkchordlist '((eval *low*) 72 (random '(1 3)) '(0 4 7)) '(60 72 (random 1 4) *scl1*)) ;ok


;; oh this too !
;; the same messages and wanings is shown when I move the cursor on to atom 'mkchordlist'.
(xtmdoc-documentation-function "mkchordlist")
;;  -> error
;cadadr argument, (let ((p (gensym))) (#_list-values 'map (#_list-values 'lambda (#_list-values p) (#_list-values 'set! p (#_list-values 'cadr p)) (#_list-values 'eval (#_list-values 'list ''pc:make-chord (#_list-values 'car p) (#_list-values 'cadr p) (#_list-values 'caddr p) (#_list-values 'cadddr p)))) (#_list-values #_quote lis))), is a pair but should be a pair whose cdadr is also a pair
;    mkchordlist
;    , line 0, position: 45
;; xtmdoc-scheme-macro-handler: (cons 'args ... ; name-sym: mkchordlist
;; xtmdoc-scheme-macro-handler: ((list 'type...
;; xtmdoc-documentation-function: (cons 'xtm... ; sym: mkchordlist
;;  ..... and so on ....


;; about cosr, too
(xtmdoc-documentation-function "cosr")
;;  -> error
;cadadr argument, (let ((args (cons 'cosr __cosr-rest))) (if (> (length args) 4) (#_list-values '+ (caddr args) (#_list-values '* (cadddr args) (list-values 'cos (#_list-values '* 'TWOPI (#_list-values '+ 'beat (cadr args)) (car (cddddr args)))))) (#_list-values '+ (cadr args) (#_list-values '* (caddr args) (#_list-values 'cos (#_list-values '* 'TWOPI 'beat (cadddr args))))))), is a pair but should be a pair whose cdadr is also a pair
;    cosr

;    , line 0, position: 38
;; xtmdoc-scheme-macro-handler: (cons 'args ... ; name-sym: cosr

(cadadr (let ((args (cons 'cosr __cosr-rest))) (if (> (length args) 4) (#_list-values '+ (caddr args) (#_list-values '* (cadddr args) (list-values 'cos (#_list-values '* 'TWOPI (#_list-values '+ 'beat (cadr args)) (car (cddddr args)))))) (#_list-values '+ (cadr args) (#_list-values '* (caddr args) (#_list-values 'cos (#_list-values '* 'TWOPI 'beat (cadddr args))))))))
;; -> error, ;unbound variable __cosr-rest
;; "__cosr-rest" is unbound in this scope, but ........

(cdadr (let ((args (cons 'cosr __cosr-rest))) (if (> (length args) 4) (#_list-values '+ (caddr args) (#_list-values '* (cadddr args) (list-values 'cos (#_list-values '* 'TWOPI (#_list-values '+ 'beat (cadr args)) (car (cddddr args)))))) (#_list-values '+ (cadr args) (#_list-values '* (caddr args) (#_list-values 'cos (#_list-values '* 'TWOPI 'beat (cadddr args))))))))
;; -> error, ;unbound variable __cosr-rest
;; "__cosr-rest" is unbound in this scope, but ........


It seems like that xtmdoc func, in particular, which has to do with macro func doesn't work well since s7.

xtmdoc-documentation-function calls xtmdoc-scheme-macro-handler

;; so I did ...

(xtmdoc-scheme-macro-handler 'mmt2)
;; showed 'error' and

;cadadr argument, (let ((v1 (gensym))) (#_list-values 'list (#_list-values #_quote args))), is a pair but should be a pair whose cdadr is also a pair
;    mmt2
;    , line 0, position: 35

;xtmdoc-scheme-macro-handler: (cons 'args ... ; name-sym: mmt2

;; oh this is it !
;; then I found definition of 'xtmdoc-scheme-macro-handler' ...

(define xtmdoc-scheme-macro-handler
  (lambda (name-sym)
    (list
     '(category . "scheme macro")
     (cons 'name (symbol->string name-sym))
     (cons 'args (cadadr (caddr (get-closure-code (eval name-sym)))))  ; <<<-------
     (list 'type)
     (list 'docstring))))

(get-closure-code (eval 'mmt2)) ; or
(get-closure-code mmt2)
;; -> (macro args (let ((v1 (gensym))) (#_list-values (#_quote list) (#_list-values #_quote args))))
;; I think this is not correct,

;; (#_list-values #_quote args) should be
;; (#_list-values (#_quote args))

(cadadr (caddr (get-closure-code mmt2)))
;; returns 'error' and these warnings we see often till now  ....

;;cadadr argument, (let ((v1 (gensym))) (#_list-values 'list (#_list-values #_quote args))), is a pair but should be a pair whose cdadr is also a pair  
;;    (get-closure-code mmt2)
;;    , line 0, position: 39


;; "should be a pair whose cdadr is also a pair " so I did it,


(cdadr (let ((v1 (gensym))) (#_list-values 'list (#_list-values #_quote args))))
;; -> error and
;'args is unbound in (#_list-values #_quote args)
;    (#_list-values #_quote args)
;    , line 0, position: 80
;(#_list-values #_quote args)

;; then use fixed one

(cdadr (let ((v1 (gensym))) (#_list-values 'list (#_list-values (#_quote args)))))
;; -> NIL without any errors


;; in addition to above examples ...

(define-macro (mmt2 . args)
  (let ((v1 (gensym)))
    `(list ',args)))

(mmt2 10 2 3) ;ok ((10 2 3))


(macro-expand '(mmt2 10 2 3))
;; -> (list (#_quote (10 2 3)))

;; this means it should be not (#_list-values #_quote args) but (#_list-values (#_quote args))

It seems like that 'get-closure-code' doesn't work well when it handles macro function which has quasiquote in s7 ?????

I looked up a scheme source code of 'get-closure-code' in ver 0.7, 0.89, 0.9 and 0.10.0, but nothing, maybe it's built-in function ???

Anyway, I'm stuck now !

Am I wrong ?
What do you think ?


2026年6月27日土曜日 14:00:40 UTC+9 Minoru:

Ben Swift

unread,
Jun 27, 2026, 1:47:01 AM (3 days ago) Jun 27
to extemp...@googlegroups.com
Hi Minoru,

Your macros are all fine, and get-closure-code is fine too. Nothing you wrote is wrong, and nothing needs changing on your end. The bug is entirely in one Extempore function, xtmdoc-scheme-macro-handler (in runtime/xtc-bind.xtm), which is what the editor calls to build the little documentation popup when your cursor lands on a symbol.

That handler pulls a macro's argument list out with this walk:

(cadadr (caddr (get-closure-code (eval name-sym))))

That (cadadr (caddr ...)) was written years ago against TinyScheme's internal macro representation. Since 0.9.4 we're on the s7 Scheme, where get-closure-code is an alias for s7's procedure-source, and a macro's source comes back in the shape:

(macro <arglist> body...)

So the argument list you actually want is just the cadr. The old walk instead dives into the body and assumes the body's first form is the quasiquote. That assumption holds for mmt1 and mmt2-b (the backtick is the whole body), so they don't error --- though they quietly return rubbish rather than the real args. The moment a macro wraps its template in a let (your mmt2, plus cosr, dotill, mkchordlist, and so on), the walk lands on the let binding list, whose cdadr is () rather than a pair, and you get the error you saw.

The (#_list-values #_quote args) vs (#_list-values (#_quote args)) thing you chased down is a red herring, by the way --- that's just how s7 prints the already-expanded quasiquote internally. It's never re-read or re-evaluated, so it does no harm; it just looks alarming.

The fix is a one-liner --- replace that line with:

(cons 'args (cadr (get-closure-code (eval name-sym))))

I've committed this to master. It fixes the crash and also the silently-wrong args for the mmt1-style cases. I've run every macro and closure in the standard runtime (a couple of thousand symbols) back through the documentation lookup and they all resolve cleanly now.

Because xtc-bind.xtm is loaded live from disk at startup (it's interpreted Scheme, not part of the AOT-compiled cache), you don't need to rebuild anything to pick this up --- just update that one file from the latest source, or wait for the next release, which won't be far off.

Cheers,
Ben
>--
>You received this message because you are subscribed to the Google Groups "Extempore" group.
>To unsubscribe from this group and stop receiving emails from it, send an email to extemporelan...@googlegroups.com.
>To view this discussion visit https://groups.google.com/d/msgid/extemporelang/12ad2be5-fc7d-4cd2-8984-eef4313a8e1bn%40googlegroups.com.


--

Cheers,
Ben

Minoru

unread,
Jun 27, 2026, 5:14:16 AM (3 days ago) Jun 27
to Extempore
Hi Ben,

Thank you so much again !
I fixed 'xtmdoc-scheme-macro-handler' as you say, it's works well !


(define xtmdoc-scheme-macro-handler
  (lambda (name-sym)
    (list
     '(category . "scheme macro")
     (cons 'name (symbol->string name-sym))
     ;; 2026-06-27(Sat) 17:10 by minoru
     ;;   fixed by Ben
     ;; (cons 'args (cadadr (caddr (get-closure-code (eval name-sym)))))
     (cons 'args (cadr (get-closure-code (eval name-sym)))) ; <------------- by Ben
     (list 'type)
     (list 'docstring))))

I'm very glad to be released from some strange error messages !

Thank you very much !

2026年6月27日土曜日 14:47:01 UTC+9 ben:

Minoru

unread,
Jun 28, 2026, 1:50:16 AM (yesterday) Jun 28
to Extempore
Hi Ben,

Thanks, ver 0.10.1  !!


2026年6月27日土曜日 18:14:16 UTC+9 Minoru:
Reply all
Reply to author
Forward
0 new messages