Debuging scope-related issues
(require debug-scopes) | package: debug-scopes |
#lang racket (require (for-syntax racket/base debug-scopes)) (define-syntax (foo stx) (displayln (+scopes stx)) (displayln (+scopes (datum->syntax #f 'no-scopes))) (displayln (+scopes (syntax-local-introduce #'here))) (print-full-scopes) #'(void)) (foo (list 123))
When using named scopes—
#lang racket (require (for-syntax (except-in racket/base syntax-local-introduce) debug-scopes debug-scopes/named-scopes)) (define-syntax (foo stx) (displayln (+scopes stx)) (displayln (+scopes (datum->syntax #f 'no-scopes))) (displayln (+scopes (syntax-local-introduce #'here))) (print-full-scopes) #'(void)) (foo (list 123))
> (require racket/trace (for-syntax racket/base racket/trace debug-scopes))
> (begin-for-syntax (define (maybe-syntax->scoped syn?) (if (syntax? syn?) (+scopes syn?) syn?)) (current-trace-print-args (let ([ctpa (current-trace-print-args)]) (lambda (s l kw l2 n) (ctpa s (map maybe-syntax->scoped l) kw l2 n)))) (current-trace-print-results (let ([ctpr (current-trace-print-results)]) (lambda (s l n) (ctpr s (map maybe-syntax->scoped l) n)))))
> (trace-define-syntax let (syntax-rules () [(_ ([x v]) e) ((lambda (x) e) v)])) > (let ([x 5]) (let ([y 120]) y))
>(let "(let⁰˙˙³ ((x⁰˙˙³ 5)) (let⁰˙˙³ ((y⁰˙˙³ 120)) y⁰˙˙³))ˢˡⁱ⁼²⁺ᵘˢᵉ⁼³")
<"((lambda⁰˙˙¹ (x⁰˙˙³) (let⁰˙˙³ ((y⁰˙˙³ 120)) y⁰˙˙³)) 5)ˢˡⁱ⁼²⁺ᵘˢᵉ⁼³"
>(let "(let⁰˙˙⁶⁻² ((y⁰˙˙⁶⁻² 120)) y⁰˙˙⁶⁻²)ˢˡⁱ⁼⁶⁺ᵘˢᵉ⁼")
<"((lambda⁰˙˙¹ (y⁰˙˙⁶⁻²) y⁰˙˙⁶⁻²) 120)ˢˡⁱ⁼⁶⁺ᵘˢᵉ⁼"
120
procedure
(print-full-scopes [reset?]) → void?
reset? : any/c = #t
This allows to get some extended information about the scopes in a summary table by calling print-full-scopes, while still getting short and readable display of syntax objects with +scopes.
After running (print-full-scopes), if reset? is true, then the scope counter is reset (and +scopes therefore starts numbering scopes starting from 0 again).
1 Hack for named scopes
(require debug-scopes/named-scopes/exptime) | |
package: debug-scopes |
Module scopes bear are annotated by Racket with the name of the module. As of December 2016, other scopes like macro scopesBoth the ones implicitly created when a macro is called, and the ones explicitly created via make-syntax-introducer are concerned by this or use-site scopes lack any form of annotation or naming.
procedure
(make-named-scope name)
→ (->* (syntax?) ([or/c 'add 'remove 'flip]) syntax?) name : (or/c string? symbol?)
procedure
(make-module-like-named-scope name)
→ (->* (syntax?) ([or/c 'add 'remove 'flip]) syntax?) name : (or/c string? symbol?)
1.1 Automatic use of named scopes
(require debug-scopes/named-scopes/override) | |
package: debug-scopes |
This module overrides define-syntax and syntax-local-introduce to automatically use a named macro scope. The use-site scope is not affected for now, as the original unnamed use-site scope from Racket benefits from special cooperation from definition contexts, which would be hard to achieve with the hack currently used to implement named scopes.
syntax
(define-syntax (name stx-arg) . body)
(define-syntax name value)
Note that this change only affects the scopes introduced by the overriden version of syntax-local-introduce, not the original syntax-local-introduce.
This means that if the macro calls a function defined in another file which uses the non-overidden version of syntax-local-introduce, both the original unnamed scope and the named scope may accidentally appear in the result. Macros defined using the overridden syntax-local-introduce should therefore take special care to always use the overridden version of syntax-local-introduce.
The use-site scope is not affected for now, as the original unnamed use-site scope from Racket benefits from special cooperation from definition contexts, which would be hard to achieve with the hack currently used to implement named scopes.
procedure
(syntax-local-introduce stx) → syntax?
stx : syntax?