My guess is that you have defined the `setup-primitives` macro using `define-macro`. The issue is that `define-macro` operates directly on raw S-expression representations and produces a S-expression which will contain very inaccurate location information (it will tag the produced S-expression with the location of the call to `setup-primitives`).
To avoid this issue you need to write the macro using `define-syntax` which can preserve accurate location information.
Here is a simple macro defined using `define-macro`. Notice that when the division by zero happens the message contains the location of the macro call, even though the error happened in the expression (/ 1 0):
(define-macro mymac-dm (lambda (arg) `(let ((x (+ 1 ,arg))) (* x x))))
(mymac-dm (/ 1 0))
$ gsi macros.scm |cat *** ERROR IN "macros.scm"@6.1 -- Divide by zero (/ 1 0) ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ macros.scm ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ┃⋯ 5┃ 6┃(mymac-dm (/ 1 0)) ┃▔ 7┃ ┃⋯
Here is how the same macro can be defined using `define-syntax` which preserves the location information of the macro argument:
(define-syntax mymac-ds (lambda (stx) (let ((stx-code (##source-code stx))) (if (and (pair? stx-code) (eq? (##source-code (car stx-code)) 'mymac-ds) (pair? (cdr stx-code)) (null? (cddr stx-code))) (let ((arg (cadr stx-code))) `(let ((x (+ 1 ,arg))) (* x x))) (error "mymac-ds syntax error")))))
(mymac-ds (/ 1 0))
$ gsi macros.scm |cat *** ERROR IN "macros.scm"@13.11-13.18 -- Divide by zero (/ 1 0) ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ macros.scm ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ┃⋯ 12┃ 13┃(mymac-ds (/ 1 0)) ┃ ▔▔▔▔▔▔▔ 14┃
It is really tedious to parse the macro arguments using `##source-code`… a much better way is to use `syntax-rules` which will also work because the pattern matcher and expander used by `syntax-rules` preserves the location information (it is implemented using `##source-code`):
(define-syntax mymac-sr (syntax-rules () ((_ arg) (let ((x (+ 1 arg))) (* x x)))))
(mymac-sr (/ 1 0))
$ gsi macros.scm |cat *** ERROR IN "macros.scm"@7.11-7.18 -- Divide by zero (/ 1 0) ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ macros.scm ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ┃⋯ 6┃ 7┃(mymac-sr (/ 1 0)) ┃ ▔▔▔▔▔▔▔
Marc
On Sep 9, 2025, at 9:58 PM, Bradley Lucier via Gambit-list gambit-list@iro.umontreal.ca wrote:
Marc:
I have the following top-level definitions:
(pp CRsqrt)
(lambda (x) (let ((args (check-args 'CRsqrt (list x)))) (with-exception-catcher (lambda (err) (##raise-range-exception 1 CRsqrt x)) (lambda () (make-CR (computable-sqrt (car args)))))))
with the intention that if computable-sqrt raises an exception, it's handled here. computable-sqrt is defined as (x is a procedure of one argument):
(pp computable-sqrt)
(lambda (x) (cond ((table-ref #:table0 x #f)) (else (let ((#:result1 (if (or (eq? x computable-zero) (eq? x computable-one)) x (let ((x_0 (x 0))) (if (> x_0 1) (let ((s (two^p<abs_m ;;<<<<<<<<<<<<<<<<<<<<<<<<<<< x_0))) (computable-memoize (lambda (k) (if (<= (* 2 k) s) (int-sqrt (* (expt 2 (* 2 k)) x_0)) (let ((n (- k (quotient s 2)))) (int-sqrt (* (expt 2 (- (* 2 k) n)) (x n)))))))) ;;>>>>>>>>>>>>>>>>>>>>>>>>>>> (computable-memoize (lambda (k) (let ((x_k (x k))) (cond ((negative? ;;<<<<<<<<<<<<<<<<<<<<<<<<<<< x_k) (error "computable-sqrt: argument is negative: " x)) ((< 1 x_k) (let ((s (two^p<abs_m x_k))) (let ((n (quotient (- (* 3 k) s) 2))) (int-sqrt (* (expt 2 (- (* 2 k) n)) (x n)))))) (else (let ((x_2k (x (* 2 k)))) (if (negative? x_2k) (error "computable-sqrt: argument is negative: " x) (int-sqrt x_2k))))))))))))) ;;>>>>>>>>>>>>>>>>>>>>>>>>>>> (table-set! #:table0 x #:result1) #:result1))))
computable-memoize is:
(pp computable-memoize)
(lambda (x) (let ((result-so-far #f) (i 0)) (lambda (k) ((letrec ((loop (lambda () (if (and result-so-far (<= k (car result-so-far))) (arithmetic-shift (cdr result-so-far) (- k (car result-so-far))) (let ((k* (+ k (integer-length k)))) (let ((result (x k*))) (set! result-so-far (cons k* ;;<<<<<<<<<<<<<<<<<<<<<<<<<<< result)) ;;>>>>>>>>>>>>>>>>>>>>>>>>>>> (loop))))))) loop)))))
And if computable-sqrt raises an exception, it hits at the
(let ((result (x k*)))
in computable-memoize as
(CR->string (CRsqrt #e-1e-100000) 100000)
*** ERROR IN loop, "basics.scm"@114.1 -- computable-sqrt: argument is negative: #<procedure #5> ┏━━━━━━━━━━━━━━━━━━━ basics.scm ━━━━━━━━━━━━━━━━━━━ ┃⋯ 113┃ 114┃(setup-primitives) 115┃ ┃⋯
(setup-primitives) is a macro that defines computable-memoize and a few other macros.
So, with what should I surround the call to (x k*) in computable-memoize to send the exception up to CRsqrt?
Brad
Gambit-list mailing list -- gambit-list@iro.umontreal.ca To unsubscribe send an email to gambit-list-leave@iro.umontreal.ca