Ok then, here are two simple examples of error traces.
In both examples we have the trace from common LISP and from racket.
In the first example I use a syntax proceedure as described in the guide 16.2.2 and as
shows up in my code. In this example both traces match. I did not have to use
syntax-case to get a trace.
In the second example common lisp gives a correct trace, but racket leaves a function
out of the trace back. Not a macro, a function. I show the macro involved implemented
in all three ways described in the guide, as a proceedure as per the first example, as
a syntax rule, and, yes, using syntax-case. In all three cases it appears that
racket leaves a function out of the trace, though common LISP does not.
In any case, functions missing from the trace are confusing to developers, as one
looks in the wrong place for the erros.
Well hope I got these examples right anyway. Apologies in advance if there is
an error in here. I hope you will point out where it is. ;-)
--------------------------------------------------------------------------------
1.1 in common LISP (gcl), error manifesting in well formed macro
bt-example.gcl:
(defmacro plus (x y) `(+ ,x ,y))
(defun f (x y) (g x y))
(defun g (x y) (plus x y))
>(load "bt-example.gcl")
Loading bt-example.gcl
Finished loading bt-example.gcl
T
>(f 3 2)
5
>(f 3 'a)
Error: TYPE-ERROR :DATUM A :EXPECTED-TYPE NUMBER
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by +.
TYPE-ERROR :DATUM A :EXPECTED-TYPE NUMBER
Broken at +. Type :H for Help.
1 Return to top level.
>>:bt
#0 + {loc0=3,loc1=a,loc2=type-error,loc3=nil,loc4=+,loc5="",loc6="",loc7=:datum,loc8=...} [ihs=6]
#1 G {} [ihs=5]
#2 F {} [ihs=4]
#3 EVAL {loc0=nil,loc1=nil,loc2=nil,loc3=(system:lambda-block f (x y) ...),loc4=3,loc5=a} [ihs=3]
NIL
>>
Ok, so it gives a back trace to the function that called the macro, and then to the
expanded function that had the error. All functions are mentioned, but the macro is not.
1.2. Same example in racket.
bt-example.rkt
#lang racket
(define-syntax (plus stx)
(let(
[datum (syntax->datum stx)]
)
(let(
[x (cadr datum)]
[y (caddr datum)]
)
(define program `(+ ,x ,y))
(datum->syntax stx program)
)))
(define (f x y) (g x y))
(define (g x y) (plus x y))
(f 3 2)
(f 3 'a)
§> racket -l errortrace -t "bt-example.rkt"
5
+: contract violation
expected: number?
given: 'a
argument position: 2nd
other arguments...:
3
errortrace...:
/home/deep/3_doc/racket_err_mess/bt-example.rkt:15:16: (g x y)
/home/deep/3_doc/racket_err_mess/bt-example.rkt:19:0: (f 3 (quote a))
context...:
/home/deep/3_doc/racket_err_mess/bt-example.rkt:15:0: f
/home/deep/3_doc/racket_err_mess/bt-example.rkt: [running body]
§>
Similar result as per gcl. All functions mentioned, no mention of the
syntax transformer.
--------------------------------------------------------------------------------
2.1 in common LISP, this time the well formed macro calls a well formed function,
where an error manifests:
bt2-example.gcl:
(defun h (x y) (+ x y))
(defmacro plus (x y) `(h ,x ,y))
(defun f (x y) (g x y))
(defun g (x y) (plus x y))
>(load "bt2-example.gcl")
Loading bt2-example.gcl
Finished loading bt2-example.gcl
T
>(f 3 2)
5
>(f 3 'a)
Error: TYPE-ERROR :DATUM A :EXPECTED-TYPE NUMBER
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by +.
TYPE-ERROR :DATUM A :EXPECTED-TYPE NUMBER
Broken at +. Type :H for Help.
1 Return to top level.
>>:bt
#0 + {loc0=3,loc1=a,loc2=type-error,loc3=nil,loc4=+,loc5="",loc6="",loc7=:datum,loc8=...} [ihs=7]
#1 H {} [ihs=6]
#2 G {} [ihs=5]
#3 F {} [ihs=4]
#4 EVAL {loc0=nil,loc1=nil,loc2=nil,loc3=(system:lambda-block f (x y) ...),loc4=3,loc5=a} [ihs=3]
NIL
>>
All functions cited. F->G->H->+ then blam. The macro is not cited.
2.1 now in racket
bt2-example.rkt
#lang racket
(define (h x y) (+ x y))
(define-syntax (plus stx)
(let(
[datum (syntax->datum stx)]
)
(let(
[x (cadr datum)]
[y (caddr datum)]
)
(define program `(h ,x ,y))
(datum->syntax stx program)
)))
(define (f x y) (g x y))
(define (g x y) (plus x y))
(f 3 2)
(f 3 'a)
§> racket -l errortrace -t bt2-example.rkt
5
+: contract violation
expected: number?
given: 'a
argument position: 2nd
other arguments...:
3
errortrace...:
/home/deep/3_doc/racket_err_mess/bt2-example.rkt:3:16: (+ x y)
/home/deep/3_doc/racket_err_mess/bt2-example.rkt:21:0: (f 3 (quote a))
context...:
/home/deep/3_doc/racket_err_mess/bt2-example.rkt:3:0: h
/home/deep/3_doc/racket_err_mess/bt2-example.rkt: [running body]
§>
f -> + and blam .. and nice to know + is inside of 'h'. ah .. but what happened to g?
Is leaving g out of the trace an error? Because when I go looking for an invocation
of 'h' (or '+') inside of 'f', but in fact it is inside of 'g'.
2.2 racket using syntax rules, same result, no mention of g in the trace
bt2-ex-rules.rkt:
(define (h x y) (+ x y))
(define-syntax plus
(syntax-rules()
[(plus x y) (h x y)]
))
(define (f x y) (g x y))
(define (g x y) (plus x y))
(f 3 2)
(f 3 'a)
racket -l errortrace -t bt2-ex-rules.rkt
5
+: contract violation
expected: number?
given: 'a
argument position: 2nd
other arguments...:
3
errortrace...:
/home/deep/3_doc/racket_err_mess/bt2-ex-rules.rkt:3:16: (+ x y)
/home/deep/3_doc/racket_err_mess/bt2-ex-rules.rkt:15:0: (f 3 (quote a))
context...:
/home/deep/3_doc/racket_err_mess/bt2-ex-rules.rkt:3:0: h
/home/deep/3_doc/racket_err_mess/bt2-ex-rules.rkt: [running body]
2.3 racket using syntax case, same result, no mention of g in the trace:
bt2-ex-case.rkt:
#lang racket
(define (h x y) (+ x y))
(define-syntax (plus stx)
(syntax-case stx ()
[(plus x y) #'(h x y)]
))
(define (f x y) (g x y))
(define (g x y) (plus x y))
(f 3 2)
(f 3 'a)
§> racket -l errortrace -t bt2-ex-case.rkt
5
+: contract violation
expected: number?
given: 'a
argument position: 2nd
other arguments...:
3
errortrace...:
/home/deep/3_doc/racket_err_mess/bt2-ex-case.rkt:3:16: (+ x y)
/home/deep/3_doc/racket_err_mess/bt2-ex-case.rkt:15:0: (f 3 (quote a))
context...:
/home/deep/3_doc/racket_err_mess/bt2-ex-case.rkt:3:0: h
/home/deep/3_doc/racket_err_mess/bt2-ex-case.rkt: [running body]