sexp-diff
8.18
top
← prev up next →

sexp-diffπŸ”— i

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

( sexp-diff e1
e2
[ #:old-markerold-marker
#:new-markernew-marker])sexp?
e1:sexp?
e2:sexp?
old-marker:(or/c any/c (-> any/c list? ))='#:old
new-marker:(or/c any/c (-> any/c list? ))='#:new
Produces a tree that corresponds to the common structure of e1 and e2, with e1-specific parts tagged with old-marker and e2-specific parts tagged with new-marker.

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 .

Examples:
'(define(fx)(+(*x2)1))
'(define(fx)(-(*x2)31)))

'((define (f x) (#:new - #:old + (* x 2) #:new 3 1)))

'(define(fx)(+(*x2)41))
'(define(fx)(-(*x2)531)))

'((define (f x) (#:new - #:old + (* x 2) #:new 5 #:new 3 #:old 4 1)))

'(define(fx)(+(*x2)441))
'(define(fx)(-(*x2)5531)))

'((define (f x)

(#:new - #:old + (* x 2) #:new 5 #:new 5 #:new 3 #:old 4 #:old 4 1)))

#:old-marker'#:expected#:new-marker'#:actual
'(1234)
'(1224))

'((1 #:actual 2 2 #:expected 3 4))

#:old-marker(lambda (x)`((highlight:old,x)))
#:new-marker(lambda (x)`((highlight:new,x)))
'(1234)
'(1224))

'((1 (highlight:new 2) 2 (highlight:old 3) 4))

'((1)234)
'([1]224))

'(((1) #:new 2 2 #:old 3 4))

procedure

( stx-diff e1
e2
[ #:old-markerold-marker
#:new-markernew-marker])syntax?
e1:syntax?
e2:syntax?
old-marker:(or/c any/c (-> any/c syntax? ))='#:old
new-marker:(or/c any/c (-> any/c syntax? ))='#:new
Produces a syntax object that corresponds to the common structure of e1 and e2, with e1-specific parts tagged with old-marker and e2-specific parts tagged with new-marker.

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.

Examples:
#'(define (fx)(+ (* x2)1))
#'(define (fx)(- (* x2)31)))

#<syntax:eval:92:13 ((define (f x) (#:new - #:old + (* x 2) #:new 3 1)))>

#'(define (fx)(+ (* x2)41))
#'(define (fx)(- (* x2)531)))

#<syntax:eval:95:13 ((define (f x) (#:new - #:old + (* x 2) #:new 5 #:new 3 #:old 4 1)))>

#'((1)234)
#'([1]224))

#<syntax:eval:103:14 (((1) #:new 2 2 #:old 3 4))>

> (define x1#'((1)234))
> (define x2#'([1]224))
> x1

#<syntax:eval:104:24 ((1) 2 3 4)>

> x2

#<syntax:eval:105:24 ((1) 2 2 4)>

[((any ... ))
(map (lambda (x)
(format "~a:~a"(syntax-line x)(syntax-column x)))
(attribute any ))])

'("105:25" "#f:#f" "105:29" "105:31" "#f:#f" "104:31" "105:33")

[((headany ... ))
(syntax-property #'head'paren-shape)])

#\[

top
← prev up next →

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /