Added the macro stepper

svn: r3987

original commit: d91e2b45022c0c043578a5f08b152825db417c07
This commit is contained in:
Ryan Culpepper 2006-08-08 20:32:58 +00:00
commit 06aad5203a
29 changed files with 3924 additions and 0 deletions

View File

@ -0,0 +1,8 @@
(module expand mzscheme
(require "view/gui.ss")
(provide expand/step)
(define (expand/step stx)
(go stx))
)

View File

@ -0,0 +1,6 @@
(module info (lib "infotab.ss" "setup")
(define name "Macro Debugger")
(define tools '(["tool.ss"]))
(define tool-names '("Macro Stepper"))
(define doc.txt '"doc.txt"))

View File

@ -0,0 +1,142 @@
(module context mzscheme
(require (lib "stx.ss" "syntax"))
(provide (struct ref (n))
(struct tail (n))
path-get
pathseg-get
path-replace
pathseg-replace
find-subterm-paths)
;; A Path is a (list-of PathSeg)
;; where the PathSegs are listed outermost to innermost
;; for example: (path-get #'((a b) (c d)) (list (make-ref 0) (make-ref 1))) = #'b, not #'c
;; A PathSeg is one of:
;; - (make-ref number)
;; - (make-tail number)
(define-struct pathseg () #f)
(define-struct (ref pathseg) (n) #f)
(define-struct (tail pathseg) (n) #f)
;; path:ref->splicing-tail : PathSeg -> ???
;; ????
(define (path:ref->splicing-tail path)
(unless (ref? path)
(raise-type-error 'path:ref->splicing-tail "ref path" path))
(make-tail (sub1 (ref-n path))))
;; path-get : syntax Path -> syntax
(define (path-get stx path)
(let loop ([stx stx] [path path])
(cond [(null? path) stx]
[(pair? path)
(loop (pathseg-get stx (car path)) (cdr path))]
[else
(error 'path-get "bad path: ~s" path)])))
;; pathseg-get : syntax PathSeg -> syntax
(define (pathseg-get stx path)
(cond [(ref? path) (pathseg-get/ref stx (ref-n path))]
[(tail? path) (pathseg-get/tail stx (tail-n path))]))
;; pathseg-get/ref : syntax number -> syntax
(define (pathseg-get/ref stx0 n0)
(let loop ([n n0] [stx stx0])
(unless (stx-pair? stx)
(error 'pathseg-get "ref path out of bounds for syntax: ~s, ~s"
n0
(syntax-object->datum stx0)))
(if (zero? n)
(stx-car stx)
(loop (sub1 n) (stx-cdr stx)))))
;; pathseg-get/tail : syntax number -> syntax
(define (pathseg-get/tail stx0 n0)
(let loop ([n n0] [stx stx0])
(unless (stx-pair? stx)
(error 'pathseg-get "tail path out of bounds for syntax: ~s, ~s" n0 stx0))
(if (zero? n)
(stx-cdr stx)
(loop (sub1 n) (stx-cdr stx)))))
;; path-replace : syntax Path syntax -> syntax
(define (path-replace stx path x)
(cond [(null? path) x]
[(pair? path)
(let ([pathseg0 (car path)])
(pathseg-replace stx
pathseg0
(path-replace (pathseg-get stx pathseg0)
(cdr path)
x)))]
[else
(error 'path-replace "bad path: ~s" path)]))
;; pathseg-replace : syntax PathSeg syntax -> syntax
(define (pathseg-replace stx pathseg x)
(cond [(ref? pathseg) (pathseg-replace/ref stx (ref-n pathseg) x)]
[(tail? pathseg) (pathseg-replace/tail stx (tail-n pathseg) x)]
[else (error 'pathseg-replace "bad path: ~s" pathseg)]))
;; pathseg-replace/ref : syntax number syntax -> syntax
(define (pathseg-replace/ref stx0 n0 x)
(let loop ([n n0] [stx stx0])
(unless (stx-pair? stx)
(error 'pathseg-replace "ref path out of bounds for syntax: ~s, ~s" n0 stx0))
(if (zero? n)
(stx-replcar stx x)
(stx-replcdr stx (loop (sub1 n) (stx-cdr stx))))))
;; pathseg-replace/tail : syntax number syntax -> syntax
(define (pathseg-replace/tail stx0 n0 x)
(let loop ([n n0] [stx stx0])
(unless (stx-pair? stx)
(error 'pathseg-replace "tail path out of bounds for syntax: ~s, ~s" n0 stx0))
(if (zero? n)
(stx-replcdr stx x)
(stx-replcdr stx (loop (sub1 n) (stx-cdr stx))))))
;; stx-replcar : syntax syntax -> syntax
(define (stx-replcar stx x)
(cond [(pair? stx)
(cons x (cdr stx))]
[(syntax? stx)
(datum->syntax-object stx (cons x (stx-cdr stx)))]
[else (raise-type-error 'stx-replcar "stx-pair" stx)]))
;; stx-replcdr : syntax syntax -> syntax
(define (stx-replcdr stx x)
(cond [(pair? stx)
(cons (car stx) x)]
[(and (syntax? stx) (pair? (syntax-e stx)))
(datum->syntax-object stx (cons (stx-car stx) x))]
[else (raise-type-error 'stx-replcdr "stx-pair" stx)]))
(define (sd x)
(syntax-object->datum (datum->syntax-object #f x)))
;;=======
;; find-subterm-paths : syntax syntax -> (list-of Path)
(define (find-subterm-paths subterm term)
(let outer-loop ([term term])
(cond [(eq? subterm term)
(list null)]
[(stx-pair? term)
;; Optimized for lists...
(let loop ([term term] [n 0])
(if (stx-pair? term)
(let* ([seg0 (make-ref n)])
(append (map (lambda (p) (cons seg0 p)) (outer-loop (stx-car term)))
(if (eq? subterm (stx-cdr term))
(list (list (make-tail n)))
(loop (stx-cdr term) (add1 n)))))
(let ([seg0 (make-tail n)])
(map (lambda (p) (cons seg0 p))
(outer-loop term)))))]
;; FIXME: more structured cases here: box, vector, ...
[else null])))
)

View File

@ -0,0 +1,160 @@
(module deriv-c mzscheme
(provide (all-defined))
;; A Derivation is either
;; - a PRule
;; - (make-mrule syntax syntax Transformation Derivation)
;; - (make-lift-deriv syntax syntax Derivation syntax Derivation)
(define-struct deriv (e1 e2) #f)
(define-struct (mrule deriv) (transformation next) #f)
(define-struct (lift-deriv deriv) (first lift-stx second) #f)
;; A Transformation is
;; (make-transformation syntax syntax (listof identifier) syntax syntax (listof LocalAction))
;; - resolves is the list of identifiers resolved by the macro keyword
;; - me1 is the marked version of the input syntax
;; - me2 is the marked version of the output syntax
(define-struct transformation (e1 e2 resolves me1 me2 locals) #f)
;; A LocalAction is one of
;; - (make-local-expansion Syntax Syntax Syntax Syntax Derivation)
;; - (make-local-lift Syntax Identifier)
(define-struct local-expansion (e1 e2 me1 me2 deriv) #f)
(define-struct local-lift (expr id) #f)
(define-struct local-lift-end (decl) #f)
;; A PRule is one of ...
(define-struct (prule deriv) (resolves) #f)
;; Lexical or Mapped Variable
(define-struct (p:variable prule) () #f)
;; Definitions: one subterm each
(define-struct (p:define-syntaxes prule) (rhs) #f)
(define-struct (p:define-values prule) (rhs) #f)
;; Simple expressions
(define-struct (p:if prule) (full? test then else) #f)
(define-struct (p:wcm prule) (key mark body) #f)
(define-struct (p:set! prule) (id-resolves rhs) #f)
(define-struct (p:set!-macro prule) (deriv) #f)
;; Sequence-containing expressions
(define-struct (p:begin prule) (lderiv) #f)
(define-struct (p:begin0 prule) (first lderiv) #f)
(define-struct (p:#%app prule) (tagged-stx lderiv) #f)
;; Binding expressions
(define-struct (p:lambda prule) (renames body) #f)
(define-struct (p:case-lambda prule) (renames+bodies) #f)
(define-struct (p:let-values prule) (renames rhss body) #f)
(define-struct (p:let*-values prule) (inner) #f)
(define-struct (p:letrec-values prule) (renames rhss body) #f)
(define-struct (p:letrec-syntaxes+values prule) (srenames srhss vrenames vrhss body) #f)
;; Atomic primitives: no subterms
(define-struct (p::STOP prule) () #f)
(define-struct (p:#%datum p::STOP) (tagged-stx) #f)
(define-struct (p:#%top p::STOP) (tagged-stx) #f)
(define-struct (p:quote p::STOP) () #f)
(define-struct (p:quote-syntax p::STOP) () #f)
(define-struct (p:require p::STOP) () #f)
(define-struct (p:require-for-syntax p::STOP) () #f)
(define-struct (p:require-for-template p::STOP) () #f)
(define-struct (p:provide p::STOP) () #f)
;; for stop expander
(define-struct (p:stop p::STOP) () #f)
;; for early primitive errors
(define-struct (p:unknown p::STOP) () #f)
;; Module stuff.... hairy
(define-struct (p:module prule) (body) #f)
(define-struct (p:#%module-begin prule) (pass1 pass2) #f)
;; where pass1 is a ModPass1
;; and pass2 is a ModPass2
;; Artificial Rename
;; FIXME: Go back and add more info later, such as rename-identity
(define-struct (p:rename prule) (renames inner) #f)
;; Synthetic primitive
(define-struct (p:synth prule) (subterms) #f)
;; where subterms is list-of-Subterm
;; A Subterm is one of
;; - (make-s:subterm Path Derivation)
(define-struct s:subterm (path deriv) #f)
;; A ListDerivation is (make-lderiv Syntaxes Syntaxes (listof Derivation))
(define-struct lderiv (es1 es2 derivs) #f)
;; A BlockDerivation is (make-bderiv syntax-list syntax-list BlockPass1 Transition LDeriv)
;; where Transition = (union 'letrec 'list)
(define-struct bderiv (es1 es2 pass1 trans pass2) #f)
;; A BlockPass1 is list-of-BRule
;; A BRule is one of
;; - (make-b:defvals BlockRename Derivation/#f)
;; - (make-b:devstx BlockRename Derivation Derivation)
;; - (make-b:splice BlockRename Derivation Syntaxes)
;; - (make-b:expr BlockRename Derivation)
;; - (make-b:begin BlockRename Derivation List-of-BRule)
;; This last only used in macro-hiding
;; A BlockRename is (cons syntax syntax)
;; It always applies only to the current block element
(define-struct brule (renames))
(define-struct (b:defvals brule) (head) #f)
(define-struct (b:defstx brule) (deriv rhs) #f)
(define-struct (b:splice brule) (head tail) #f)
(define-struct (b:expr brule) (head) #f)
(define-struct (b:begin brule) (head inner) #f)
;; A ModPass1 is a list of ModRule1
;; A ModRule1 is one of
;; - (make-mod:prim Derivation ModPrim)
;; - (make-mod:splice Derivation tail)
;; - (make-mod:lift Derivation tail)
;; - (make-mod:begin Derivation (list-of ModRule1))
;; A ModPrim is a PRule in:
;; - (make-p:define-values syntax syntax () #f)
;; - (make-p:define-syntaxes syntax syntax () Derivation)
;; - (make-p:require syntax syntax ())
;; - (make-p:require-for-syntax syntax syntax ())
;; - (make-p:require-for-template syntax syntax ())
;; - (make-p:provide syntax syntax ())
;; - #f
;; A ModPass2 is a list of ModRule2
;; A ModRule2 is one of
;; - (make-mod:skip)
;; - (make-mod:cons Derivation)
;; - (make-mod:lift Derivation syntaxes)
(define-struct modrule ())
(define-struct (mod:cons modrule) (head) #f)
(define-struct (mod:prim modrule) (head prim) #f)
(define-struct (mod:skip modrule) () #f)
(define-struct (mod:splice modrule) (head tail) #f)
(define-struct (mod:lift modrule) (head tail) #f)
(define-struct (mod:lift-end modrule) (tail) #f)
(define-struct (mod:begin modrule) (head inner) #f)
;; Handling Syntax Errors
;; ----------------------
;; An interrupted node is (make-interrupted-wrap symbol node)
;; where node is one of Derivation, ListDerivation, BlockDerivation,
;; PRule, MRule, BRule, or ModRule
(define-struct interrupted-wrap (tag inner) #f)
;; An error-wrapped node is (make-error-wrap exception symbol node)
;; where node is one of PRule, MRule, BRule, or ModRule
(define-struct error-wrap (exn tag inner) #f)
)

View File

@ -0,0 +1,470 @@
(module deriv-parser mzscheme
(require "yacc-ext.ss"
"yacc-interrupted.ss"
"deriv.ss"
"deriv-tokens.ss")
(provide parse-derivation)
(define (deriv-error ok? name value start end)
(if ok?
(error 'derivation-parser "error on token #~a: <~s, ~s>" start name value)
(error 'derivation-parser "bad token #~a" start)))
;; PARSER
(define parse-derivation
(parser
(options (start Expansion)
(src-pos)
(tokens basic-tokens prim-tokens renames-tokens)
(end EOF)
(error deriv-error)
#;(debug "debug-parser.txt"))
;; Required (non-hygienically) by productions/I
(productions
#;(Error [(syntax-error) $1])
(NoError [() #f]))
;; tokens
(skipped-token-values visit resolve next next-group return
enter-macro macro-pre-transform macro-post-transform exit-macro
enter-prim exit-prim
enter-block block->list block->letrec splice
enter-list exit-list
enter-check exit-check
local-post exit-local
phase-up module-body
renames-lambda
renames-case-lambda
renames-let
renames-letrec-syntaxes
renames-block
IMPOSSIBLE)
;; Entry point
(productions
(Expansion
[(EE/Lifts) $1]
[(EE/Lifts/Interrupted) $1]))
(productions/I
;; Expansion of an expression
;; EE Answer = Derivation (I)
(EE
(#:no-wrap)
[(visit (? PrimStep 'prim) return)
$2]
[(visit (? TaggedPrimStep 'prim) return)
($2 $1)]
[((? EE/Macro))
$1])
(EE/Macro
[(visit (? MacroStep 'macro) (? EE 'next))
(make-mrule $1 (and (deriv? $3) (deriv-e2 $3)) $2 $3)])
;; Expand/Lifts
;; Expand/Lifts Answer = Derivation (I)
(EE/Lifts
(#:no-wrap)
[((? EE)) $1]
[((? EE/Lifts+)) $1])
(EE/Lifts+
[(EE lift-loop (? EE/Lifts))
(let ([initial (deriv-e1 $1)]
[final (and (deriv? $3) (deriv-e2 $3))])
(make-lift-deriv initial final $1 $2 $3))])
;; Evaluation
(Eval
[() #f])
;; Expansion of an expression to primitive form
;; CheckImmediateMacro Answer = Derivation (I)
(CheckImmediateMacro
(#:no-wrap)
[(enter-check (? CheckImmediateMacro/Inner) exit-check)
($2 $1 $3 (lambda (ce1 ce2) (make-p:stop ce1 ce2 null)))])
(CheckImmediateMacro/Inner
(#:args e1 e2 k)
[()
(k e1 e2)]
[(visit (? MacroStep 'macro) return (? CheckImmediateMacro/Inner 'next))
(let ([next ($4 $3 e2 k)])
(make-mrule $1 (and (deriv? next) (deriv-e2 next)) $2 next))])
;; Expansion of multiple expressions, next-separated
;; NextEEs Answer = (listof Derivation)
(NextEEs
(#:no-wrap)
(#:skipped null)
[() null]
[(next (? EE 'first) (? NextEEs 'rest)) (cons $2 $3)])
;; Keyword resolution
;; Resolves Answer = (listof identifier)
(Resolves [() null]
[(resolve Resolves) (cons $1 $2)])
;; Single macro step (may contain local-expand calls)
;; MacroStep Answer = Transformation (I,E)
(MacroStep
[(Resolves enter-macro
macro-pre-transform (? LocalActions 'locals) (! 'transform) macro-post-transform
exit-macro)
(make-transformation $2 $7 $1 $3 $6 $4)])
;; Local actions taken by macro
;; LocalAction Answer = (list-of LocalAction)
(LocalActions
(#:no-wrap)
(#:skipped null)
[() null]
[((? LocalAction) (? LocalActions)) (cons $1 $2)])
(LocalAction
[(enter-local local-pre (? EE) local-post exit-local)
(make-local-expansion $1 $5 $2 $4 $3)]
[(lift)
(make-local-lift (car $1) (cdr $1))]
[(lift-statement)
(make-local-lift-end $1)])
;; Multiple calls to local-expand
;; EEs Answer = (listof Derivation)
(EEs
(#:skipped null)
(#:no-wrap)
[() null]
[((? EE 'first) (? EEs 'rest)) (cons $1 $2)])
;; Primitive syntax step
;; PrimStep Answer = PRule
(PrimStep
(#:no-wrap)
[(Resolves NoError enter-prim (? Prim) exit-prim)
($4 $3 $5 $1)]
[(Resolves variable)
(make-p:variable (car $2) (cdr $2) $1)])
;; Tagged Primitive syntax
;; TaggedPrimStep Answer = syntax -> PRule
(TaggedPrimStep
(#:no-wrap)
(#:args orig-stx)
[(Resolves ! IMPOSSIBLE)
(make-p:unknown orig-stx #f $1)]
[(Resolves NoError enter-prim (? TaggedPrim) exit-prim)
($4 orig-stx $5 $1 $3)])
;; Primitive
;; Prim Answer = syntax syntax (listof identifier) -> PRule
(Prim
(#:args e1 e2 rs)
(#:no-wrap)
[((? PrimModule)) ($1 e1 e2 rs)]
[((? Prim#%ModuleBegin)) ($1 e1 e2 rs)]
[((? PrimDefineSyntaxes)) ($1 e1 e2 rs)]
[((? PrimDefineValues)) ($1 e1 e2 rs)]
[((? PrimIf)) ($1 e1 e2 rs)]
[((? PrimWCM)) ($1 e1 e2 rs)]
[((? PrimSet)) ($1 e1 e2 rs)]
[((? PrimBegin)) ($1 e1 e2 rs)]
[((? PrimBegin0)) ($1 e1 e2 rs)]
[((? PrimLambda)) ($1 e1 e2 rs)]
[((? PrimCaseLambda)) ($1 e1 e2 rs)]
[((? PrimLetValues)) ($1 e1 e2 rs)]
[((? PrimLet*Values)) ($1 e1 e2 rs)]
[((? PrimLetrecValues)) ($1 e1 e2 rs)]
[((? PrimLetrecSyntaxes+Values)) ($1 e1 e2 rs)]
[((? PrimSTOP)) ($1 e1 e2 rs)]
[((? PrimQuote)) ($1 e1 e2 rs)]
[((? PrimQuoteSyntax)) ($1 e1 e2 rs)]
[((? PrimRequire)) ($1 e1 e2 rs)]
[((? PrimRequireForSyntax)) ($1 e1 e2 rs)]
[((? PrimRequireForTemplate)) ($1 e1 e2 rs)]
[((? PrimProvide)) ($1 e1 e2 rs)])
;; Tagged Primitive
;; TaggedPrim Answer = syntax syntax (list-of identifier) syntax -> PRule
(TaggedPrim
(#:args e1 e2 rs tagged-stx)
(#:no-wrap)
[((? Prim#%App)) ($1 e1 e2 rs tagged-stx)]
[((? Prim#%Datum)) ($1 e1 e2 rs tagged-stx)]
[((? Prim#%Top)) ($1 e1 e2 rs tagged-stx)])
;; Modules
(PrimModule
(#:args e1 e2 rs)
[(prim-module ! (? EE 'body))
(make-p:module e1 e2 rs $3)]
;; One form after language ... macro that expands into #%module-begin
[(prim-module NoError next
enter-check (? CheckImmediateMacro/Inner) exit-check
(! 'module-begin) next (? EE))
(make-p:module e1 e2 rs
($5 $4
(and (deriv? $9) (deriv-e2 $9))
(lambda (ce1 ce2) $9)))])
(Prim#%ModuleBegin
(#:args e1 e2 rs)
[(prim-#%module-begin ! (? ModulePass1 'pass1) next-group (? ModulePass2 'pass2))
(make-p:#%module-begin e1 e2 rs $3 $5)])
(ModulePass1
(#:skipped null)
(#:no-wrap)
[() null]
[(next (? ModulePass1-Part) (? ModulePass1))
(cons $2 $3)]
[(lift-end-loop (? ModulePass1))
(cons (make-mod:lift-end $1) $2)])
(ModulePass1-Part
[((? EE) (? ModulePass1/Prim))
(make-mod:prim $1 $2)]
[(EE splice)
(make-mod:splice $1 $2)]
[(EE lift-loop)
(make-mod:lift $1 $2)])
(ModulePass1/Prim
[(enter-prim prim-define-values ! exit-prim)
(make-p:define-values $1 $4 null #f)]
[(enter-prim prim-define-syntaxes ! phase-up (? EE) exit-prim)
(make-p:define-syntaxes $1 $6 null $5)]
[(enter-prim prim-require ! exit-prim)
(make-p:require $1 $4 null)]
[(enter-prim prim-require-for-syntax ! exit-prim)
(make-p:require-for-syntax $1 $4 null)]
[(enter-prim prim-require-for-template ! exit-prim)
(make-p:require-for-template $1 $4 null)]
[(enter-prim prim-provide ! exit-prim)
(make-p:provide $1 $4 null)]
[()
#f])
(ModulePass2
(#:skipped null)
(#:no-wrap)
[() null]
[(next (? ModulePass2-Part) (? ModulePass2))
(cons $2 $3)]
[(lift-end-loop (? ModulePass2))
(cons (make-mod:lift-end $1) $2)])
(ModulePass2-Part
;; not normal; already handled
[()
(make-mod:skip)]
;; normal: expand completely
[((? EE))
(make-mod:cons $1)]
;; catch lifts
[(EE lift-loop)
(make-mod:lift $1 $2)])
;; Definitions
(PrimDefineSyntaxes
(#:args e1 e2 rs)
[(prim-define-syntaxes ! (? EE/Lifts))
(make-p:define-syntaxes e1 e2 rs $3)])
(PrimDefineValues
(#:args e1 e2 rs)
[(prim-define-values ! (? EE))
(make-p:define-values e1 e2 rs $3)])
;; Simple expressions
(PrimIf
(#:args e1 e2 rs)
[(prim-if ! (? EE 'test) next (? EE 'then) next (? EE 'else))
(make-p:if e1 e2 rs #t $3 $5 $7)]
[(prim-if NoError next-group (? EE 'test) next (? EE 'then))
(make-p:if e1 e2 rs #f $4 $6 #f)])
(PrimWCM
(#:args e1 e2 rs)
[(prim-wcm ! (? EE 'key) next (? EE 'mark) next (? EE 'body))
(make-p:wcm e1 e2 rs $3 $5 $7)])
;; Sequence-containing expressions
(PrimBegin
(#:args e1 e2 rs)
[(prim-begin ! (? EL))
(make-p:begin e1 e2 rs $3)])
(PrimBegin0
(#:args e1 e2 rs)
[(prim-begin0 ! next (? EE) next (? EL))
(make-p:begin0 e1 e2 rs $4 $6)])
(Prim#%App
(#:args e1 e2 rs tagged-stx)
[(prim-#%app !)
(make-p:#%app e1 e2 rs tagged-stx (make-lderiv null null null))]
[(prim-#%app NoError (? EL))
(make-p:#%app e1 e2 rs tagged-stx $3)])
;; Binding expressions
(PrimLambda
(#:args e1 e2 rs)
[(prim-lambda ! renames-lambda (? EB))
(make-p:lambda e1 e2 rs $3 $4)])
(PrimCaseLambda
(#:args e1 e2 rs)
[(prim-case-lambda ! (? NextCaseLambdaClauses))
(make-p:case-lambda e1 e2 rs $3)])
(NextCaseLambdaClauses
(#:skipped null)
[(next ! renames-case-lambda (? EB 'first) (? NextCaseLambdaClauses 'rest))
(cons (cons $3 $4) $5)]
[() null])
(PrimLetValues
(#:args e1 e2 rs)
[(prim-let-values ! renames-let (? NextEEs 'rhss) next-group (? EB 'body))
(make-p:let-values e1 e2 rs $3 $4 $6)])
(PrimLet*Values
(#:args e1 e2 rs)
;; let*-values with bindings is "macro-like"
[(prim-let*-values ! (? EE))
(make-p:let*-values e1 e2 rs $3)]
;; No bindings... model as "let"
[(prim-let*-values NoError renames-let (? NextEEs 'rhss) next-group (? EB 'body))
(make-p:let-values e1 e2 rs $3 $4 $6)])
(PrimLetrecValues
(#:args e1 e2 rs)
[(prim-letrec-values ! renames-let (? NextEEs 'rhss) next-group (? EB 'body))
(make-p:letrec-values e1 e2 rs $3 $4 $6)])
;; Might have to deal with let*-values
(PrimLetrecSyntaxes+Values
(#:args e1 e2 rs)
[(prim-letrec-syntaxes+values (! 'bad-syntax) renames-letrec-syntaxes
(? NextBindSyntaxess 'srhss) next-group (? EB 'body))
(make-p:letrec-syntaxes+values e1 e2 rs $3 $4 #f null $6)]
[(prim-letrec-syntaxes+values NoError renames-letrec-syntaxes
NextBindSyntaxess next-group
prim-letrec-values (! 'impossible?)
renames-let (? NextEEs 'vrhss) next-group (? EB 'body))
(make-p:letrec-syntaxes+values e1 e2 rs $3 $4 $8 $9 $11)])
;; Atomic expressions
(Prim#%Datum
(#:args e1 e2 rs tagged-stx)
[(prim-#%datum !) (make-p:#%datum e1 e2 rs tagged-stx)])
(Prim#%Top
(#:args e1 e2 rs tagged-stx)
[(prim-#%top !) (make-p:#%top e1 e2 rs tagged-stx)])
(PrimSTOP
(#:args e1 e2 rs)
[(prim-stop !) (make-p:stop e1 e2 rs)])
(PrimQuote
(#:args e1 e2 rs)
[(prim-quote !) (make-p:quote e1 e2 rs)])
(PrimQuoteSyntax
(#:args e1 e2 rs)
[(prim-quote-syntax !) (make-p:quote-syntax e1 e2 rs)])
(PrimRequire
(#:args e1 e2 rs)
[(prim-require !) (make-p:require e1 e2 rs)])
(PrimRequireForSyntax
(#:args e1 e2 rs)
[(prim-require-for-syntax !) (make-p:require-for-syntax e1 e2 rs)])
(PrimRequireForTemplate
(#:args e1 e2 rs)
[(prim-require-for-template !) (make-p:require-for-template e1 e2 rs)])
(PrimProvide
(#:args e1 e2 rs)
[(prim-provide !) (make-p:provide e1 e2 rs)])
(PrimSet
(#:args e1 e2 rs)
[(prim-set! ! Resolves next (? EE))
(make-p:set! e1 e2 rs $3 $5)]
[(prim-set! NoError (? MacroStep 'macro) (? EE 'continue))
(make-p:set!-macro e1 e2 rs (make-mrule e1 (and (deriv? $4) (deriv-e2 $4)) $3 $4))])
;; Blocks
;; EB Answer = BlockDerivation
(EB
[(enter-block (? BlockPass1 'pass1) block->list (? EL 'pass2))
(make-bderiv $1
(and (lderiv? $4) (lderiv-es2 $4))
$2
'list
$4)]
[(enter-block BlockPass1 block->letrec (? EL 'pass2))
(make-bderiv $1
(and (lderiv? $4) (lderiv-es2 $4))
$2
'letrec
$4)])
;; BlockPass1 Answer = (list-of BRule)
(BlockPass1
(#:no-wrap)
(#:skipped null)
[() null]
[((? BRule) (? BlockPass1))
(cons $1 $2)])
;; BRule Answer = BRule
(BRule
[(next ! IMPOSSIBLE)
#f]
[(next NoError renames-block (? CheckImmediateMacro 'check))
(make-b:expr $3 $4)]
[(next NoError renames-block CheckImmediateMacro prim-begin ! splice !)
(make-b:splice $3 $4 $7)]
[(next NoError renames-block CheckImmediateMacro prim-define-values !)
(make-b:defvals $3 $4)]
[(next NoError renames-block CheckImmediateMacro
prim-define-syntaxes (? BindSyntaxes 'bind))
(make-b:defstx $3 $4 $5)])
;; BindSyntaxes Answer = Derivation
(BindSyntaxes
[(phase-up (? EE/Lifts) Eval) $2])
;; NextBindSyntaxess Answer = (list-of Derivation)
(NextBindSyntaxess
(#:skipped null)
[() null]
[(next (? BindSyntaxes 'first) (? NextBindSyntaxess 'rest)) (cons $2 $3)])
;; Lists
;; EL Answer = ListDerivation
(EL
(#:skipped #f)
[(enter-list ! (? EL*) exit-list) (make-lderiv $1 $4 $3)])
;; EL* Answer = (listof Derivation)
(EL*
(#:no-wrap)
(#:skipped null)
[() null]
[(next (? EE 'first) (? EL* 'rest)) (cons $2 $3)])
)))
)

View File

@ -0,0 +1,143 @@
(module deriv-tokens mzscheme
(require (lib "lex.ss" "parser-tools")
"deriv.ss")
(provide (all-defined))
(define-tokens basic-tokens
(visit ; syntax
resolve ; identifier
next ; .
next-group ; .
enter-macro ; syntax
macro-pre-transform ; syntax
macro-post-transform ; syntax
exit-macro ; syntax
enter-prim ; syntax
exit-prim ; syntax
return ; syntax
enter-block ; syntaxes
block->list ; syntaxes
block->letrec ; syntax(es?)
splice ; syntaxes
enter-list ; syntaxes
exit-list ; syntaxes
enter-check ; syntax
exit-check ; syntax
phase-up ; .
module-body ; (list-of (cons syntax boolean))
... ; .
EOF ; .
syntax-error ; exn
lift-loop ; syntax
lift-end-loop ; syntax
lift ; (cons syntax id)
lift-statement ; syntax
enter-local ; syntax
local-pre ; syntax
local-post ; syntax
exit-local ; syntax
IMPOSSIBLE ; useful for error-handling clauses that have no NoError counterpart
))
(define-tokens renames-tokens
(renames-lambda ; (cons syntax syntax)
renames-case-lambda ; (cons syntax syntax)
renames-let ; (cons (listof syntax) syntax)
renames-letrec-syntaxes ; (cons (listof syntax) (cons (listof syntax) syntax))
renames-block ; (cons syntax syntax) ... different, contains both pre+post
))
(define-tokens prim-tokens
(prim-module prim-#%module-begin
prim-define-syntaxes prim-define-values
prim-if prim-wcm prim-begin prim-begin0 prim-#%app prim-lambda
prim-case-lambda prim-let-values prim-let*-values prim-letrec-values
prim-letrec-syntaxes+values prim-#%datum prim-#%top prim-stop
prim-quote prim-quote-syntax prim-require prim-require-for-syntax
prim-require-for-template prim-provide
prim-set!
variable ; (cons identifier identifier)
))
;; ** Signals to tokens
(define signal-mapping
`((EOF . EOF)
(error . ,token-syntax-error)
(0 . ,token-visit)
(1 . ,token-resolve)
(2 . ,token-return)
(3 . ,token-next)
(4 . ,token-enter-list)
(5 . ,token-exit-list)
(6 . ,token-enter-prim)
(7 . ,token-exit-prim)
(8 . ,token-enter-macro)
(9 . ,token-exit-macro)
(10 . ,token-enter-block)
(11 . ,token-splice)
(12 . ,token-block->list)
(13 . ,token-next-group)
(14 . ,token-block->letrec)
#;(15 . renamer)
(16 . ,token-renames-let)
(17 . ,token-renames-lambda)
(18 . ,token-renames-case-lambda)
(19 . ,token-renames-letrec-syntaxes)
(20 . phase-up)
(21 . ,token-macro-pre-transform)
(22 . ,token-macro-post-transform)
(23 . ,token-module-body)
(24 . ,token-renames-block)
(100 . prim-stop)
(101 . prim-module)
(102 . prim-#%module-begin)
(103 . prim-define-syntaxes)
(104 . prim-define-values)
(105 . prim-if)
(106 . prim-wcm)
(107 . prim-begin)
(108 . prim-begin0)
(109 . prim-#%app)
(110 . prim-lambda)
(111 . prim-case-lambda)
(112 . prim-let-values)
(113 . prim-letrec-values)
(114 . prim-letrec-syntaxes+values)
(115 . prim-#%datum)
(116 . prim-#%top)
(117 . prim-quote)
(118 . prim-quote-syntax)
(119 . prim-require)
(120 . prim-require-for-syntax)
(121 . prim-require-for-template)
(122 . prim-provide)
(123 . prim-set!)
(124 . prim-let*-values)
(125 . ,token-variable)
(126 . ,token-enter-check)
(127 . ,token-exit-check)
(128 . ,token-lift-loop)
(129 . ,token-lift)
(130 . ,token-enter-local)
(131 . ,token-exit-local)
(132 . ,token-local-pre)
(133 . ,token-local-post)
(134 . ,token-lift-statement)
(135 . ,token-lift-end-loop)
))
(define (tokenize sig-n val pos)
(let ([p (assv sig-n signal-mapping)])
(if (pair? p)
(make-position-token
(cond [(procedure? (cdr p)) ((cdr p) val)]
[(symbol? (cdr p)) (cdr p)])
pos
pos)
(error 'tokenize "bad signal: ~s" sig-n))))
)

View File

@ -0,0 +1,165 @@
(module deriv-util mzscheme
(require "deriv.ss"
(lib "plt-match.ss"))
(provide IntW
ErrW
AnyQ
IntQ
$$
$$I
$$E
Wrap
lift/wrap
rewrap
rewrap/nt
outer-rewrap
lift/deriv-e1
lift/deriv-e2
wrapped?)
;; IntW
;; Matches only interrupted wraps
(define-match-expander IntW
(syntax-rules ()
[(IntW S (var ...))
(struct interrupted-wrap (_ (struct S (var ...))))]
[(IntW S (var ...) tag)
(struct interrupted-wrap (tag (struct S (var ...))))]))
;; ErrW
;; Matches only error wraps
(define-match-expander ErrW
(syntax-rules ()
[(ErrW S (var ...))
(struct error-wrap (_ _ (struct S (var ...))))]
[(ErrW S (var ...) exn)
(struct error-wrap (exn _ (struct S (var ...))))]
[(ErrW S (var ...) tag exn)
(struct error-wrap (exn tag (struct S (var ...))))]))
;; AnyQ matcher
;; Matches unwrapped, interrupted wrapped, or error wrapped
(define-match-expander AnyQ
(syntax-rules ()
[(AnyQ S (var ...))
(or (struct S (var ...))
(struct interrupted-wrap (_ (struct S (var ...))))
(struct error-wrap (_ _ (struct S (var ...)))))]
[(AnyQ S (var ...) exni)
(or (and (struct S (var ...))
(app (lambda (_) #f) exni))
(and (struct interrupted-wrap (tag (struct S (var ...))))
(app (lambda (ew) (cons #f (interrupted-wrap-tag ew))) exni))
(and (struct error-wrap (exn tag (struct S (var ...))))
(app (lambda (ew) (cons (error-wrap-exn ew) (error-wrap-tag ew))) exni)))]))
;; IntQ
;; Matches interrupted wraps and unwrapped structs
(define-match-expander IntQ
(syntax-rules ()
[(IntQ S (var ...))
(or (struct S (var ...))
(struct interrupted-wrap (_ (struct S (var ...)))))]
[(IntQ S (var ...) tag)
(or (and (struct S (var ...))
(app (lambda (_) #f) tag))
(struct interrupted-wrap (tag (struct S (var ...)))))]))
;; $$ match form
;; ($$ struct-name (var ...) info)
;; If normal instance of struct-name, binds info to #f
;; If interrupted-wrapped, binds info to (cons #f symbol/#f)
;; If error-wrapped, binds info to (cons exn symbol/#f)
(define-match-expander $$
(lambda (stx)
(syntax-case stx ()
[($$ S (var ...) info)
#'(or (and (struct S (var ...))
(app (lambda (_) #f) info))
(and (struct interrupted-wrap (tag (struct S (var ...))))
(app (lambda (ew) (cons #f (interrupted-wrap-tag ew))) info))
(and (struct error-wrap (exn tag (struct S (var ...))))
(app (lambda (ew) (cons (error-wrap-exn ew) (error-wrap-tag ew)))
info)))]
[($$ S (var ...))
#'(struct S (var ...))])))
(define-match-expander $$I
(lambda (stx)
(syntax-case stx ()
[($$I S (var ...))
#'(or (struct interrupted-wrap (tag (struct S (var ...))))
(struct S (var ...)))]
[($$I S (var ...) tag)
#'(or (struct interrupted-wrap (tag (struct S (var ...))))
(and (app (lambda (_) #f) tag)
(struct S (var ...))))])))
(define-match-expander $$E
(lambda (stx)
(syntax-case stx ()
[($$E S (var ...))
#'(or (struct interrupted-wrap (_tag (struct S (var ...))))
(struct error-wrap (_exn _tag (struct S (var ...))))
(struct S (var ...)))])))
(define-match-expander Wrap
(syntax-rules ()
[(Wrap x)
(or (struct interrupted-wrap (_tag x))
(struct error-wrap (_exn _tag x))
x)]))
;; lift/wrap : ('a -> 'b) boolean -> Wrap('a) -> Wrap('b)
(define (lift/wrap f preserve-tag?)
(lambda (x)
(match x
[(struct interrupted-wrap (tag inner))
(make-interrupted-wrap (and preserve-tag? tag) (f inner))]
[(struct error-wrap (exn tag inner))
(make-error-wrap exn (and preserve-tag? tag) (f inner))]
[x
(f x)])))
;; rewrap : Wrap('a) 'b -> Wrap('b)
(define (rewrap x y)
(if (wrapped? y)
y
((lift/wrap (lambda (x) y) #t) x)))
;; rewrap/nt : Wrap('a) 'b -> Wrap('b)
(define (rewrap/nt x y)
(if (wrapped? y)
y
((lift/wrap (lambda (x) y) #f) x)))
(define (outer-rewrap x y)
(if (and (wrapped? x) (not (wrapped? y)))
(make-interrupted-wrap #f y)
y))
(define (lift/deriv-e1 x)
(match x
[(AnyQ deriv (e1 _)) e1]))
(define (lift/deriv-e2 x)
(match x
[(AnyQ deriv (_ e2)) e2]))
(define (wrapped? x)
(or (interrupted-wrap? x)
(error-wrap? x)))
; (define-match-expander $$E
; (lambda (stx)
; (syntax-case stx (@)
; [($$E S (var ...))
; #'($$ S (var ...) _exni)]
; [($$E S (var ...) @ tag)
; #'($$ S (var ...) (cons #f tag))]
; [($$E S (var ...) @ tag exn)
; #'($$ S (var ...) (cons exn tag))])))
)

View File

@ -0,0 +1,311 @@
(module deriv mzscheme
(require (lib "contract.ss")
(lib "stx.ss" "syntax")
"deriv-c.ss")
;; NO CONTRACTS
; (provide (all-from "deriv-c.ss"))
;; CONTRACTS
(define (stx-list-like? x)
(or (syntax? x)
(null? x)
(and (pair? x) (syntax? (car x)) (stx-list-like? (cdr x)))))
(define (maybe c) (or/c c false/c))
(define node/c (or/c deriv? lderiv? bderiv? transformation? brule? modrule?))
(define errnode/c (or/c prule? transformation? lderiv? brule? modrule?))
(define tag/c (maybe symbol?))
(define syntax/f (maybe syntax?))
(define syntaxes/c stx-list-like?)
(define syntaxes/f (maybe syntaxes/c))
(define (anyw C)
(or/c (struct/c error-wrap exn? tag/c C)
(struct/c interrupted-wrap tag/c C)))
(define (anyq C)
(or/c C (anyw C)))
(define (intw C)
(struct/c interrupted-wrap tag/c C))
(define (intq C)
(or/c C (intw C)))
(define resolves/c (listof identifier?))
(provide/contract
(struct deriv
([e1 syntax?]
[e2 syntax/f]))
(struct (mrule deriv)
([e1 syntax?]
[e2 syntax/f]
[transformation (anyq transformation?)]
[next (maybe (anyq deriv?))]))
(struct (lift-deriv deriv)
([e1 syntax?]
[e2 syntax/f]
[first deriv?]
[lift-stx syntax?]
[second (anyq deriv?)]))
(struct transformation
([e1 syntax?]
[e2 syntax/f]
[resolves resolves/c]
[me1 syntax?]
[me2 syntax/f]
[locals (listof (or/c local-expansion? local-lift? local-lift-end?))]))
(struct (prule deriv)
([e1 syntax?]
[e2 syntax/f]
[resolves resolves/c]))
(struct lderiv
([es1 syntaxes/c]
[es2 syntaxes/f]
[derivs (listof (anyq deriv?))]))
(struct interrupted-wrap
([tag (or/c symbol? false/c)]
[inner node/c]))
(struct error-wrap
([exn exn?]
[tag (or/c symbol? false/c)]
[inner errnode/c])))
(provide ;(struct deriv (e1 e2))
;(struct mrule (transformation next))
;(struct lift-deriv (first lift-stx second))
;(struct transformation (e1 e2 resolves me1 me2 locals))
(struct local-expansion (e1 e2 me1 me2 deriv))
(struct local-lift (expr id))
(struct local-lift-end (decl))
;(struct prule (resolves))
(struct p:variable ())
(struct p:define-syntaxes (rhs))
(struct p:define-values (rhs))
(struct p:if (full? test then else))
(struct p:wcm (key mark body))
(struct p:set! (id-resolves rhs))
(struct p:set!-macro (deriv))
(struct p:begin (lderiv))
(struct p:begin0 (first lderiv))
(struct p:#%app (tagged-stx lderiv))
(struct p:lambda (renames body))
(struct p:case-lambda (renames+bodies))
(struct p:let-values (renames body))
(struct p:let*-values (inner))
(struct p:letrec-values (renames rhss body))
(struct p:letrec-syntaxes+values (srenames srhss vrenames vrhss body))
(struct p:module (body))
(struct p:#%module-begin (pass1 pass2))
(struct p::STOP ())
(struct p:#%datum (tagged-stx))
(struct p:#%top (tagged-stx))
(struct p:quote ())
(struct p:quote-syntax ())
(struct p:require ())
(struct p:require-for-syntax ())
(struct p:require-for-template ())
(struct p:provide ())
(struct p:stop ())
(struct p:unknown ())
(struct p:rename (renames inner))
(struct p:synth (subterms))
(struct s:subterm (path deriv))
;(struct lderiv (es1 es2 derivs))
(struct bderiv (es1 es2 pass1 trans pass2))
(struct brule (renames))
(struct b:defvals (head))
(struct b:defstx (deriv rhs))
(struct b:splice (head tail))
(struct b:expr (head))
(struct b:begin (head inner))
(struct modrule ())
(struct mod:cons (head))
(struct mod:prim (head prim))
(struct mod:skip ())
(struct mod:splice (head tail))
(struct mod:lift (head tail))
(struct mod:lift-end (tail))
(struct mod:begin (head inner))
;(struct interrupted-wrap (tag inner))
;(struct error-wrap (exn tag inner))
)
;; Well-formedness
;; Predicates on well-formed derivations
#;
(define (wf-ok-deriv? x)
(match x
[($ pderiv e1 e2 prule)
(and (syntax? e1)
(syntax? e2)
(wf-ok-prule? prule))]
[($ mderiv e1 e2 mrule next)
(and (syntax? e1)
(syntax? e2)
(wf-ok-mrule? mrule)
(wf-ok-deriv? next))]
[else #f]))
#;
(define (wf-ok-mrule? x)
(match x
[($ mrule e1 e2 rs me1 me2 locals)
(and (syntax? e1)
(syntax? e2)
(list? rs)
(andmap identifier? rs)
(syntax? me1)
(syntax? me2)
(list? locals)
(andmap wf-ok-deriv? locals))]
[else #f]))
#;
(define (wf-ok-basic-prule? x)
(match x
[($ prule e1 e2 rs)
(and (syntax? e1)
(syntax? e2)
(list? rs)
(andmap identifier? rs))]
[else #f]))
#;
(define (wf-ok-prule? x)
(and (wf-ok-basic-prule? x)
(match x
[($ p:variable _ _ _) #t]
[($ p:define-syntaxes _ _ _ rhs)
(wf-ok-deriv? rhs)]
[($ p:define-values _ _ _ rhs)
(wf-ok-deriv? rhs)]
[($ p:if _ _ _ test then else)
(and (wf-ok-deriv? test)
(wf-ok-deriv? then)
(wf-ok-deriv? else))]
[($ p:wcm _ _ _ key value body)
(and (wf-ok-deriv? key)
(wf-ok-deriv? value)
(wf-ok-deriv? body))]
[($ p:set! _ _ _ id-rs rhs)
(and (list? id-rs)
(andmap identifier? id-rs)
(wf-ok-deriv? rhs))]
[($ p:set!-macro _ _ _ deriv)
(wf-ok-deriv? deriv)]
[($ p:begin _ _ _ lderiv)
(wf-ok-lderiv? lderiv)]
[($ p:begin0 _ _ _ first lderiv)
(and (wf-ok-deriv? first)
(wf-ok-lderiv? lderiv))]
[($ p:#%app _ _ _ lderiv)
(wf-ok-lderiv? lderiv)]
[($ p:lambda _ _ _ renames body)
(and (pair? renames)
(syntax? (car renames))
(syntax? (cdr renames))
(wf-ok-bderiv? body))]
[($ p:case-lambda _ _ _ (renames+bodies ...))
(andmap (lambda (r+b)
(and (pair? r+b)
(pair? (car r+b))
(syntax? (caar r+b))
(syntax? (cdar r+b))
(wf-ok-bderiv? (cdr r+b))))
renames+bodies)]
[($ p:let-values _ _ _ (renames ...) (rhss ...) body)
(and (andmap (lambda (r)
(and (pair? r)
(syntax? (car r))
(syntax? (cdr r))))
renames)
(andmap wf-ok-deriv? rhss)
(= (length renames) (length rhss))
(wf-ok-bderiv? body))]
[($ p:letrec-values _ _ _ (renames ...) (rhss ...) body)
(and (andmap (lambda (r)
(and (pair? r)
(syntax? (car r))
(syntax? (cdr r))))
renames)
(andmap wf-ok-deriv? rhss)
(= (length renames) (length rhss))
(wf-ok-bderiv? body))]
[($ p:letrec-syntaxes+values _ _ _
(srenames ...) (srhss ...) (vrenames ...) (vrhss ...) body)
(and (andmap (lambda (r)
(and (pair? r) (syntax? (car r)) (syntax? (cdr r))))
srenames)
(andmap wf-ok-deriv? srhss)
(= (length srenames) (length srhss))
(andmap (lambda (r)
(and (pair? r) (syntax? (car r)) (syntax? (cdr r))))
vrenames)
(andmap wf-ok-deriv? vrhss)
(= (length vrenames) (length vrhss))
(wf-ok-bderiv? body))]
[($ p::STOP _ _ _) #t]
[else #f])))
#;
(define (wf-ok-lderiv? x)
(match x
[($ lderiv es1 es2 derivs)
(and (list? es1)
(andmap syntax? es1)
(list? es2)
(andmap syntax? es2)
(list? derivs)
(andmap wf-ok-lderiv? derivs))]
[else #f]))
#;
(define (wf-ok-bderiv? x)
(define (wf-ok-brule? x)
(match x
[($ brskip renames next)
(and (void renames)
(wf-ok-brule? next))]
[($ brcons renames head next)
(and (void renames)
(wf-ok-deriv? head)
(wf-ok-brule? next))]
[($ brdefstx renames deriv rhs next)
(and (void renames)
(wf-ok-deriv? deriv)
(wf-ok-deriv? rhs)
(wf-ok-brule? next))]
[($ brsplice tail next)
(and (list? tail)
(andmap syntax? tail)
(wf-ok-brule? next))]
[else #f]))
(match x
[($ bderiv es1 es2 pass1 trans pass2)
(and (wf-ok-brule? pass1)
(wf-ok-lderiv? pass2))]
[else #f]))
#;
(define (wf-exn-deriv? x)
#f)
)

View File

@ -0,0 +1,81 @@
(module hiding-policies mzscheme
(require (lib "plt-match.ss")
(lib "boundmap.ss" "syntax"))
(provide (all-defined))
(define-struct hiding-policy
(opaque-modules opaque-ids opaque-kernel transparent-ids))
(define (policy-hide-module p m)
(hash-table-put! (hiding-policy-opaque-modules p) m #t))
(define (policy-unhide-module p m)
(hash-table-remove! (hiding-policy-opaque-modules p) m))
(define (policy-hide-kernel p)
(set-hiding-policy-opaque-kernel! p #t))
(define (policy-unhide-kernel p)
(set-hiding-policy-opaque-kernel! p #f))
(define (policy-hide-id p id)
(policy-unshow-id p id)
(module-identifier-mapping-put! (hiding-policy-opaque-ids p) id #t))
(define (policy-unhide-id p id)
(module-identifier-mapping-put! (hiding-policy-opaque-ids p) id #f))
(define (policy-show-id p id)
(policy-unhide-id p id)
(module-identifier-mapping-put! (hiding-policy-transparent-ids p) id #t))
(define (policy-unshow-id p id)
(module-identifier-mapping-put! (hiding-policy-transparent-ids p) id #f))
(define (new-hiding-policy)
(make-hiding-policy (make-hash-table)
(make-module-identifier-mapping)
#f
(make-module-identifier-mapping)))
(define (new-standard-hiding-policy)
(let ([p (new-hiding-policy)])
(policy-hide-kernel p)
p))
;; ---
(define-syntax inline
(syntax-rules ()
[(inline ([name expr] ...) . body)
(let-syntax ([name
(lambda (x)
(syntax-case x ()
[xx (identifier? #'xx) #'expr]))] ...)
. body)]))
(define (/false) #f)
(define (policy-show-macro? policy id)
(match policy
[(struct hiding-policy (opaque-modules
opaque-identifiers
opaque-kernel
transparent-identifiers))
(let ([binding (identifier-binding id)])
(if (list? binding)
(let-values ([(srcmod srcname nommod nomname _) (apply values binding)])
(inline ([opaque-srcmod (hash-table-get opaque-modules srcmod /false)]
[opaque-nommod (hash-table-get opaque-modules nommod /false)]
;; FIXME
[in-kernel?
(and (symbol? srcmod)
(eq? #\# (string-ref (symbol->string srcmod) 0)))]
[not-opaque-id
(not (module-identifier-mapping-get opaque-identifiers id /false))]
[transparent-id
(module-identifier-mapping-get transparent-identifiers id /false)])
(or transparent-id
(and (not opaque-srcmod)
(not opaque-nommod)
(not (and in-kernel? opaque-kernel))
not-opaque-id))))
#f))]))
)

View File

@ -0,0 +1,196 @@
(module reductions-engine mzscheme
(require "deriv.ss"
"stx-util.ss")
(provide (all-defined))
;; A ReductionSequence is a (list-of Reduction)
;; A Reduction is one of
;; - (make-step Syntaxes Syntaxes Syntax Syntax BigContext)
;; - (make-misstep Syntax Syntax Exception)
(define-struct step (redex contractum e1 e2 note lctx) #f)
;(define-struct lift-step (expr id note lctxt) #t)
(define-struct misstep (redex e1 exn) #f)
;; -------------------------
;; A Context is (syntax -> syntax)
;; A BigContext is (list-of (cons Syntaxes Syntax))
;; local expansion contexts: pairs of foci, term
;; context: parameter of Context
(define context (make-parameter (lambda (x) x)))
;; big-context: parameter of BigContext
(define big-context (make-parameter null))
(define-syntax with-context
(syntax-rules ()
[(with-context f . body)
(let ([E (context)])
(parameterize ([context (lambda (x) (E (f x)))])
. body))]))
(define-syntax with-new-local-context
(syntax-rules ()
[(with-new-local-context e . body)
(parameterize ([big-context (cons (cons (list e) (E e)) (big-context))]
[context (lambda (x) x)])
. body)]))
;; E : syntax -> syntax
(define (E stx) ((context) stx))
;; -----------------------------------
;; CC
;; the context constructor
(define-syntax (CC stx)
(syntax-case stx ()
[(CC HOLE expr pattern)
#'(syntax-copier HOLE expr pattern)]))
;; R
;; the threaded reductions engine
(define-syntax R
(syntax-rules ()
[(R form pattern . clauses)
(R** #f _ [#:set-syntax form] [#:pattern pattern] . clauses)]))
(define-syntax (R** stx)
(syntax-case stx (! @ List Block =>)
[(R** form-var pattern)
#'null]
[(R** f p => k)
#'(k f)]
;; Change patterns
[(R** f p [#:pattern p2] . more)
#'(R** f p2 . more)]
;; Bind pattern variables
[(R** f p [#:bind pattern rhs] . more)
#'(with-syntax ([pattern rhs])
(R** f p . more))]
;; Change syntax
[(R** f p [#:set-syntax form] . more)
#'(let ([form-variable form])
(R** form-variable p . more))]
;; Change syntax with step
[(R** f p [#:walk form2 foci1 foci2 description] . more)
#'(let-values ([(form2-var foci1-var foci2-var description-var)
(with-syntax ([p f])
(values form2 foci1 foci2 description))])
(cons (walk/foci/E foci1-var foci2-var f form2-var description-var)
(R** form2-var p . more)))]
[(R** f p [#:walk form2 description] . more)
#'(let-values ([(form2-var description-var)
(with-syntax ([p f])
(values form2 description))])
(cons (walk f form2-var description-var)
(R** form2-var p . more)))]
;; Conditional
[(R** f p [#:if test consequent ...] . more)
#'(if (with-syntax ([p f]) test)
(R** f p consequent ... . more)
(R** f p . more))]
;; Error-point case
[(R** f p [! info] . more)
#'(R** f p [! info #f] . more)]
[(R** f p [! info key] . more)
#'(let ([continue (lambda () (R** f p . more))])
(cond [(and (pair? info) (car info))
;; error-wrap
;; If this is the key, then insert the misstep here and stop.
;; This stops processing *within* an error-wrapped prim.
(if (or (eq? key #f) (eq? key (cdr info)))
(list (make-misstep f (E f) (car info)))
(continue))]
[else
(continue)]))]
[(R** f p [Generator hole0 fill0] . more)
#'(let-values ([(reducer get-e1 get-e2) Generator])
(R** f p [reducer get-e1 get-e2 hole0 fill0] . more))]
; ;; Expression case
; [(R** f p [hole0 fill0] . more)
; #'(R** f p [reductions deriv-e1 deriv-e2 hole0 fill0] . more)]
; ;; List case
; [(R** f p [List hole0 fill0] . more)
; #'(R** f p [list-reductions lderiv-es1 lderiv-es2 hole0 fill0] . more)]
; ;; Block case
; [(R** f p [Block hole0 fill0] . more)
; #'(R** f p [block-reductions bderiv-es1 bderiv-es2 hole0 fill0] . more)]
;; Implementation for (hole ...) sequences
[(R** form-var pattern
[f0 get-e1 get-e2 (hole0 :::) fill0s] . more)
(module-identifier=? #'::: (quote-syntax ...))
#'(let ([ctx0 (CC (hole0 :::) form-var pattern)])
(let ([e1s (with-syntax ([pattern form-var]) (syntax->list #'(hole0 :::)))])
(let loop ([fills fill0s] [prefix null] [suffix e1s])
(cond
[(pair? fills)
(append
(with-context ctx0
(with-context (lambda (x) (revappend prefix (cons x (cdr suffix))))
(f0 (car fills))))
(cond [(interrupted-wrap? (car fills))
null]
[(error-wrap? (car fills))
null]
[else
(loop (cdr fills)
(cons (get-e2 (car fills)) prefix)
(cdr suffix))]))]
[(null? fills)
(let ([form-var (ctx0 (reverse prefix))])
(R** form-var pattern . more))]))))]
;; Implementation
[(R** form-var pattern
[f0 get-e1 get-e2 hole0 fill0] . more)
#'(let ([ctx0 (CC hole0 form-var pattern)])
(append (with-context ctx0
(f0 fill0))
;; If the last thing we ran through was interrupted,
;; then there's nothing left to do.
;; This stops processing *after* an error-wrapped deriv.
(cond [(interrupted-wrap? fill0) null]
[(error-wrap? fill0) null]
[else
(let ([form-var (ctx0 (get-e2 fill0))])
(R** form-var pattern . more))])))]))
;; -----------------------------------
;; walk : syntax(s) syntax(s) [string] -> Reduction
;; Lifts a local step into a term step.
(define walk
(case-lambda
[(e1 e2) (walk e1 e2 #f)]
[(e1 e2 note) (make-step e1 e2 (E e1) (E e2) note (big-context))]))
;; walk/foci/E : syntax(s) syntax(s) syntax syntax string -> Reduction
(define (walk/foci/E focus1 focus2 e1 e2 note)
(walk/foci focus1 focus2 (E e1) (E e2) note))
;; walk/foci : syntax(s) syntax(s) syntax syntax string -> Reduction
(define (walk/foci focus1 focus2 Ee1 Ee2 note)
(make-step focus1 focus2 Ee1 Ee2 note (big-context)))
;; stumble : syntax exception -> Reduction
(define (stumble stx exn)
(make-misstep stx (E stx) exn))
;; ------------------------------------
(define (revappend a b)
(cond [(pair? a) (revappend (cdr a) (cons (car a) b))]
[(null? a) b]))
)

View File

@ -0,0 +1,523 @@
(module reductions mzscheme
(require (lib "plt-match.ss")
"stx-util.ss"
"deriv-util.ss"
"context.ss"
"deriv.ss"
"reductions-engine.ss")
(provide reductions
(struct step (redex contractum e1 e2 note lctx))
(struct misstep (redex e1 exn)))
;; Setup for reduction-engines
(define-syntax Expr
(syntax-id-rules ()
[Expr (values reductions deriv-e1 deriv-e2)]))
(define-syntax List
(syntax-id-rules ()
[List (values list-reductions lderiv-es1 lderiv-es2)]))
(define-syntax Block
(syntax-id-rules ()
[Block (values block-reductions bderiv-es1 bderiv-es2)]))
;; Reductions
;; reductions : Derivation -> ReductionSequence
(define (reductions d)
(match d
;; Primitives
[(struct p:variable (e1 e2 rs))
null]
[(IntQ p:module (e1 e2 rs body))
(with-syntax ([(?module name language . BODY) e1])
(let ([ctx (lambda (x) (d->so e1 `(,#'?module ,#'name ,#'language ,x)))]
[body-e1 (match body [($$ deriv (body-e1 _) _) body-e1])])
(cons (walk e1 (ctx body-e1) "Tag #%module-begin")
(with-context ctx
(reductions body)))))]
[(IntQ p:#%module-begin (e1 e2 rs pass1 pass2))
#;(R e1 (?module-begin . MBODY)
[! exni 'blah]
[ModulePass1 MBODY pass1]
=> (lambda (e1prime)
(R e1prime (?module-begin2 . MBODY2)
[ModulePass2 MBODY2 pass2])))
(with-syntax ([(?#%module-begin form ...) e1])
(let-values ([(reductions1 final-stxs1)
(with-context (lambda (x) (d->so e1 (cons #'?#%module-begin x)))
(mbrules-reductions pass1 (syntax->list #'(form ...)) #t))])
(let-values ([(reductions2 final-stxs2)
(with-context (lambda (x) (d->so e1 (cons #'?#%module-begin x)))
(mbrules-reductions pass2 final-stxs1 #f))])
(append reductions1 reductions2))))]
[(AnyQ p:define-syntaxes (e1 e2 rs rhs) exni)
(R e1 _
[! exni]
[#:pattern (?define-syntaxes formals RHS)]
[Expr RHS rhs])]
[(AnyQ p:define-values (e1 e2 rs rhs) exni)
(R e1 _
[! exni]
[#:pattern (?define-values formals RHS)]
[Expr RHS rhs])]
[(AnyQ p:if (e1 e2 rs full? test then else) exni)
(if full?
(R e1 _
[! exni]
[#:pattern (?if TEST THEN ELSE)]
[Expr TEST test]
[Expr THEN then]
[Expr ELSE else])
(R e1 _
[! exni]
[#:pattern (?if TEST THEN)]
[Expr TEST test]
[Expr THEN then]))]
[(AnyQ p:wcm (e1 e2 rs key mark body) exni)
(R e1 _
[! exni]
[#:pattern (?wcm KEY MARK BODY)]
[Expr KEY key]
[Expr MARK mark]
[Expr BODY body])]
[(AnyQ p:begin (e1 e2 rs lderiv) exni)
(R e1 _
[! exni]
[#:pattern (?begin . LDERIV)]
[List LDERIV lderiv])]
[(AnyQ p:begin0 (e1 e2 rs first lderiv) exni)
(R e1 _
[! exni]
[#:pattern (?begin0 FIRST . LDERIV)]
[Expr FIRST first]
[List LDERIV lderiv])]
[(AnyQ p:#%app (e1 e2 rs tagged-stx lderiv) exni)
(let ([tail
(R tagged-stx (?#%app . LDERIV)
[! exni]
[List LDERIV lderiv])])
(if (eq? tagged-stx e1)
tail
(cons (walk e1 tagged-stx "Tag application") tail)))]
[(AnyQ p:lambda (e1 e2 rs renames body) exni)
(R e1 _
[! exni]
[#:bind (?formals* . ?body*) renames]
[#:pattern (?lambda ?formals . ?body)]
[#:walk (syntax/skeleton e1 (?lambda ?formals* . ?body*))
#'?formals #'?formals*
"Rename formal parameters"]
[Block ?body body])
#;
(R e1 _1
[! exni]
=>
(lambda (stx)
(with-syntax ([(?lambda ?formals . ?body) stx]
[(?formals* . ?body*) renames])
(let ([mid (syntax/skeleton e1 (?lambda ?formals* . ?body*))])
(append
(if (stx-pair? #'?formals)
(list (walk/foci/E #'?formals #'?formals* e1 mid
"Rename formal parameters"))
null)
(R mid (LAMBDA FORMALS . BODY)
[Block BODY body]))))))
#;(with-syntax ([(?lambda ?formals . ?body) e1]
[(?formals* . ?body*) renames])
(let ([mid (syntax/skeleton e1 (?lambda ?formals* . ?body*))])
(append
(if (stx-pair? #'?formals)
(list (walk/foci/E #'?formals #'?formals* e1 mid
"Rename formal parameters"))
null)
(R mid (LAMBDA FORMALS . BODY)
[Block BODY body]))))]
[(struct p:case-lambda (e1 e2 rs renames+bodies))
#;
(R e1 _
[! exni]
[#:pattern (?case-lambda [?formals . ?body] ...)]
[#:bind [(?formals* . ?body*) ...] (map car renames+bodies)]
[#:walk (syntax/skeleton e1 (?case-lambda [?formals* . ?body*] ...))
(syntax->list #'(?formals ...))
(syntax->list #'(?formals* ...))
"Rename formal parameters"]
[Block (?body ...) (map cdr renames+bodies)])
(with-syntax ([(?case-lambda [?formals . ?body] ...) e1]
[((?formals* . ?body*) ...) (map car renames+bodies)])
(let ([mid (syntax/skeleton e1 (?case-lambda [?formals* . ?body*] ...))])
(cons (walk/foci/E (syntax->list #'(?formals ...))
(syntax->list #'(?formals* ...))
e1 mid "Rename formal parameters")
(R mid (CASE-LAMBDA [FORMALS . BODY] ...)
[Block (BODY ...) (map cdr renames+bodies)]))))]
[(AnyQ p:let-values (e1 e2 rs renames rhss body) exni)
(R e1 _
[! exni]
[#:pattern (?let-values ([?vars ?rhs] ...) . ?body)]
[#:bind (([?vars* ?rhs*] ...) . ?body*) renames]
[#:walk (syntax/skeleton e1 (?let-values ([?vars* ?rhs*] ...) . ?body*))
(syntax->list #'(?vars ...))
(syntax->list #'(?vars* ...))
"Rename bound variables"]
[Expr (?rhs ...) rhss]
[Block ?body body])
#;
(with-syntax ([(?let-values ([?vars ?rhs] ...) . ?body) e1]
[(([?vars* ?rhs*] ...) . ?body*) renames])
(let ([mid (syntax/skeleton e1 (?let-values ([?vars* ?rhs*] ...) . ?body*))])
(cons (walk/foci/E (syntax->list #'(?vars ...))
(syntax->list #'(?vars* ...))
e1 mid "Rename let-bound variables")
(R mid (LET-VALUES ([VARS RHS] ...) . BODY)
[Expr (RHS ...) rhss]
[Block BODY body]))))]
[(AnyQ p:letrec-values (e1 e2 rs renames rhss body) exni)
(R e1 _
[! exni]
[#:pattern (?letrec-values ([?vars ?rhs] ...) . ?body)]
[#:bind (([?vars* ?rhs*] ...) . ?body*) renames]
[#:walk (syntax/skeleton e1 (?letrec-values ([?vars* ?rhs*] ...) . ?body*))
(syntax->list #'(?vars ...))
(syntax->list #'(?vars* ...))
"Rename bound variables"]
[Expr (?rhs ...) rhss]
[Block ?body body])
#;
(with-syntax ([(?letrec-values ([?vars ?rhs] ...) . ?body) e1]
[(([?vars* ?rhs*] ...) . ?body*) renames])
(let ([mid (syntax/skeleton e1 (?letrec-values ([?vars* ?rhs*] ...) . ?body*))])
(cons (walk/foci/E (syntax->list #'(?vars ...))
(syntax->list #'(?vars* ...))
e1 mid "Rename letrec-bound variables")
(R mid (LETREC-VALUES ([VARS RHS] ...) . BODY)
[Expr (RHS ...) rhss]
[Block BODY body]))))]
[(AnyQ p:letrec-syntaxes+values (e1 e2 rs srenames srhss vrenames vrhss body) exni)
(R e1 _
[! exni]
[#:pattern (?lsv ([?svars ?srhs] ...) ([?vvars ?vrhs] ...) . ?body)]
[#:bind (([?svars* ?srhs*] ...) ([?vvars* ?vrhs] ...) . ?body*) srenames]
[#:walk (syntax/skeleton e1 (?lsv ([?svars* ?srhs*] ...) ([?vvars* ?vrhs*] ...) . ?body*))
(syntax->list #'(?svars ...))
(syntax->list #'(?svars* ...))
"Rename bound variables"]
[Expr (?srhs ...) srhss]
[#:bind (([?vvars** ?vrhs**] ...) . ?body**) vrenames]
[#:walk (syntax/skeleton e1 (?lsv ([?svars* ?srhs*] ...) ([?vars** ?vrhs**] ...) . ?body**))
(syntax->list #'(?vvars* ...))
(syntax->list #'(?vvars** ...))
"Rename bound variables"]
[Expr (?vrhs ...) vrhss]
[Block ?body body]
=> (lambda (mid)
(if (eq? mid e2)
null
(list (walk mid e2 "Remove syntax bindings")))))
#;
(with-syntax ([(?lsv ([?svars ?srhs] ...) ([?vvars ?vrhs] ...) . ?body) e1]
[(([?svars* ?srhs*] ...) ?vpart* . ?body*) srenames])
(with-syntax ([(([?vvars* ?vrhs*] ...) . ?body**)
(or vrenames #'(?vpart* . ?body*))])
(let ([mid (syntax/skeleton
e1
(?lsv ([?svars* ?srhs*] ...) ([?vvars* ?vrhs] ...) . ?body**))])
(cons
(walk/foci/E (syntax->list #'(?svars ... ?vvars ...))
(syntax->list #'(?svars* ... ?vvars* ...))
e1 mid "Rename local variables")
(R mid (LETREC-SYNTAXES+VALUES ([SVARS SRHS] ...) ([VVARS VRHS] ...) . BODY)
[Expr (SRHS ...) srhss]
[Expr (VRHS ...) vrhss]
[Block BODY body]
=> (lambda (mid)
(if (eq? mid e2)
null
(list (walk mid e2 "Finish letrec-syntaxes+values")))))))))]
;; The auto-tagged atomic primitives
[(AnyQ p:#%datum (e1 e2 rs tagged-stx) exni)
(append (if (eq? e1 tagged-stx)
null
(list (walk e1 tagged-stx "Tag datum")))
(if exni
(list (stumble tagged-stx (car exni)))
null))]
[(AnyQ p:#%top (e1 e2 rs tagged-stx) exni)
(append (if (eq? e1 tagged-stx)
null
(list (walk e1 tagged-stx "Tag top-level variable")))
(if exni
(list (stumble tagged-stx (car exni)))
null))]
;; The rest of the automatic primitives
[(AnyQ p::STOP (e1 e2 rs) exni)
(R e1 _
[! exni])]
[(AnyQ p:set!-macro (e1 e2 rs deriv) exni)
(R e1 _
[! exni]
=> (lambda (mid)
(reductions deriv)))]
[(AnyQ p:set! (e1 e2 rs id-rs rhs) exni)
(R e1 _
[! exni]
[#:pattern (SET! VAR RHS)]
[Expr RHS rhs])]
;; Synthetic primitives
;; These have their own subterm replacement mechanisms
[(and d (AnyQ p:synth (e1 e2 rs subterms)))
(let loop ([term e1] [subterms subterms])
(cond [(null? subterms)
(let ([exn (and (error-wrap? d) (error-wrap-exn d))])
(if exn
(list (stumble term exn))
null))]
[(pair? subterms)
(let* ([subterm0 (car subterms)]
[path0 (s:subterm-path subterm0)]
[deriv0 (s:subterm-deriv subterm0)])
(let ([ctx (lambda (x) (path-replace term path0 x))])
(append (with-context ctx
(reductions deriv0))
(loop (path-replace term path0 (deriv-e2 deriv0))
(cdr subterms)))))]))]
;; FIXME
[(IntQ p:rename (e1 e2 rs rename inner))
(reductions inner)]
;; Error
; [(struct error-wrap (exn tag (? prule? prule)))
; ;; Let's take the attitude that all primitive syntax errors
; ;; occur "at the beginning"
; (list (make-misstep (deriv-e1 prule) (E (deriv-e1 prule)) exn))]
;
; #;
; [($$ interrupted-wrap (tag prule))
; (reductions prule orig-stx)]
;; Macros
[(IntQ mrule (e1 e2 transformation next))
(append (reductions-transformation transformation)
(reductions next))]
;; Lifts
[(IntQ lift-deriv (e1 e2 first lifted-stx second))
(append (reductions first)
(list (walk (deriv-e2 first) lifted-stx "Capture lifts"))
(reductions second))]
;; Skipped
[#f null]))
;; reductions-transformation : Transformation -> ReductionSequence
(define (reductions-transformation tx)
(match tx
[(struct transformation (e1 e2 rs me1 me2 locals))
(append (reductions-locals e1 locals)
(list (walk e1 e2 "Macro transformation")))]
[(IntW transformation (e1 e2 rs me1 me2 locals) 'locals)
(reductions-locals e1 locals)]
[(ErrW transformation (e1 e2 rs me1 me2 locals) 'transform exn)
(append (reductions-locals e1 locals)
(list (stumble e1 exn)))]))
;; reductions-locals : syntax (list-of LocalAction) -> ReductionSequence
(define (reductions-locals stx locals)
(with-new-local-context stx
(apply append (map reductions-local locals))))
;; reductions-local : LocalAction -> ReductionSequence
(define (reductions-local local)
(match local
[(IntQ local-expansion (e1 e2 me1 me2 deriv))
(reductions deriv)]
[(struct local-lift (expr id))
(list (walk expr id "Macro lifted expression to top-level"))]
[(struct local-lift-end (decl))
(list (walk decl decl "Declaration lifted to end of module"))]))
;; list-reductions : ListDerivation -> ReductionSequence
(define (list-reductions ld)
(match ld
[(IntQ lderiv (es1 es2 derivs))
(let loop ([derivs derivs] [suffix es1])
(cond [(pair? derivs)
(append
(with-context (lambda (x) (cons x (stx-cdr suffix)))
(reductions (car derivs)))
(with-context (lambda (x) (cons (deriv-e2 (car derivs)) x))
(loop (cdr derivs) (stx-cdr suffix))))]
[(null? derivs)
null]))]
[(ErrW lderiv (es1 es2 derivs) _ exn)
(list (stumble es1 exn))]
[#f null]))
;; block-reductions : BlockDerivation -> ReductionSequence
(define (block-reductions bd)
(match bd
;; If interrupted in pass1, skip pass2
[(IntW bderiv (es1 es2 pass1 trans pass2) 'pass1)
(let-values ([(reductions stxs) (brules-reductions pass1 es1)])
reductions)]
;; Otherwise, do both
[(IntQ bderiv (es1 es2 pass1 trans pass2))
(let-values ([(reductions1 stxs1) (brules-reductions pass1 es1)])
(append reductions1
(if (eq? trans 'letrec)
(match pass2
[($$ lderiv (pass2-es1 _ _) _exni)
(list (walk stxs1 pass2-es1 "Transform block to letrec"))])
null)
(list-reductions pass2)))]
[#f null]))
;; brules-reductions : (list-of-BRule) syntax-list -> ReductionSequence syntax-list
(define (brules-reductions brules all-stxs)
(let loop ([brules brules] [suffix all-stxs] [prefix null] [rss null])
(match brules
[(cons (struct b:expr (renames head)) next)
(let ([estx (deriv-e2 head)])
(loop next (stx-cdr suffix) (cons estx prefix)
(cons (with-context (lambda (x)
(revappend prefix (cons x (stx-cdr suffix))))
(reductions head))
rss)))]
[(cons (IntW b:expr (renames head) tag) '())
(loop '() #f #f
(cons (with-context (lambda (x) (revappend prefix (cons x (stx-cdr suffix))))
(reductions head))
rss))]
[(cons (struct b:defvals (renames head)) next)
(let ([head-rs
(with-context (lambda (x) (revappend prefix (cons x (stx-cdr suffix))))
(reductions head))])
(loop next (stx-cdr suffix) (cons (deriv-e2 head) prefix)
(cons head-rs rss)))]
[(cons ($$ b:defstx (renames head rhs) _exni) next)
(let* ([estx (deriv-e2 head)]
[estx2 (with-syntax ([(?ds ?vars ?rhs) estx]
[?rhs* (deriv-e2 rhs)])
;;FIXME
#'(?ds ?vars ?rhs*))])
(loop next (cdr suffix) (cons estx2 prefix)
(with-context (lambda (x) (revappend prefix (cons x (stx-cdr suffix))))
(cons (with-context (CC (?ds ?vars ?rhs) estx ?rhs)
(reductions rhs))
(cons (reductions head)
rss)))))]
[(cons (struct b:splice (renames head tail)) next)
(loop next tail prefix
(cons (list (walk/foci (deriv-e2 head)
(take-until tail (stx-cdr suffix))
(E (revappend prefix
(cons (deriv-e2 head) (stx-cdr suffix))))
(E (revappend prefix tail))
"Splice block-level begin"))
(cons (with-context (lambda (x)
(revappend prefix (cons x (stx-cdr suffix))))
(reductions head))
rss)))]
[(cons (struct b:begin (renames head derivs)) next)
;; FIXME
(error 'unimplemented)]
[(cons (struct error-wrap (exn tag _inner)) '())
(values (list (make-misstep suffix (E (revappend prefix suffix)) exn))
(revappend prefix suffix))]
['()
(values (apply append (reverse rss))
(revappend prefix suffix))])))
;; mbrules-reductions : MBRules (list-of syntax) -> ReductionSequence
;; The reprocess-on-lift? argument controls the behavior of a mod:lift event.
;; In Pass1, #t; in Pass2, #f.
(define (mbrules-reductions mbrules all-stxs reprocess-on-lift?)
;(printf "**** MB Reductions, pass ~s~n" (if reprocess-on-lift? 1 2))
(let* ([final-stxs #f]
[reductions
(let loop ([mbrules mbrules] [suffix all-stxs] [prefix null])
;(printf "** MB loop~n")
;(printf " rules: ~s~n" mbrules)
;(printf " suffix: ~s~n" suffix)
;(printf " prefix: ~s~n" prefix)
(match mbrules
[(cons ($$ mod:skip ()) next)
(loop next (stx-cdr suffix) (cons (stx-car suffix) prefix))]
[(cons ($$ mod:cons (head) _exni) next)
(append (with-context (lambda (x)
(revappend prefix (cons x (stx-cdr suffix))))
(append (reductions head)))
(let ([estx (and (deriv? head) (deriv-e2 head))])
(loop next (stx-cdr suffix) (cons estx prefix))))]
[(cons ($$ mod:prim (head prim) _exni) next)
(append (with-context (lambda (x)
(revappend prefix (cons x (stx-cdr suffix))))
(if (and prim (not (p:define-values? prim)))
(append (reductions head)
(reductions prim))
(reductions head)))
(let ([estx (and (deriv? head) (deriv-e2 head))])
(loop next (stx-cdr suffix) (cons estx prefix))))]
[(cons ($$ mod:splice (head stxs)) next)
;(printf "suffix is: ~s~n~n" suffix)
;(printf "stxs is: ~s~n" stxs)
(append
(with-context (lambda (x) (revappend prefix (cons x (stx-cdr suffix))))
(reductions head))
(let ([suffix-tail (stx-cdr suffix)]
[head-e2 (deriv-e2 head)])
(cons (walk/foci head-e2
(stx-take stxs
(- (stx-improper-length stxs)
(stx-improper-length suffix-tail)))
(E (revappend prefix (cons head-e2 suffix-tail)))
(E (revappend prefix stxs))
"Splice module-level begin")
(loop next stxs prefix))))]
[(cons ($$ mod:lift (head stxs)) next)
;(printf "suffix is: ~s~n~n" suffix)
;(printf "stxs is: ~s~n" stxs)
(append
(with-context (lambda (x) (revappend prefix (cons x (stx-cdr suffix))))
(reductions head))
(let ([suffix-tail (stx-cdr suffix)]
[head-e2 (deriv-e2 head)])
(let ([new-suffix (append stxs (cons head-e2 suffix-tail))])
(cons (walk/foci null
stxs
(E (revappend prefix (cons head-e2 suffix-tail)))
(E (revappend prefix new-suffix))
"Splice definitions from lifted expressions")
(loop next
new-suffix
prefix)))))]
[(cons ($$ mod:lift-end (tail)) next)
(append
(if (pair? tail)
(list (walk/foci null
tail
(E (revappend prefix suffix))
(E (revappend prefix tail))
"Splice lifted module declarations"))
null)
(loop next tail prefix))]
['()
(set! final-stxs (reverse prefix))
null]))])
(values reductions final-stxs)))
)

View File

@ -0,0 +1,97 @@
(module stx-util mzscheme
(require (lib "stx.ss" "syntax"))
(provide (all-defined)
(all-from (lib "stx.ss" "syntax")))
#;
(define-syntax (CC stx)
(syntax-case stx ()
[(CC HOLE expr pattern)
#'(lambda (in-the-hole)
(with-syntax ([pattern expr])
(with-syntax ([HOLE in-the-hole])
#'pattern)))]))
(define (d->so template datum)
(let ([template (and (syntax? template) #f)])
(datum->syntax-object template datum template template)))
(define-syntax (syntax-copier stx)
(syntax-case stx ()
[(syntax-copier hole expr pattern)
#'(let ([expr-var expr])
(lambda (in-the-hole)
(with-syntax ([pattern expr-var])
(with-syntax ([hole in-the-hole])
(syntax/restamp pattern #'pattern expr-var)))))]))
(define-syntax syntax/skeleton
(syntax-rules ()
[(syntax/skeleton old-expr pattern)
(syntax/restamp pattern #'pattern old-expr)]))
;; FIXME: Need to avoid turning syntax lists into syntax pairs
(define-syntax (syntax/restamp stx)
(syntax-case stx (...)
[(syntax/restamp (pa (... ...)) new-expr old-expr)
#`(let ([new-parts (stx->list new-expr)]
[old-parts (stx->list old-expr)])
(unless (= (length new-parts) (length old-parts))
(printf "** syntax/restamp~n~s~n" (quote-syntax #,stx))
(printf "pattern : ~s~n" (syntax-object->datum #'(pa (... ...))))
(printf "old parts: ~s~n" old-parts)
(printf "new parts: ~s~n" new-parts))
(d->so
old-expr
(map (lambda (new old) (syntax/restamp pa new old))
new-parts
old-parts)))]
#;[(syntax/restamp (pa ...) new-expr old-expr)
(with-syntax ([(na ...) (generate-temporaries #'(pa ...))]
[(oa ...) (generate-temporaries #'(pa ...))])
#'(with-syntax ([(na ...) new-expr]
[(oa ...) old-expr])
(d->so
old-expr
(list (syntax/restamp pa #'na #'oa) ...))))]
[(syntax/restamp (pa . pb) new-expr old-expr)
#'(let ([na (stx-car new-expr)]
[nb (stx-cdr new-expr)]
[oa (stx-car old-expr)]
[ob (stx-cdr old-expr)])
(d->so old-expr
(cons (syntax/restamp pa na oa)
(syntax/restamp pb nb ob))))]
[(syntax/restamp pvar new-expr old-expr)
#'new-expr]))
(define (iota n)
(let loop ([i 0])
(if (< i n)
(cons i (loop (add1 i)))
null)))
;; stx-take : syntax-list number -> (list-of syntax)
(define (stx-take items n)
(cond [(zero? n) null]
[else (cons (stx-car items) (stx-take (stx-cdr items) (sub1 n)))]))
(define *args* #f)
(define (take-until stxs tail)
(set! *args* (list stxs tail))
(let loop ([stxs stxs])
(if (eq? stxs tail)
null
(cons (stx-car stxs) (loop (stx-cdr stxs))))))
(define (stx-improper-length stx)
(if (stx-pair? stx)
(add1 (stx-improper-length (stx-cdr stx)))
0))
)

View File

@ -0,0 +1,37 @@
(module trace-raw mzscheme
(require "../syntax-browser/syntax-browser.ss"
(lib "class.ss")
(lib "lex.ss" "parser-tools")
"deriv-tokens.ss"
"deriv-parser.ss")
(provide (all-defined))
(define current-expand-observe
(dynamic-require '#%expobs 'current-expand-observe))
(define (go-trace sexpr)
(define browser
(parameterize (#;(identifier=-choices
(list (cons "related by table"
(lambda (a b) (related-by-table table a b))))))
(make-syntax-browser)))
(define table #f)
(define pos 0)
(parameterize ((current-expand-observe
(lambda (sig val)
(define t (tokenize sig val pos))
(send browser add-text
(format "Signal: ~s: ~s~n"
pos
(token-name (position-token-token t))))
(send browser add-syntax
(datum->syntax-object #f val))
(set! pos (add1 pos)))))
(expand sexpr)))
(define (related-by-table table a b)
(or (eq? a b)
#;(and table '...)))
)

View File

@ -0,0 +1,79 @@
(module trace mzscheme
(require (lib "lex.ss" "parser-tools")
(lib "class.ss"))
(require "deriv.ss"
"deriv-parser.ss"
"deriv-tokens.ss"
"reductions.ss"
"hide.ss"
"hiding-policies.ss")
(provide trace-verbose?
trace
trace/result
trace+reductions
(all-from "reductions.ss"))
(define current-expand-observe
(dynamic-require '#%expobs 'current-expand-observe))
(define trace-verbose? (make-parameter #f))
;; trace : syntax -> Derivation
(define (trace stx)
(let-values ([(result tracer) (expand+tracer stx)])
(parse-derivation tracer)))
;; trace/result : syntax -> (values syntax/exn Derivation)
(define (trace/result stx)
(let-values ([(result tracer) (expand+tracer stx)])
(values result
(parse-derivation tracer))))
;; trace+reductions : syntax -> ReductionSequence
(define (trace+reductions stx)
(reductions (trace stx)))
;; expand+tracer : syntax/sexpr -> (values syntax/exn (-> event))
(define (expand+tracer sexpr)
(let* ([s (make-semaphore 1)]
[head (cons #f #f)]
[tail head]
[pos 0])
(define (add! x)
(semaphore-wait s)
(set-car! tail x)
(set-cdr! tail (cons #f #f))
(set! tail (cdr tail))
(semaphore-post s))
(define get
(let ([head head])
(lambda ()
(semaphore-wait s)
(let ([result (car head)])
(set! head (cdr head))
(semaphore-post s)
result))))
(parameterize ((current-expand-observe
(lambda (sig val)
(add! (cons sig val)))))
(let ([result
(with-handlers ([(lambda (exn) #t)
(lambda (exn)
(add! (cons 'error exn))
exn)])
(expand sexpr))])
(add! (cons 'EOF pos))
(values result
(lambda ()
(let* ([sig+val (get)]
[sig (car sig+val)]
[val (cdr sig+val)]
[t (tokenize sig val pos)])
(when (trace-verbose?)
(printf "~s: ~s~n" pos (token-name (position-token-token t))))
(set! pos (add1 pos))
t)))))))
)

View File

@ -0,0 +1,44 @@
(module yacc-ext mzscheme
(require (prefix yacc: (lib "yacc.ss" "parser-tools")))
(provide parser
options
productions)
(define-syntax options
(lambda (stx)
(raise-syntax-error #f "options keyword used out of context" stx)))
(define-syntax productions
(lambda (stx)
(raise-syntax-error #f "productions keyword used out of context" stx)))
(define-syntax (parser stx)
(syntax-case stx ()
[(parser form ...)
(let* ([stop-list (list #'begin #'options #'productions)]
[forms (syntax->list #'(form ...))]
[options+productions
(let loop ([forms forms] [opts null] [prods null])
(if (pair? forms)
(let ([eform0 (local-expand (car forms) 'expression stop-list)]
[forms (cdr forms)])
(syntax-case eform0 (begin options productions)
[(begin subform ...)
(loop (append (syntax->list #'(subform ...)) forms) opts prods)]
[(options subform ...)
(loop forms (append (syntax->list #'(subform ...)) opts) prods)]
[(productions subform ...)
(loop forms opts (append (syntax->list #'(subform ...)) prods))]
[else
(raise-syntax-error #f "bad parser subform" eform0)]))
(cons opts (reverse prods))))]
[opts (car options+productions)]
[prods (cdr options+productions)])
(with-syntax ([(opt ...) opts]
[(prod ...) prods])
#'(yacc:parser opt ... (grammar prod ...))))]))
)

View File

@ -0,0 +1,219 @@
(module yacc-interrupted mzscheme
(require "deriv.ss"
"yacc-ext.ss")
(provide ! ?
production/I
productions/I
skipped-token-values
%skipped
%action)
;; Grammar macros for "interrupted parses"
;; Uses interrupted-wrap and error-wrap from deriv.ss
(define-syntax !
(lambda (stx)
(raise-syntax-error #f "keyword ! used out of context" stx)))
(define-syntax ?
(lambda (stx)
(raise-syntax-error #f "keyword ? used out of context" stx)))
(define-syntax (productions/I stx)
(syntax-case stx ()
[(productions/I def ...)
#'(begin (production/I def) ...)]))
(define-for-syntax (partition-options/alternates forms)
(let loop ([forms forms] [options null] [alts null])
(if (pair? forms)
(syntax-case (car forms) ()
[(#:args . args)
(loop (cdr forms) (cons (cons #:args #'args) options) alts)]
[(#:skipped expr)
(loop (cdr forms) (cons (cons #:skipped #'expr) options) alts)]
[(#:no-interrupted)
(loop (cdr forms) (cons (cons #:no-interrupted #t) options) alts)]
[(#:no-wrap)
(loop (cdr forms) (cons (cons #:no-wrap #t) options) alts)]
[(#:no-wrap-error)
(loop (cdr forms) (cons (cons #:no-wrap-error #t) options) alts)]
[(kw . args)
(keyword? (syntax-e #'kw))
(raise-syntax-error #f "bad keyword" (car forms))]
[(pattern action)
(loop (cdr forms) options (cons (cons #'pattern #'action) alts))])
(values options (reverse alts)))))
(define-for-syntax (symbol+ . args)
(define (norm x)
(cond [(identifier? x) (norm (syntax-e x))]
[(string? x) x]
[(number? x) (number->string x)]
[(symbol? x) (symbol->string x)]))
(string->symbol (apply string-append (map norm args))))
(define-for-syntax (I symbol)
(syntax-local-introduce
(syntax-local-get-shadower (datum->syntax-object #f symbol))))
(define-for-syntax (elaborate-skipped-tail head tail action)
(define new-tail
(let loop ([parts tail])
(syntax-case parts (? !)
[() #'()]
[(! . parts-rest) (loop #'((! #f) . parts-rest))]
[((! expr) . parts-rest)
(with-syntax ([NoError (I 'NoError)]
[parts-rest (loop #'parts-rest)])
#'(NoError . parts-rest))]
[((? NT) . parts-rest)
(loop #'((? NT #f) . parts-rest))]
[((? NT expr) . parts-rest)
(loop #'(NT . parts-rest))]
[(part0 . parts-rest)
(identifier? #'part0)
(with-syntax ([part0/Skipped (I (symbol+ #'part0 '/Skipped))]
[parts-rest (loop #'parts-rest)])
#'(part0/Skipped . parts-rest))])))
(with-syntax ([head head]
[new-tail new-tail])
(cons #'(head . new-tail)
action)))
(define-for-syntax (elaborate-successful-alternate alt)
(define pattern (car alt))
(define action (cdr alt))
(cons (let loop ([parts pattern])
(syntax-case parts (? !)
[() #'()]
[(! . parts-rest)
(loop #'((! #f) . parts-rest))]
[((! expr) . parts-rest)
(with-syntax ([NoError (I 'NoError)]
[parts-rest (loop #'parts-rest)])
#'(NoError . parts-rest))]
[((? NT) . parts-rest)
(loop #'((? NT #f) . parts-rest))]
[((? NT expr) . parts-rest)
(with-syntax ([parts-rest (loop #'parts-rest)])
#'(NT . parts-rest))]
[(part0 . parts-rest)
(identifier? #'part0)
(with-syntax ([parts-rest (loop #'parts-rest)])
#'(part0 . parts-rest))]))
action))
(define-for-syntax (elaborate-interrupted-alternate alt wrap? wrap-error?)
(define pattern (car alt))
(define action (cdr alt))
(let loop ([parts pattern] [position 1])
(syntax-case parts (? !)
[()
;; Can't be interrupted
null]
[(! . parts-rest)
(loop #'((! #f) . parts-rest) position)]
[((! expr) . parts-rest)
(cons
;; Error occurs
(with-syntax ([Error (I 'syntax-error #;Error)]
[action action]
[position-argument (I (symbol+ '$ position))])
(elaborate-skipped-tail
#'Error
#'parts-rest
(if wrap-error?
#'(make-error-wrap position-argument expr action)
#'action)))
;; Error doesn't occur
(with-syntax ([NoError (I 'NoError)])
(loop #'(NoError . parts-rest) position)))]
[((? NT) . parts-rest)
(loop #'((? NT #f) . parts-rest) position)]
[((? NT expr) . parts-rest)
(cons
;; NT is interrupted
(with-syntax ([NT/I (I (symbol+ #'NT '/Interrupted))]
[action action])
(elaborate-skipped-tail
#'NT/I
#'parts-rest
(if wrap?
#'(make-interrupted-wrap expr action)
#'action)))
;; NT is not interrupted
(loop #'(NT . parts-rest) position))]
[(part0 . parts-rest)
(identifier? #'part0)
(map (lambda (clause) (cons #`(part0 . #,(car clause)) (cdr clause)))
(loop #'parts-rest (add1 position)))])))
(define-syntax (production/I stx)
(syntax-case stx ()
[(production/I (name form ...))
(let ()
(define-values (options alternates)
(partition-options/alternates (syntax->list #'(form ...))))
(define successful-alternates
(map elaborate-successful-alternate alternates))
(define interrupted-alternates
(apply append
(map (lambda (a)
(elaborate-interrupted-alternate a
(not (assq #:no-wrap options))
(not (assq #:no-wrap-error options))))
alternates)))
(with-syntax ([((success-pattern . success-action) ...)
successful-alternates]
[((interrupted-pattern . interrupted-action) ...)
interrupted-alternates]
[skip-spec (assq #:skipped options)]
[args-spec (assq #:args options)]
[name/Skipped (I (symbol+ #'name '/Skipped))]
[name/Interrupted (I (symbol+ #'name '/Interrupted))]
[%action ((syntax-local-certifier) #'%action)])
#`(begin
(productions
(name [success-pattern
(%action args-spec success-action)]
...)
(name/Skipped [() (%skipped args-spec skip-spec)]))
#,(if (and (not (assq #:no-interrupted options))
(pair? interrupted-alternates))
#'(productions
(name/Interrupted [interrupted-pattern
(%action args-spec interrupted-action)]
...))
#'(begin)))))]))
(define-syntax (skipped-token-values stx)
(syntax-case stx ()
[(skipped-token-values)
#'(begin)]
[(skipped-token-values name . more)
(identifier? #'name)
(with-syntax ([name/Skipped (I (symbol+ #'name '/Skipped))])
#'(begin (productions (name/Skipped [() #f]))
(skipped-token-values . more)))]
[(skipped-token-values (name value) . more)
(with-syntax ([name/Skipped (I (symbol+ #'name '/Skipped))])
#'(begin (productions (name/Skipped [() value]))
(skipped-token-values . more)))]))
(define-syntax (%skipped stx)
(syntax-case stx ()
[(%skipped args (#:skipped . expr))
#'(%action args expr)]
[(%skipped args #f)
#'(%action args #f)]))
(define-syntax (%action stx)
(syntax-case stx ()
[(elaborate-action (#:args . args) action)
#'(lambda args action)]
[(elaborate-action #f action)
#'action]))
)

View File

@ -0,0 +1,7 @@
(module syntax-browser mzscheme
(require "syntax-browser/syntax-browser.ss")
(provide browse-syntax
browse-syntaxes
syntax-snip))

View File

@ -0,0 +1,69 @@
(module controller mzscheme
(require (lib "class.ss")
"interfaces.ss"
"partition.ss"
"properties.ss")
(provide syntax-controller%)
;; syntax-controller%
(define syntax-controller%
(class* object% (syntax-controller<%>
syntax-pp-snip-controller<%>
color-controller<%>)
(define colorers null)
(define selection-listeners null)
(define selected-syntax #f)
(init-field (properties-controller
(new independent-properties-controller% (controller this))))
;; syntax-controller<%> Methods
(define/public (select-syntax stx)
(set! selected-syntax stx)
(send properties-controller set-syntax stx)
(for-each (lambda (c) (send c select-syntax stx)) colorers)
(for-each (lambda (p) (p stx)) selection-listeners))
(define/public (get-selected-syntax)
selected-syntax)
(define/public (get-properties-controller) properties-controller)
(define/public (add-view-colorer c)
(set! colorers (cons c colorers))
(send c select-syntax selected-syntax))
(define/public (get-view-colorers) colorers)
(define/public (add-selection-listener p)
(set! selection-listeners (cons p selection-listeners)))
(define/public (on-update-identifier=? id=?)
(set! -secondary-partition
(and id=? (new partition% (relation id=?))))
(for-each (lambda (c) (send c refresh)) colorers))
(define/public (erase)
(set! colorers null))
;; syntax-pp-snip-controller<%> Methods
(define/public (on-select-syntax stx)
(select-syntax stx))
;; color-controller<%> Methods
(define -primary-partition (new-bound-partition))
(define -secondary-partition #f)
(define/public (get-primary-partition) -primary-partition)
(define/public (get-secondary-partition) -secondary-partition)
;; Initialization
(super-new)
))
)

View File

@ -0,0 +1,34 @@
(module hrule-snip mzscheme
(require (lib "class.ss")
(lib "mred.ss" "mred"))
(provide hrule-snip%)
;; hrule-snip%
;; A snip for drawing horizontal separating lines.
(define hrule-snip%
(class snip%
(inherit get-admin)
(define/override (get-extent dc x y bw bh bdescent bspace blspace brspace)
(let-values [((h) (get-xheight dc))
((fw fh) (send dc get-size))]
(let ([ad-x (box 0)]
[ad-y (box 0)])
(send (get-admin) get-view-size ad-x ad-y)
#;(set-box?! bw fw)
(set-box?! bw (unbox ad-x))
(set-box?! bh h))))
(define/override (draw dc x y left top right bottom dx dy draw-caret)
(let* [(xh (get-xheight dc))
(ny (+ y (/ xh 2)))]
(send dc draw-line x ny right ny)))
(define/private (set-box?! b v)
(when (box? b) (set-box! b v)))
(define/private (get-xheight dc)
(or cached-xheight
(let-values [((w h descent extra) (send dc get-text-extent "x"))]
(set! cached-xheight h)
h)))
(define cached-xheight #f)
(super-new)))
)

View File

@ -0,0 +1,123 @@
(module interfaces mzscheme
(require (lib "class.ss"))
(provide (all-defined))
;; syntax-controller<%>
;; A syntax-controller coordinates state shared by many different syntax views.
;; Syntax views can share:
;; - selection
;; - partitioning configuration
;; - property display
(define syntax-controller<%>
(interface ()
;; select-syntax : syntax -> void
select-syntax
;; get-selected-syntax : -> syntax/#f
get-selected-syntax
;; get-properties-controller : -> syntax-properties-controller<%>
get-properties-controller
;; add-view-colorer : syntax-colorer<%> -> void
add-view-colorer
;; get-view-colorers : -> (list-of syntax-colorer<%>)
get-view-colorers
;; add-selection-listener : syntax -> void
add-selection-listener
))
;; syntax-properties-controller<%>
(define syntax-properties-controller<%>
(interface ()
;; set-syntax : syntax -> void
set-syntax
;; show : boolean -> void
#;show
;; is-shown? : -> boolean
#;is-shown?))
;; syntax-configuration<%>
(define syntax-configuration<%>
(interface ()
;; get-primary-partition : -> partition<%>
get-primary-partition
;; get-secondary-partition : -> partition<%>
get-secondary-partition
;; update-identifier=? : ... -> void
update-identifier=?))
;; syntax-colorer<%>
(define syntax-colorer<%>
(interface ()
select-syntax
apply-styles))
;;----------
;; Convenience widget, specialized for displaying stx and not much else
(define syntax-browser<%>
(interface ()
add-syntax
add-text
add-separator
erase-all
select-syntax
get-text
))
(define partition<%>
(interface ()
;; get-partition : any -> number
get-partition
;; same-partition? : any any -> number
same-partition?
;; count : -> number
count))
;; Internal interfaces
(define syntax-pp-snip-controller<%>
(interface ()
on-select-syntax
))
(define color-controller<%>
(interface ()
get-primary-partition
get-secondary-partition
))
(define syntax-pp<%>
(interface ()
pretty-print-syntax
get-range
get-identifier-list
flat=>stx
stx=>flat))
(define typesetter<%>
(interface ()
get-output-port
get-current-position))
(define range<%>
(interface ()
get-start
set-start
get-ranges
add-range
all-ranges))
)

View File

@ -0,0 +1,160 @@
(module partition mzscheme
(require (lib "class.ss")
(lib "boundmap.ss" "syntax")
(lib "stx.ss" "syntax")
"interfaces.ss")
(provide new-bound-partition
partition%
identifier=-choices)
(define (new-bound-partition)
#;(define p (new partition% (relation id:same-marks?)))
(define p (new bound-partition%))
(send p get-partition (datum->syntax-object #f 'no-marks))
p)
;; representative-symbol : symbol
;; Must be fresh---otherwise, using it could detect rename wraps
;; instead of only marks.
;; For example, in (lambda (representative) representative)
(define representative-symbol
(gensym 'representative))
;; unmarked-syntax : identifier
;; Has no marks---used to initialize bound partition so that
;; unmarked syntax always gets colored "black"
(define unmarked-syntax
(datum->syntax-object #f representative-symbol))
(define partition%
(class* object% (partition<%>)
(init relation)
(define related? relation)
(field (rep=>num (make-hash-table)))
(field (obj=>rep (make-hash-table 'weak)))
(field (reps null))
(field (next-num 0))
(define/public (get-partition obj)
(rep->partition (obj->rep obj)))
(define/public (same-partition? A B)
(= (get-partition A) (get-partition B)))
(define/private (obj->rep obj)
(hash-table-get obj=>rep obj (lambda () (obj->rep* obj))))
(define/public (count)
next-num)
(define/private (obj->rep* obj)
(let loop ([reps reps])
(cond [(null? reps)
(new-rep obj)]
[(related? obj (car reps))
(hash-table-put! obj=>rep obj (car reps))
(car reps)]
[else
(loop (cdr reps))])))
(define/private (new-rep rep)
(hash-table-put! rep=>num rep next-num)
(set! next-num (add1 next-num))
(set! reps (cons rep reps))
rep)
(define/private (rep->partition rep)
(hash-table-get rep=>num rep))
;; Nearly useless as it stands
(define/public (dump)
(hash-table-for-each
rep=>num
(lambda (k v)
(printf "~s => ~s~n" k v))))
(super-new)
))
;; bound-partition%
(define bound-partition%
(class* object% (partition<%>)
;; numbers : bound-identifier-mapping[identifier => number]
(define numbers (make-bound-identifier-mapping))
(define next-number 0)
(define/public (get-partition stx)
(let* ([r (representative stx)]
[n (bound-identifier-mapping-get numbers r (lambda _ #f))])
(or n
(begin0 next-number
(bound-identifier-mapping-put! numbers r next-number)
(set! next-number (add1 next-number))))))
(define/public (same-partition? a b)
(= (get-partition a) (get-partition b)))
(define/public (count)
next-number)
(define/private (representative stx)
(datum->syntax-object stx representative-symbol))
(super-new)))
;; Different identifier relations for highlighting.
(define (lift/rep id=?)
(lambda (A B)
(let ([ra (datum->syntax-object A representative-symbol)]
[rb (datum->syntax-object B representative-symbol)])
(id=? ra rb))))
(define (lift id=?)
(lambda (A B)
(and (identifier? A) (identifier? B) (id=? A B))))
;; id:same-marks? : syntax syntax -> boolean
(define id:same-marks?
(lift/rep bound-identifier=?))
;; id:X-module=? : identifier identifier -> boolean
;; If both module-imported, do they come from the same module?
;; If both top-bound, then same source.
(define (id:source-module=? a b)
(let ([ba (identifier-binding a)]
[bb (identifier-binding b)])
(cond [(or (eq? 'lexical ba) (eq? 'lexical bb))
(module-identifier=? a b)]
[(and (not ba) (not bb))
#t]
[(or (not ba) (not bb))
#f]
[else
(eq? (car ba) (car bb))])))
(define (id:nominal-module=? A B)
(let ([ba (identifier-binding A)]
[bb (identifier-binding B)])
(cond [(or (eq? 'lexical ba) (eq? 'lexical bb))
(module-identifier=? A B)]
[(or (not ba) (not bb))
(and (not ba) (not bb))]
[else (eq? (caddr ba) (caddr bb))])))
(define (symbolic-identifier=? A B)
(eq? (syntax-e A) (syntax-e B)))
(define identifier=-choices
(make-parameter
`(("<nothing>" . #f)
("bound-identifier=?" . ,bound-identifier=?)
("same marks" . ,id:same-marks?)
("module-identifier=?" . ,module-identifier=?)
("module-or-top-identifier=?" . ,module-or-top-identifier=?)
("symbolic-identifier=?" . ,symbolic-identifier=?)
("same source module" . ,id:source-module=?)
("same nominal module" . ,id:nominal-module=?))))
)

View File

@ -0,0 +1,27 @@
(module prefs mzscheme
(require (lib "framework.ss" "framework"))
(provide (all-defined))
(define current-syntax-font-size (make-parameter 16))
(define current-default-columns (make-parameter 40))
(define-syntax pref:get/set
(syntax-rules ()
[(_ get/set prop)
(define get/set
(case-lambda
[() (preferences:get 'prop)]
[(newval) (preferences:set 'prop newval)]))]))
(preferences:set-default 'SyntaxBrowser:Width 700 number?)
(preferences:set-default 'SyntaxBrowser:Height 600 number?)
(preferences:set-default 'SyntaxBrowser:PropertiesPanelPercentage 1/3 number?)
(preferences:set-default 'SyntaxBrowser:PropertiesPanelShown #t boolean?)
(pref:get/set pref:width SyntaxBrowser:Width)
(pref:get/set pref:height SyntaxBrowser:Height)
(pref:get/set pref:props-percentage SyntaxBrowser:PropertiesPanelPercentage)
(pref:get/set pref:props-shown? SyntaxBrowser:PropertiesPanelShown)
)

View File

@ -0,0 +1,81 @@
(module pretty-helper mzscheme
(require (lib "class.ss")
"partition.ss")
(provide (all-defined))
;; Fixme: null object still confusable.
;; Problem: If stx1 and stx2 are two distinguishable syntax objects, it
;; still may be the case that (syntax-e stx1) and (syntax-e stx2) are
;; indistinguishable.
;; Solution: Rather than map stx to (syntax-e stx), in the cases where
;; (syntax-e stx) is confusable, map it to a different, unique, value.
;; - stx is identifier : map it to an uninterned symbol w/ same rep
;; (Symbols are useful: see pretty-print's style table)
;; - else : map it to a syntax-dummy object
(define-struct syntax-dummy (val))
;; syntax->datum/tables : stx [partition% num boolean]
;; -> (values s-expr hashtable hashtable)
;; When partition is not false, tracks the partititions that subterms belong to
;; When limit is a number, restarts processing with numbering? set to true
;; When numbering? is true, suffixes identifiers with partition numbers.
;;
;; Returns three values:
;; - an S-expression
;; - a hashtable mapping S-expressions to syntax objects
;; - a hashtable mapping syntax objects to S-expressions
;; Syntax objects which are eq? will map to same flat values
(define syntax->datum/tables
(case-lambda
[(stx) (table stx #f #f #f)]
[(stx partition limit numbering?) (table stx partition limit numbering?)]))
;; table : syntax partition%-or-#f num-or-#f -> (values s-expr hashtable hashtable)
(define (table stx partition limit numbering?)
(define (make-identifier-proxy id)
(let ([n (send partition get-partition id)])
(cond [(or (zero? n) (not numbering?))
(string->uninterned-symbol (symbol->string (syntax-e id)))]
[else
(string->uninterned-symbol
(format "~a:~a" (syntax-e id) n))])))
(let/ec escape
(let ([flat=>stx (make-hash-table)]
[stx=>flat (make-hash-table)])
(values (let loop ([obj stx])
(cond
[(hash-table-get stx=>flat obj (lambda _ #f))
=> (lambda (datum) datum)]
[(and partition (identifier? obj))
(let ([lp-datum (make-identifier-proxy obj)])
(when (and limit (> (send partition count) limit))
(call-with-values (lambda () (table stx partition #f #t))
escape))
(hash-table-put! flat=>stx lp-datum obj)
(hash-table-put! stx=>flat obj lp-datum)
lp-datum)]
[(syntax? obj)
(void (send partition get-partition obj))
(let ([lp-datum (loop (syntax-e obj))])
(hash-table-put! flat=>stx lp-datum obj)
(hash-table-put! stx=>flat obj lp-datum)
lp-datum)]
[(pair? obj)
(cons (loop (car obj))
(loop (cdr obj)))]
[(vector? obj)
(list->vector (map loop (vector->list obj)))]
[(symbol? obj)
#;(make-syntax-dummy obj)
(string->uninterned-symbol (symbol->string obj))]
[(number? obj)
(make-syntax-dummy obj)]
#;[(null? obj)
(make-syntax-dummy obj)]
[else obj]))
flat=>stx
stx=>flat))))
)

View File

@ -0,0 +1,94 @@
(module pretty-printer mzscheme
(require (lib "list.ss")
(lib "class.ss")
(lib "pretty.ss")
(lib "mred.ss" "mred")
"pretty-range.ss"
"pretty-helper.ss"
"interfaces.ss"
"prefs.ss")
(provide syntax-pp%
(struct range (obj start end)))
;; syntax-pp%
;; Pretty printer for syntax objects.
(define syntax-pp%
(class* object% (syntax-pp<%>)
(init-field main-stx)
(init-field typesetter)
(init-field (primary-partition #f))
(init-field (columns (current-default-columns)))
(unless (syntax? main-stx)
(error 'syntax-snip% "got non-syntax object: ~s" main-stx))
(define datum #f)
(define ht:flat=>stx #f)
(define ht:stx=>flat #f)
(define identifier-list null)
(define -range #f)
(define/public (get-range) -range)
(define/public (get-identifier-list) identifier-list)
(define/public (flat=>stx obj)
(hash-table-get ht:flat=>stx obj))
(define/public (stx=>flat obj)
(hash-table-get ht:stx=>flat obj))
(define/public (pretty-print-syntax)
(define range (new ranges%))
(define (pp-pre-hook obj port)
(send range set-start obj (send typesetter get-current-position)))
(define (pp-post-hook obj port)
(let ([start (send range get-start obj)]
[end (send typesetter get-current-position)])
(when start
(send range add-range
(flat=>stx obj)
(cons start end)))))
(define (pp-size-hook obj display-like? port)
(cond [(is-a? obj editor-snip%)
columns]
[(syntax-dummy? obj)
(let ((ostring (open-output-string)))
((if display-like? display write) (syntax-dummy-val obj) ostring)
(string-length (get-output-string ostring)))]
[else #f]))
(define (pp-print-hook obj display-like? port)
(cond [(syntax-dummy? obj)
((if display-like? display write) (syntax-dummy-val obj) port)]
[(is-a? obj editor-snip%)
(write-special obj port)]
[else
(error 'pretty-print-hook "unexpected special value: ~e" obj)]))
(define (pp-extend-style-table)
(let* ([ids identifier-list]
[syms (map (lambda (x) (stx=>flat x)) ids)]
[like-syms (map syntax-e ids)])
(pretty-print-extend-style-table (pretty-print-current-style-table)
syms
like-syms)))
(parameterize
([pretty-print-pre-print-hook pp-pre-hook]
[pretty-print-post-print-hook pp-post-hook]
[pretty-print-size-hook pp-size-hook]
[pretty-print-print-hook pp-print-hook]
[pretty-print-columns columns]
[pretty-print-current-style-table (pp-extend-style-table)])
(pretty-print datum (send typesetter get-output-port))
(set! -range range)))
;; recompute-tables : -> void
(define/private (recompute-tables)
(set!-values (datum ht:flat=>stx ht:stx=>flat)
(syntax->datum/tables main-stx primary-partition 12 #f))
(set! identifier-list
(filter identifier? (hash-table-map ht:stx=>flat (lambda (k v) k)))))
;; Initialization
(recompute-tables)
(super-new)))
)

View File

@ -0,0 +1,173 @@
(module properties mzscheme
(require "prefs.ss"
"interfaces.ss"
"partition.ss"
"util.ss"
(lib "class.ss")
(lib "mred.ss" "mred"))
(provide properties-view%
independent-properties-controller%)
;; independent-properties-controller%
(define independent-properties-controller%
(class* object% (syntax-properties-controller<%>)
(init-field controller)
;; Properties display
(define parent
(new frame% (label "Properties and Configuration") (height (pref:height))
(width (floor (* (pref:props-percentage) (pref:width))))))
(define choice (new choice% (label "identifer=?") (parent parent)
(choices (map car (identifier=-choices)))
(callback (lambda _ (on-update-identifier=?-choice)))))
(new message% (label " ") (parent parent))
(define pv (new properties-view% (parent parent)))
(define/private (show-properties)
(unless (send parent is-shown?)
(send parent show #t)))
(define/private (on-update-identifier=?-choice)
(let ([id=? (get-identifier=?)])
(send controller on-update-identifier=? id=?)))
(define/private (get-identifier=?)
(cond [(assoc (send choice get-string-selection)
(identifier=-choices))
=> cdr]
[else #f]))
(define/public (set-syntax stx)
(send pv set-syntax stx))
(define/public (show ?)
(send parent show ?))
(define/public (is-shown?)
(send parent is-shown?))
(super-new)))
;; properties-view%
(define properties-view%
(class* object% ()
(init parent)
(define selected-syntax #f)
(define tab-panel (new tab-panel%
(choices (list "Binding" "Source" "Properties"))
(parent parent)
(callback (lambda _ (refresh)))))
(define text (new text%))
(send text set-styles-sticky #f)
(define ecanvas (new editor-canvas% (editor text) (parent tab-panel)))
(define/public (set-syntax stx)
(set! selected-syntax stx)
(refresh))
(define/private (refresh)
(send* text
(lock #f)
(begin-edit-sequence)
(erase))
(when (syntax? selected-syntax)
(let ([s (send tab-panel get-item-label (send tab-panel get-selection))])
(cond [(equal? s "Binding")
(display-binding-info)]
[(equal? s "Source")
(display-source-info)]
[(equal? s "Properties")
(display-properties)])))
(send* text
(end-edit-sequence)
(lock #t)
(scroll-to-position 0)))
(define/private (display-binding-info)
(for-each (lambda (p) (display-binding-kv (car p) ((cdr p) selected-syntax)))
binding-properties))
(define/private (display-binding-kv k v)
(display (format "~a~n" k) key-sd)
(cond [(eq? v 'lexical)
(display "lexical\n" #f)]
[(eq? v #f)
(display "#f (top-level or unbound)\n" #f)]
[(list? v)
(display-subkv "source module" (mpi->string (list-ref v 0)))
(display-subkv "source id" (list-ref v 1))
(display-subkv "nom. module" (mpi->string (list-ref v 2)))
(display-subkv "nom. id" (list-ref v 3))
(if (list-ref v 4)
(display-subkv "phase" "via define-for-syntax"))]
[(void? v)
(display "Not applicable\n" n/a-sd)])
(display "\n" #f))
(define/private (display-subkv k v)
(display (format "~a: " k) sub-key-sd)
(display (format "~a~n" v) #f))
(define/private (display-source-info)
(for-each (lambda (p) (display-subkv (car p) ((cdr p) selected-syntax)))
source-properties))
(define/private (display-properties)
(let ([keys (syntax-property-symbol-keys selected-syntax)])
(if (null? keys)
(display "No properties available" n/a-sd)
(for-each (lambda (k) (display-kv k (syntax-property selected-syntax k)))
keys))))
(define/private (display-kv key value)
(display (format "~a~n" key) key-sd)
(display (format "~s~n~n" value) #f))
(define/private (display item sd)
(let ([p0 (send text last-position)])
(send text insert item)
(let ([p1 (send text last-position)])
(send text change-style sd p0 p1))))
(send text lock #t)
(super-new)))
;; lift/id : (identifier -> void) 'a -> void
(define (lift/id f)
(lambda (stx) (when (identifier? stx) (f stx))))
;; binding-properties : (listof (cons string (syntax -> any)))
(define binding-properties
(list (cons "identifier-binding"
(lift/id identifier-binding))
(cons "identifier-transformer-binding"
(lift/id identifier-transformer-binding))
(cons "identifier-template-binding"
(lift/id identifier-template-binding))))
;; source-properties : (listof (cons string (syntax -> any)))
(define source-properties
(list (cons "syntax-source" syntax-source)
(cons "syntax-source-module"
(lambda (stx) (mpi->string (syntax-source-module stx))))
(cons "syntax-line" syntax-line)
(cons "syntax-position" syntax-position)
(cons "syntax-span" syntax-span)
(cons "syntax-original?" syntax-original?)))
(define key-sd
(let ([sd (new style-delta%)])
(send sd set-delta-foreground "blue")
(send sd set-weight-on 'bold)
sd))
(define sub-key-sd
(let ([sd (new style-delta%)])
(send sd set-delta-foreground "blue")
sd))
(define n/a-sd
(let ([sd (new style-delta%)])
(send sd set-delta-foreground "gray")
sd))
)

View File

@ -0,0 +1,154 @@
(module syntax-snip mzscheme
(require (lib "class.ss")
(lib "mred.ss" "mred")
"interfaces.ss"
"prefs.ss"
"properties.ss"
"typesetter.ss"
"widget.ss"
"partition.ss")
(provide syntax-snip%
super-syntax-snip%)
(define current-syntax-controller (make-parameter #f))
(define (the-syntax-controller)
(let ([controller (current-syntax-controller)])
(or controller
(let ([controller (new syntax-controller%)])
(current-syntax-controller controller)
controller))))
;; syntax-snip%
(define syntax-snip%
(class* editor-snip% ()
(init-field ((stx syntax)))
(init-field controller)
(define -outer (new text%))
(super-new (editor -outer))
;; Initialization
(send -outer begin-edit-sequence)
(initialize -outer)
(outer:insert "Syntax browser" style:bold)
(outer:insert " ")
(outer:insert "Clear" style:hyper
(lambda (x y z) (send controller select-syntax #f)))
(outer:insert " ")
(outer:insert "Properties" style:hyper
(lambda (x y z)
(send (send controller get-properties-controller)
show #t)))
(outer:insert "\n")
(new typesetter-for-text%
(syntax stx)
(controller controller)
(text -outer))
(send -outer lock #t)
(send -outer end-edit-sequence)
(send -outer hide-caret #t)
(define/public (initialize outer)
(void))
(define/private outer:insert
(case-lambda
[(obj)
(outer:insert obj style:normal)]
[(text style)
(outer:insert text style #f)]
[(text style clickback)
(let ([start (send -outer last-position)])
(send -outer insert text)
(let ([end (send -outer last-position)])
(send -outer change-style style start end #f)
(when clickback
(send -outer set-clickback start end clickback))))]))
;; snip% Methods
(define/override (copy)
(new syntax-snip% (controller controller) (syntax stx)))
))
(define subservient-syntax-snip%
(class syntax-snip%
(init-field f)
(define/override (initialize outer)
(f outer))
(super-new)))
(define style:normal (make-object style-delta% 'change-normal))
(define style:hyper
(let ([s (make-object style-delta% 'change-normal)])
(send s set-delta 'change-toggle-underline)
(send s set-delta-foreground "blue")
s))
(define style:bold
(let ([s (make-object style-delta% 'change-normal)])
(send s set-delta 'change-bold)
s))
(define (show-icon) (make-object image-snip% (build-path (collection-path "icons") "turn-up.png")))
(define (hide-icon) (make-object image-snip% (build-path (collection-path "icons") "turn-down.png")))
(define super-syntax-snip%
(class* editor-snip% ()
(init-field ((stx syntax)))
(init-field (controller (the-syntax-controller)))
(define -outer (new text%))
(super-new (editor -outer) (with-border? #f))
(define/private (hide-me)
(send* -outer
(lock #f)
(erase))
(outer:insert (show-icon) style:hyper (lambda _ (show-me)))
(outer:insert "#<syntax>")
(send -outer lock #t))
(define/private (show-me)
(send* -outer
(lock #f)
(erase))
(outer:insert (new subservient-syntax-snip%
(syntax stx)
(controller controller)
(f (lambda (t)
(let* ([start (send t last-position)]
[_ (send t insert (hide-icon))]
[end (send t last-position)])
(send t insert " ")
(send t change-style style:hyper start end #f)
(send t set-clickback start end (lambda _ (hide-me))))))))
(send* -outer
(lock #t)))
(define/private outer:insert
(case-lambda
[(obj)
(outer:insert obj style:normal)]
[(text style)
(outer:insert text style #f)]
[(text style clickback)
(let ([start (send -outer last-position)])
(send -outer insert text)
(let ([end (send -outer last-position)])
(send -outer change-style style start end #f)
(when clickback
(send -outer set-clickback start end clickback))))]))
(define/override (copy)
(new super-syntax-snip% (controller controller) (syntax stx)))
(hide-me)
(send -outer hide-caret #t)
(send -outer lock #t)
))
)

View File

@ -0,0 +1,50 @@
(module util mzscheme
(require (lib "class.ss"))
(provide with-unlock
mpi->string
mpi->list)
(define-syntax with-unlock
(syntax-rules ()
[(with-unlock text . body)
(let* ([t text]
[locked? (send t is-locked?)])
(send t lock #f)
(let () . body)
(send t lock locked?))]))
(define (mpi->string mpi)
(if (module-path-index? mpi)
(let ([mps (mpi->list mpi)])
(cond [(and (pair? mps) (pair? (cdr mps)))
(apply string-append
(format "~s" (car mps))
(map (lambda (x) (format " <= ~s" x)) (cdr mps)))]
[(and (pair? mps) (null? (cdr mps)))
(format "~s" (car mps))]
[(null? mps) "self"]))
(format "~s" mpi)))
(define (mpi->list mpi)
(if mpi
(let-values ([(path rel) (module-path-index-split mpi)])
(if (and (pair? path) (memq (car path) '(file lib planet)))
(cons path null)
(cons path (mpi->list rel))))
'()))
; ;; mpi->string : module-path-index -> string
; ;; Human-readable form of module-path-index
; (define (mpi->string x)
; (cond [(module-path-index? x)
; (let-values ([(path base) (module-path-index-split x)])
; (cond [(eq? path #f)
; "self module"]
; [(eq? base #f)
; (format "top-level => ~a" path)]
; [else
; (format "~a => ~a" (mpi->string base) path)]))]
; [else x]))
)

View File

@ -0,0 +1,184 @@
(module widget mzscheme
(require "interfaces.ss"
"controller.ss"
"typesetter.ss"
"hrule-snip.ss"
"properties.ss"
"partition.ss"
"prefs.ss"
"util.ss"
(lib "list.ss")
(lib "class.ss")
(lib "framework.ss" "framework")
(lib "mred.ss" "mred"))
(provide syntax-controller%
syntax-widget%
syntax-browser-frame%)
;; syntax-widget%
;; A syntax-widget creates its own syntax-controller.
(define syntax-widget%
(class* object% (syntax-browser<%> syntax-properties-controller<%>)
(init parent)
(define -main-panel (new vertical-panel% (parent parent)))
(define -split-panel (new panel:horizontal-dragable% (parent -main-panel)))
(define -text (new text%))
(define -ecanvas (new editor-canvas% (parent -split-panel) (editor -text)))
(define -props-panel (new horizontal-panel% (parent -split-panel)))
(define props (new properties-view% (parent -props-panel)))
(define -saved-panel-percentages #f)
(define controller
(new syntax-controller%
(properties-controller this)))
#;(send -text hide-caret #t)
(send -text lock #t)
(send -split-panel set-percentages
(let ([pp (pref:props-percentage)]) (list (- 1 pp) pp)))
(toggle-props)
;; syntax-properties-controller<%> methods
(define/public (set-syntax stx)
(send props set-syntax stx))
(define/public (show ?)
(if ? (show-props) (hide-props)))
(define/public (is-shown?)
(send -props-panel is-shown?))
(define/public (toggle-props)
(if (send -props-panel is-shown?)
(hide-props)
(show-props)))
(define/public (hide-props)
(when (send -props-panel is-shown?)
(set! -saved-panel-percentages (send -split-panel get-percentages))
(send -split-panel delete-child -props-panel)
(send -props-panel show #f)))
(define/public (show-props)
(unless (send -props-panel is-shown?)
(send -split-panel add-child -props-panel)
(send -split-panel set-percentages -saved-panel-percentages)
(send -props-panel show #t)))
;;
(define/public (get-controller) controller)
;;
(define/public (get-main-panel) -main-panel)
(define/public (on-close)
(unless (= (cadr -saved-panel-percentages) (pref:props-percentage))
(pref:props-percentage (cadr -saved-panel-percentages))))
;; syntax-browser<%> Methods
(define/public (add-text text)
(with-unlock -text
(send -text insert text)))
(define/public add-syntax
(case-lambda
[(stx)
(internal-add-syntax stx null #f)]
[(stx hi-stxs hi-color)
(internal-add-syntax stx hi-stxs hi-color)]))
(define/public (add-separator)
(with-unlock -text
(send* -text
(insert (new hrule-snip%))
(insert "\n"))))
(define/public (erase-all)
(with-unlock -text (send -text erase))
(send controller erase))
(define/public (select-syntax stx)
(send controller select-syntax stx))
(define/public (get-text) -text)
(define/private (internal-add-syntax stx hi-stxs hi-color)
(with-unlock -text
(let ([current-position (send -text last-position)])
(let* ([new-ts (new typesetter-for-text%
(controller controller)
(syntax stx)
(text -text))]
[new-colorer (send new-ts get-colorer)])
(send* -text
(insert "\n")
(scroll-to-position current-position))
(unless (null? hi-stxs)
(send new-colorer highlight-syntaxes hi-stxs hi-color))))))
(super-new)))
;; syntax-widget/controls%
(define syntax-widget/controls%
(class* syntax-widget% ()
(inherit get-main-panel
get-controller
toggle-props)
(super-new)
(define -control-panel
(new horizontal-pane% (parent (get-main-panel)) (stretchable-height #f)))
;; Put the control panel up front
(send (get-main-panel) change-children
(lambda (children)
(cons -control-panel (remq -control-panel children))))
(define -identifier=-choices (identifier=-choices))
(define -choice
(new choice% (label "identifer=?") (parent -control-panel)
(choices (map car -identifier=-choices))
(callback (lambda _ (on-update-identifier=?-choice)))))
(new button%
(label "Clear")
(parent -control-panel)
(callback (lambda _ (send (get-controller) select-syntax #f))))
(new button%
(label "Properties")
(parent -control-panel)
(callback (lambda _ (toggle-props))))
(define/private (on-update-identifier=?-choice)
(let ([id=? (get-identifier=?)])
(send (get-controller) on-update-identifier=? id=?)))
(define/private (get-identifier=?)
(cond [(assoc (send -choice get-string-selection)
-identifier=-choices)
=> cdr]
[else #f]))))
;; syntax-browser-frame%
(define syntax-browser-frame%
(class* frame% ()
(super-new (label "Syntax Browser")
(width (pref:width))
(height (pref:height)))
(define widget (new syntax-widget/controls% (parent this)))
(define/public (get-widget) widget)
(define/augment (on-close)
(pref:width (send this get-width))
(pref:height (send this get-height))
(send widget on-close)
(preferences:save)
(inner (void) on-close))
))
)

View File

@ -0,0 +1,87 @@
(module cursor mzscheme
(provide (all-defined))
;; Cursors
;; (define-struct cursor (v n))
;;
;; (define (cursor:new items)
;; (if (pair? items)
;; (make-cursor (list->vector items) 0)
;; (make-cursor #f #f)))
;;
;; (define (cursor:current c)
;; (when (cursor-n c)
;; (vector-ref (cursor-v c) (cursor-n c))))
;; (define (cursor:move-next c)
;; (when (cursor:can-move-next? c)
;; (set-cursor-n! c (add1 (cursor-n c)))))
;; (define (cursor:move-previous c)
;; (when (cursor:can-move-previous? c)
;; (set-cursor-n! c (sub1 (cursor-n c)))))
;; (define (cursor:move-to-start c)
;; (when (cursor-n c)
;; (set-cursor-n! c 0)))
;; (define (cursor:move-to-end c)
;; (when (cursor-n c)
;; (set-cursor-n! c (sub1 (vector-length (cursor-v c))))))
;;
;; (define (cursor:can-move-next? c)
;; (and (cursor-n c) (< (cursor-n c) (sub1 (vector-length (cursor-v c))))))
;;
;; (define (cursor:can-move-previous? c)
;; (and (cursor-n c) (> (cursor-n c) 0)))
(define-struct cursor (prefix suffixp))
(define (cursor-suffix c)
(if (promise? (cursor-suffixp c))
(force (cursor-suffixp c))
(cursor-suffixp c)))
(define set-cursor-suffix! set-cursor-suffixp!)
(define (cursor:new items)
(if (pair? items)
(make-cursor null items)
; A convenient lie
(make-cursor null (list #f))))
(define (cursor:current c)
(let ([suffix (cursor-suffix c)])
(car suffix)))
(define (cursor:move-to-start c)
(when (cursor:can-move-previous? c)
(cursor:move-previous c)
(cursor:move-to-start c)))
(define (cursor:move-to-end c)
(when (cursor:can-move-next? c)
(cursor:move-next c)
(cursor:move-to-end c)))
(define (cursor:move-previous c)
(when (pair? (cursor-prefix c))
(let ([old-prefix-cell (cursor-prefix c)])
(set-cursor-prefix! c (cdr old-prefix-cell))
(set-cdr! old-prefix-cell (cursor-suffix c))
(set-cursor-suffix! c old-prefix-cell))))
(define (cursor:move-next c)
(when (cursor:can-move-next? c)
(let ([old-suffix-cell (cursor-suffix c)])
(set-cursor-suffix! c (cdr old-suffix-cell))
(set-cdr! old-suffix-cell (cursor-prefix c))
(set-cursor-prefix! c old-suffix-cell))))
(define (cursor:can-move-next? c)
(pair? (cdr (cursor-suffix c))))
(define (cursor:can-move-previous? c)
(pair? (cursor-prefix c)))
)