Vincent St-Amour <stamourv@racket-lang.org>
and William J. Bowman <wjb@williamjbowman.com>
This package provides an S-expression-aware diffing tool based on Levenshtein-like tree edit distance.
procedure
e2[ #:old-markerold-marker#:new-markernew-marker]) → sexp?e1:sexp?e2:sexp?
If either old-marker or new-marker is a procedure? , then it will be called on the node instead of inserted as a literal in the tree. This can be used to replace the node with a new s-expression whose head is the marker, rather than inserting the marker as a sibling of the node, enabling the marker to be interpreted as a function in some DSL. It may make more sense to use this feature in stx-diff .
'((define (f x) (#:new - #:old + (* x 2) #:new 3 1)))
'((define (f x) (#:new - #:old + (* x 2) #:new 5 #:new 3 #:old 4 1)))
'((define (f x)
(#:new - #:old + (* x 2) #:new 5 #:new 5 #:new 3 #:old 4 #:old 4 1)))
'((1 #:actual 2 2 #:expected 3 4))
'(1234)'(1224))'((1 (highlight:new 2) 2 (highlight:old 3) 4))
'(((1) #:new 2 2 #:old 3 4))
The algorithm ignores syntax properties and source location when determining equality, instead comparing up to free-identifier=? , but attempts to reconstruct source locations and syntax properties in the generated syntax object.
If either old-marker or new-marker is a procedure? , then it is in essence a macro that will transformer node instead of inserting a a literal as a sibling in the syntax object. The marker procedure must return a syntax object that represents a list.
#<syntax:eval:92:13 ((define (f x) (#:new - #:old + (* x 2) #:new 3 1)))>
#<syntax:eval:95:13 ((define (f x) (#:new - #:old + (* x 2) #:new 5 #:new 3 #:old 4 1)))>
#<syntax:eval:103:14 (((1) #:new 2 2 #:old 3 4))>
> x1#<syntax:eval:104:24 ((1) 2 3 4)>
> x2#<syntax:eval:105:24 ((1) 2 2 4)>
'("105:25" "#f:#f" "105:29" "105:31" "#f:#f" "104:31" "105:33")
#\[