parent
5c82f510da
commit
94e3de51bd
@ -0,0 +1,16 @@
|
||||
; We'll use the same function as both a keyboard and mouse event
|
||||
; handler. If it's a mouse event, we only want to insert something
|
||||
; on the button-down part
|
||||
(define insert-star
|
||||
(lambda (edit event)
|
||||
(if (or (not (is-a? event wx:mouse-event%))
|
||||
(send event button-down?))
|
||||
(send edit insert "*"))
|
||||
#t))
|
||||
|
||||
(let ((kmap (send mred:console-edit get-keymap)))
|
||||
(send kmap add-key-function "insert-star" insert-star)
|
||||
(send kmap add-mouse-function "insert-star" insert-star)
|
||||
(send kmap map-function "c:." "insert-star")
|
||||
(send kmap map-function "ESC;rightbutton" "insert-star"))
|
||||
|
@ -0,0 +1,2 @@
|
||||
|
||||
(load "demo.ss")
|
Binary file not shown.
@ -0,0 +1,379 @@
|
||||
|
||||
(require-library "macro.ss")
|
||||
|
||||
(define TILE-HW 24)
|
||||
(define WIDTH 16)
|
||||
(define HEIGHT 16)
|
||||
(define BOMB-COUNT 30)
|
||||
|
||||
; Temporary
|
||||
(define FRDW 12)
|
||||
(define FRDH 39)
|
||||
(define PANEL-HEIGHT 50)
|
||||
(define TIME-WIDTH 600)
|
||||
(define COUNT-WIDTH 600)
|
||||
|
||||
(define DIGIT-COLOR-NAMES
|
||||
; 0th is background; 8th is foreground
|
||||
(vector "LIGHT GREY" "BLUE" "GREEN" "RED" "PURPLE" "ORANGE" "YELLOW" "BROWN" "BLACK"))
|
||||
|
||||
(define DIGIT-COLORS
|
||||
(build-vector 9 (lambda (i)
|
||||
(send wx:the-colour-database find-colour
|
||||
(vector-ref DIGIT-COLOR-NAMES i)))))
|
||||
|
||||
(define BG-COLOR (vector-ref DIGIT-COLORS 0))
|
||||
(define FG-COLOR (vector-ref DIGIT-COLORS 8))
|
||||
(define EXPLODE-COLOR (send wx:the-colour-database find-colour "RED"))
|
||||
|
||||
(define BG-PEN (send wx:the-pen-list find-or-create-pen BG-COLOR 1 wx:const-solid))
|
||||
(define FG-PEN (send wx:the-pen-list find-or-create-pen FG-COLOR 1 wx:const-solid))
|
||||
|
||||
(define step-while
|
||||
(opt-lambda (first test until step f [accum void] [init (void)])
|
||||
(let loop ([n first][a init])
|
||||
(if (test n until)
|
||||
(loop (step n) (accum a (f n)))
|
||||
a))))
|
||||
|
||||
(define tile:plain%
|
||||
(class null ()
|
||||
(private
|
||||
[state 'covered]
|
||||
[neighbor-bomb-count 0])
|
||||
(public
|
||||
[set-state
|
||||
(lambda (newstate)
|
||||
(set! state newstate))]
|
||||
[get-state
|
||||
(lambda ()
|
||||
state)]
|
||||
[set-neighbor-bomb-count
|
||||
(lambda (c)
|
||||
(set! neighbor-bomb-count c))]
|
||||
[get-neighbor-bomb-count
|
||||
(lambda ()
|
||||
neighbor-bomb-count)]
|
||||
[draw-text-tile
|
||||
(lambda (dc x y w h hilite? border? str color)
|
||||
(if border?
|
||||
(send dc set-pen FG-PEN)
|
||||
(send dc set-pen BG-PEN))
|
||||
(send dc draw-rectangle x y w h)
|
||||
(when hilite?
|
||||
(send dc draw-rectangle
|
||||
(add1 x) (add1 y)
|
||||
(- w 2) (- h 2)))
|
||||
(when str
|
||||
(if color
|
||||
(send dc set-text-foreground color)
|
||||
(send dc set-text-foreground FG-COLOR))
|
||||
(let ([tw (box 0)][th (box 0)])
|
||||
(send dc get-text-extent str tw th)
|
||||
(send dc draw-text str
|
||||
(+ x (/ (- w (unbox tw)) 2))
|
||||
(+ y (/ (- h (unbox th)) 2))))))]
|
||||
[draw
|
||||
(lambda (dc x y w h hilite?)
|
||||
(case state
|
||||
[(covered) (draw-text-tile dc x y w h hilite? #t #f #f)]
|
||||
[(flagged) (draw-text-tile dc x y w h hilite? #t "X" #f)]
|
||||
[(semi-flagged) (draw-text-tile dc x y w h hilite? #t "?" #f)]
|
||||
[(uncovered) (draw-text-tile
|
||||
dc x y w h #f #f
|
||||
(if (zero? neighbor-bomb-count)
|
||||
#f
|
||||
(number->string neighbor-bomb-count))
|
||||
(vector-ref DIGIT-COLORS neighbor-bomb-count))]))])))
|
||||
|
||||
(define tile:bomb%
|
||||
(class tile:plain% ()
|
||||
(inherit get-state draw-text-tile)
|
||||
(rename [super-draw draw])
|
||||
(private
|
||||
[explode-source? #f])
|
||||
(public
|
||||
[set-explode-source
|
||||
(lambda (s?)
|
||||
(set! explode-source? s?))]
|
||||
[draw
|
||||
(lambda (dc x y w h hilite?)
|
||||
(if (eq? (get-state) 'uncovered)
|
||||
(draw-text-tile dc x y w h #f #f "*"
|
||||
(and explode-source? EXPLODE-COLOR))
|
||||
(super-draw dc x y w h hilite?)))])
|
||||
(sequence
|
||||
(super-init))))
|
||||
|
||||
(define (get-tile b x y)
|
||||
(vector-ref (vector-ref b x) y))
|
||||
|
||||
(define (set-tile! b x y t)
|
||||
(vector-set! (vector-ref b x) y t))
|
||||
|
||||
(define (do-surrounding b x y accum start default f)
|
||||
(step-while -1 <= 1 add1
|
||||
(lambda (dx)
|
||||
(step-while -1 <= 1 add1
|
||||
(lambda (dy)
|
||||
(if (and (not (and (zero? dx) (zero? dy)))
|
||||
(< -1 (+ x dx) WIDTH)
|
||||
(< -1 (+ y dy) HEIGHT))
|
||||
(f dx dy)
|
||||
default))
|
||||
accum start))
|
||||
accum start))
|
||||
|
||||
(define (is-bomb? x)
|
||||
(is-a? x tile:bomb%))
|
||||
|
||||
(define (count-surrounding-bombs b x y)
|
||||
(do-surrounding
|
||||
b x y + 0 0
|
||||
(lambda (dx dy)
|
||||
(if (is-bomb? (get-tile b (+ x dx) (+ y dy)))
|
||||
1
|
||||
0))))
|
||||
|
||||
(define (for-each-tile b f)
|
||||
(step-while 0 < WIDTH add1
|
||||
(lambda (x)
|
||||
(step-while 0 < HEIGHT add1
|
||||
(lambda (y)
|
||||
(f (get-tile b x y) x y))))))
|
||||
|
||||
(define (make-board)
|
||||
(let ([b (build-vector WIDTH
|
||||
(lambda (i)
|
||||
(build-vector HEIGHT
|
||||
(lambda (j)
|
||||
(make-object tile:plain%)))))])
|
||||
(let loop ([n BOMB-COUNT])
|
||||
(unless (zero? n)
|
||||
(let rloop ()
|
||||
(let* ([x (random WIDTH)]
|
||||
[y (random HEIGHT)]
|
||||
[t (get-tile b x y)])
|
||||
(if (is-a? t tile:bomb%)
|
||||
(rloop)
|
||||
(begin
|
||||
(set-tile! b x y (make-object tile:bomb%))
|
||||
(loop (sub1 n))))))))
|
||||
(for-each-tile b (lambda (t x y)
|
||||
(send t
|
||||
set-neighbor-bomb-count
|
||||
(count-surrounding-bombs b x y))))
|
||||
b))
|
||||
|
||||
(define f (make-object mred:frame% null "Minesweeper"))
|
||||
(define vpanel (make-object mred:vertical-panel% f))
|
||||
|
||||
(define ms:canvas%
|
||||
(class mred:canvas% args
|
||||
(inherit get-dc clear
|
||||
set-min-width set-min-height
|
||||
stretchable-in-x stretchable-in-y)
|
||||
(private
|
||||
[panel (make-object mred:horizontal-panel% vpanel)])
|
||||
(sequence
|
||||
(send panel stretchable-in-y #f))
|
||||
(private
|
||||
[lspace (make-object mred:vertical-panel% panel)]
|
||||
[time (make-object mred:message% panel "Time: 00000")]
|
||||
[lmspace (make-object mred:vertical-panel% panel)]
|
||||
[button (make-object mred:button% panel (lambda (b e) (reset)) "Reset")]
|
||||
[rmspace (make-object mred:vertical-panel% panel)]
|
||||
[count (make-object mred:message% panel "Count: 000")]
|
||||
[rspace (make-object mred:vertical-panel% panel)]
|
||||
|
||||
[set-time
|
||||
(lambda (t)
|
||||
(send time set-label (string-append "Time: " (number->string t))))]
|
||||
[set-count
|
||||
(lambda (c)
|
||||
(send count set-label (string-append "Bombs: " (number->string c))))]
|
||||
|
||||
[clicking #f]
|
||||
[clicking-x 0]
|
||||
[clicking-y 0]
|
||||
[ready? #t]
|
||||
[start-time #f]
|
||||
[elapsed-time 0]
|
||||
[timer #f]
|
||||
[bomb-count BOMB-COUNT]
|
||||
[cover-count (* HEIGHT WIDTH)]
|
||||
[board null])
|
||||
(public
|
||||
(stop-timer
|
||||
(lambda ()
|
||||
(when timer
|
||||
(send timer stop)
|
||||
(set! timer #f))))
|
||||
(start-timer
|
||||
(lambda ()
|
||||
(set! start-time (current-seconds))
|
||||
(set! timer
|
||||
(make-object
|
||||
(class-asi wx:timer%
|
||||
(public
|
||||
[notify
|
||||
(lambda ()
|
||||
(let ([e (- (current-seconds) start-time)])
|
||||
(when (> e elapsed-time)
|
||||
(set! elapsed-time e)
|
||||
(set-time e))))]))))
|
||||
(send timer start 100 #f)))
|
||||
(end-of-game
|
||||
(lambda (win?)
|
||||
(stop-timer)
|
||||
(set! ready? #f)
|
||||
(set! start-time #f)
|
||||
(unless win?
|
||||
(show-all-bombs))
|
||||
(set-count BOMB-COUNT)))
|
||||
(explode
|
||||
(lambda ()
|
||||
(end-of-game #f)))
|
||||
(win
|
||||
(lambda ()
|
||||
(end-of-game #t)))
|
||||
(reset
|
||||
(lambda ()
|
||||
(stop-timer)
|
||||
(set! ready? #t)
|
||||
(set! start-time #f)
|
||||
(set! elapsed-time 0)
|
||||
(set! cover-count (* HEIGHT WIDTH))
|
||||
(clear)
|
||||
(set-time 0)
|
||||
(set! bomb-count BOMB-COUNT)
|
||||
(set-count BOMB-COUNT)
|
||||
(set! board (make-board))
|
||||
(on-paint)))
|
||||
(show-all-bombs
|
||||
(lambda ()
|
||||
(for-each-tile board
|
||||
(lambda (t x y)
|
||||
(when (is-bomb? t)
|
||||
(change-state t (send t get-state) 'uncovered #f)
|
||||
(paint-one t x y))))))
|
||||
(autoclick-surrounding
|
||||
(lambda (x y)
|
||||
(do-surrounding
|
||||
board x y void (void) (void)
|
||||
(lambda (dx dy)
|
||||
(let* ([x2 (+ x dx)]
|
||||
[y2 (+ y dy)]
|
||||
[t (get-tile board x2 y2)]
|
||||
[state (send t get-state)]
|
||||
[nc (send t get-neighbor-bomb-count)])
|
||||
(unless (eq? state 'uncovered)
|
||||
(change-state t state 'uncovered #t)
|
||||
(paint-one t x2 y2)
|
||||
(when (zero? nc)
|
||||
(autoclick-surrounding x2 y2))))))))
|
||||
(change-state
|
||||
(lambda (t old-state new-state update-count?)
|
||||
(send t set-state new-state)
|
||||
(when (and update-count? (not (eq? new-state old-state)))
|
||||
(when (eq? new-state 'uncovered)
|
||||
(set! cover-count (sub1 cover-count)))
|
||||
(when (eq? old-state 'uncovered)
|
||||
(set! cover-count (add1 cover-count)))
|
||||
(when (eq? new-state 'flagged)
|
||||
(set! bomb-count (sub1 bomb-count))
|
||||
(set-count bomb-count))
|
||||
(when (eq? old-state 'flagged)
|
||||
(set! bomb-count (add1 bomb-count))
|
||||
(set-count bomb-count)))))
|
||||
(do-select
|
||||
(lambda (x y flag?)
|
||||
(let* ([t (get-tile board x y)]
|
||||
[state (send t get-state)]
|
||||
[new-state
|
||||
(case state
|
||||
[(covered)
|
||||
(if flag? 'flagged 'uncovered)]
|
||||
[(flagged)
|
||||
(if flag? 'semi-flagged state)]
|
||||
[(semi-flagged)
|
||||
(if flag? 'covered 'uncovered)]
|
||||
[else state])]
|
||||
[nc (send t get-neighbor-bomb-count)]
|
||||
[new-uncover? (and (eq? new-state 'uncovered)
|
||||
(not (eq? state 'uncovered)))]
|
||||
[bomb? (is-bomb? t)])
|
||||
(change-state t state new-state #t)
|
||||
(when (and new-uncover? bomb?)
|
||||
(send t set-explode-source #t))
|
||||
(paint-one t x y)
|
||||
(when new-uncover?
|
||||
(if bomb?
|
||||
(explode)
|
||||
(begin
|
||||
(when (zero? nc)
|
||||
(autoclick-surrounding x y))))
|
||||
(when (and ready? (= cover-count BOMB-COUNT))
|
||||
(win))))))
|
||||
(on-event
|
||||
(lambda (e)
|
||||
(when ready?
|
||||
(unless start-time
|
||||
(when (send e button-down?)
|
||||
(start-timer)))
|
||||
(let* ([x (quotient (inexact->exact (floor (send e get-x))) TILE-HW)]
|
||||
[y (quotient (inexact->exact (floor (send e get-y))) TILE-HW)]
|
||||
[t (if (and (< -1 x WIDTH)
|
||||
(< -1 y HEIGHT))
|
||||
(get-tile board x y)
|
||||
#f)])
|
||||
(cond
|
||||
[(and clicking (or (not (eq? t clicking))
|
||||
(not (or (send e button-up?)
|
||||
(send e dragging?)))))
|
||||
(let ([old clicking])
|
||||
(set! clicking #f)
|
||||
(paint-one old clicking-x clicking-y))]
|
||||
[(and t
|
||||
(not (eq? (send t get-state) 'uncovered))
|
||||
(or (send e button-down?)
|
||||
(and (send e dragging?)
|
||||
(= x clicking-x)
|
||||
(= y clicking-y))))
|
||||
(set! clicking t)
|
||||
(set! clicking-x x)
|
||||
(set! clicking-y y)
|
||||
(paint-one t x y)]
|
||||
[(send e button-down?) ; click not on a tile
|
||||
(set! clicking-x -1)]
|
||||
[(and clicking (send e button-up?))
|
||||
(set! clicking #f)
|
||||
(do-select x y (send e button-up? 3))]
|
||||
[else 'ok])))))
|
||||
(paint-one
|
||||
(lambda (t x y)
|
||||
(let ([xloc (* x TILE-HW)]
|
||||
[yloc (* y TILE-HW)])
|
||||
(send t draw dc xloc yloc TILE-HW TILE-HW
|
||||
(eq? t clicking)))))
|
||||
(on-paint
|
||||
(lambda ()
|
||||
(for-each-tile board (lambda (t x y)
|
||||
(paint-one t x y))))))
|
||||
(sequence
|
||||
(apply super-init args)
|
||||
(set-min-width (* TILE-HW WIDTH))
|
||||
(set-min-height (* TILE-HW HEIGHT))
|
||||
(stretchable-in-x #f)
|
||||
(stretchable-in-y #f))
|
||||
(private
|
||||
[dc (get-dc)])
|
||||
(sequence
|
||||
(reset)
|
||||
(send dc set-text-background BG-COLOR)
|
||||
(send dc set-brush (send wx:the-brush-list find-or-create-brush
|
||||
BG-COLOR wx:const-solid)))))
|
||||
|
||||
(define c (make-object ms:canvas% vpanel))
|
||||
|
||||
(send f show #t)
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
(load-relative (build-path "morph" "load.ss"))
|
@ -0,0 +1,57 @@
|
||||
(define 2d-vector%
|
||||
(make-class ()
|
||||
(private
|
||||
[default? #f]
|
||||
[default (void)]
|
||||
[vec (void)]
|
||||
[found-error
|
||||
(lambda (x w h)
|
||||
(error '2d-vector% "~s out of bounds: ~s ~s; array size ~sx~s"
|
||||
x w h width height))]
|
||||
[index (lambda (w h) (+ (* h width) w))])
|
||||
(public
|
||||
[height (void)]
|
||||
[width (void)]
|
||||
[set-default
|
||||
(lambda (d)
|
||||
(set! default? #t)
|
||||
(set! default d))]
|
||||
[no-default (lambda () (set! default? #f))]
|
||||
[straighten (lambda () vec)]
|
||||
[bend (lambda (list)
|
||||
(when (not (list? list))
|
||||
(error '2d-vector%
|
||||
"bend expected a list, found: ~s" list))
|
||||
(when (not (= (length list) (* height width)))
|
||||
(error '2d-vector%
|
||||
(string-append "attempted to bend a list of length ~s,"
|
||||
" should have length ~s")
|
||||
(length list) (* height width)))
|
||||
(set! vec (list->vector list)))]
|
||||
[update (lambda (w h v)
|
||||
(let ([w (floor w)]
|
||||
[h (floor h)])
|
||||
(debug-print 2d-vector% 'width width 'height height w h
|
||||
'index (index w h))
|
||||
(if (and (<= 0 w) (< w width) (<= 0 h) (< h height))
|
||||
(vector-set! vec (index w h) v)
|
||||
(found-error 'update w h))))]
|
||||
[lookup (lambda (w h)
|
||||
(let ([w (floor w)]
|
||||
[h (floor h)])
|
||||
(debug-print 2d-vector% 'width width 'height height w h
|
||||
'index (index w h))
|
||||
(if (and (<= 0 w) (< w width) (<= 0 h) (< h height))
|
||||
(vector-ref vec (index w h))
|
||||
(if default?
|
||||
default
|
||||
(found-error 'lookup w h)))))])
|
||||
(lambda (w h v)
|
||||
(if (and (integer? w) (integer? h))
|
||||
(begin
|
||||
(set! width w)
|
||||
(set! height h)
|
||||
(set! vec (make-vector (* w h) v)))
|
||||
(error '2d-vector%
|
||||
"received w = ~s and h = ~s; both must should be integral"
|
||||
w h)))))
|
@ -0,0 +1,96 @@
|
||||
;;; this file sets up coordinates
|
||||
|
||||
;; bary represents just a three tuple of coordinates, not necessarily
|
||||
;; with respect to some triangle.
|
||||
(define-struct bary (a b c))
|
||||
(define show-bary
|
||||
(let ([shorten (lambda (x) (/ (floor (* x 100)) 100))])
|
||||
(lambda (p)
|
||||
(printf "#<str:bary ~s ~s ~s>"
|
||||
(shorten (bary-a p))
|
||||
(shorten (bary-b p))
|
||||
(shorten (bary-c p))))))
|
||||
|
||||
(define-struct posn (x y))
|
||||
(define show-posn
|
||||
(let ([shorten (lambda (x) (/ (floor (* x 10)) 10))])
|
||||
(lambda (p)
|
||||
(printf "#<str:posn ~s ~s>"
|
||||
(shorten (posn-x p))
|
||||
(shorten (posn-y p))))))
|
||||
|
||||
(define-struct tri (a b c area))
|
||||
(define build-tri
|
||||
(lambda (a b c)
|
||||
(make-tri a b c (find-area a b c))))
|
||||
|
||||
(define posn-minus
|
||||
(lambda (p q)
|
||||
(make-posn (- (posn-x p) (posn-x q))
|
||||
(- (posn-y p) (posn-y q)))))
|
||||
|
||||
(define bary-minus
|
||||
(lambda (p1 p2)
|
||||
(make-bary (- (bary-a p1) (bary-a p2))
|
||||
(- (bary-b p1) (bary-b p2))
|
||||
(- (bary-c p1) (bary-c p2)))))
|
||||
|
||||
(define square (lambda (x) (* x x)))
|
||||
|
||||
(define norm
|
||||
(lambda (b)
|
||||
(+ (square (bary-a b))
|
||||
(square (bary-b b))
|
||||
(square (bary-c a)))))
|
||||
|
||||
(define find-area
|
||||
(let ([helper
|
||||
(lambda (p q)
|
||||
(let ([sroot (- (* (posn-y p) (posn-x q))
|
||||
(* (posn-x p) (posn-y q)))])
|
||||
(/ (abs sroot) 2)))])
|
||||
(lambda (p1 p2 p3)
|
||||
(helper (posn-minus p1 p2) (posn-minus p1 p3)))))
|
||||
|
||||
(define find-barycentric
|
||||
(lambda (p1 p2 p3 p)
|
||||
(find-barycentric-area (build-tri p1 p2 p3) p)))
|
||||
|
||||
(define find-barycentric-area
|
||||
(lambda (tri p)
|
||||
(let* ([p1 (tri-a tri)]
|
||||
[p2 (tri-b tri)]
|
||||
[p3 (tri-c tri)]
|
||||
[area (tri-area tri)]
|
||||
[little-area/big-area
|
||||
(lambda (p q)
|
||||
(let ([sroot (- (* (posn-y p) (posn-x q))
|
||||
(* (posn-x p) (posn-y q)))])
|
||||
(/ sroot area 2)))]
|
||||
[p1-p (posn-minus p1 p)]
|
||||
[p2-p (posn-minus p2 p)]
|
||||
[p3-p (posn-minus p3 p)])
|
||||
(make-bary (little-area/big-area p2-p p3-p)
|
||||
(little-area/big-area p3-p p1-p)
|
||||
(little-area/big-area p1-p p2-p)))))
|
||||
|
||||
(define find-euclid
|
||||
(lambda (tri b)
|
||||
(let ([p1 (tri-a tri)]
|
||||
[p2 (tri-b tri)]
|
||||
[p3 (tri-c tri)]
|
||||
[a (bary-a b)]
|
||||
[b (bary-b b)]
|
||||
[c (bary-c b)])
|
||||
(make-posn (+ (* a (posn-x p1))
|
||||
(* b (posn-x p2))
|
||||
(* c (posn-x p3)))
|
||||
(+ (* a (posn-y p1))
|
||||
(* b (posn-y p2))
|
||||
(* c (posn-y p3)))))))
|
||||
|
||||
(define distance-sq
|
||||
(lambda (p q)
|
||||
(let ([x-delta (- (posn-x p) (posn-x q))]
|
||||
[y-delta (- (posn-y p) (posn-y q))])
|
||||
(+ (* x-delta x-delta) (* y-delta y-delta)))))
|
@ -0,0 +1,57 @@
|
||||
(define debug-on? (lambda (type) #f))
|
||||
|
||||
(define debug-on? (lambda (type) #t))
|
||||
|
||||
(define debug-on?
|
||||
(lambda (type)
|
||||
(case type
|
||||
[(2d-vector%) #f]
|
||||
[(engine) #t]
|
||||
[(graph) #f]
|
||||
[(main) #t]
|
||||
[(mesh%) #t]
|
||||
[(pager%) #t]
|
||||
[else #t])))
|
||||
|
||||
(defmacro debug-print (type . args)
|
||||
(if (debug-on? type)
|
||||
`(begin
|
||||
(display (quote ,type))
|
||||
(display ": ")
|
||||
(debug-print-function ,@args))
|
||||
'(void)))
|
||||
|
||||
(define debug-print-function
|
||||
(letrec ([debug-print-one
|
||||
(lambda (x)
|
||||
(cond
|
||||
[(list? x) (debug-print-list x)]
|
||||
[(pair? x) (display "(")
|
||||
(debug-print-one (car x))
|
||||
(display " . ")
|
||||
(debug-print-one (cdr x))
|
||||
(display ")")]
|
||||
[(posn? x) (show-posn x)]
|
||||
[(bary? x) (show-bary x)]
|
||||
; [(3vector? x) (show-3vector x)]
|
||||
; [(intersection? x) (show-intersection x)]
|
||||
[else (display x)]))]
|
||||
[debug-print-list-innards
|
||||
(lambda (list)
|
||||
(cond
|
||||
[(null? list) (void)]
|
||||
[(null? (cdr list)) (debug-print-one (car list))]
|
||||
[else (debug-print-one (car list))
|
||||
(display " ")
|
||||
(debug-print-list-innards (cdr list))]))]
|
||||
[debug-print-list
|
||||
(lambda (x)
|
||||
(display "(")
|
||||
(debug-print-list-innards x)
|
||||
(display ")"))])
|
||||
(lambda args
|
||||
(debug-print-list-innards args)
|
||||
(newline)
|
||||
(flush-output)
|
||||
(void))))
|
||||
|
@ -0,0 +1,154 @@
|
||||
|
||||
;; a mesh is a graph of the connectivities of the points.
|
||||
(define-struct mesh (index children))
|
||||
|
||||
;; an image is a 2d array of color values, all of which are between
|
||||
;; one and zero.
|
||||
|
||||
|
||||
;; input:
|
||||
;; src-verticies: the positions in the mesh where the
|
||||
;; verticies are in the src image.
|
||||
;; src-img: the source image
|
||||
;; dest-verticies: the positions in the mesh where the
|
||||
;; verticies are in the dest image.
|
||||
;; src-img: the destination image
|
||||
;; w: a constant between zero and one indicating how far the morph between
|
||||
;; the images.
|
||||
;;
|
||||
;; It returns a function which computes the color value for the pixel
|
||||
;; x and y, which should be a number between one and zero.
|
||||
|
||||
|
||||
|
||||
(define engine-simple
|
||||
(lambda (mesh src-lookup dest-lookup w)
|
||||
(lambda (x y)
|
||||
(let ([scale-pt (+ (* w (src-lookup x y))
|
||||
(* (- 1 w) (dest-lookup x y)))]
|
||||
[x (- (/ (random 101) 400) 1/8)])
|
||||
(max 0 (min 1 (+ scale-pt x)))))))
|
||||
|
||||
(define ormap-count 'uhoh)
|
||||
|
||||
(define ormap-debug
|
||||
(lambda (f list)
|
||||
(letrec ([helper
|
||||
(lambda (i l)
|
||||
(cond
|
||||
[(null? l) (set! ormap-count 'not-there)
|
||||
#f]
|
||||
[else (let ([w (f (car l))])
|
||||
(if w
|
||||
(begin
|
||||
(set! ormap-count (cons i w))
|
||||
w)
|
||||
(helper (1+ i) (cdr l))))]))])
|
||||
(helper 1 list))))
|
||||
|
||||
(define engine
|
||||
(lambda (mesh src-lookup dest-lookup w)
|
||||
(let* ([tmp-triangles (build-triangles w mesh)]
|
||||
[triangles (cons (car tmp-triangles) tmp-triangles)]
|
||||
[1-w (- 1 w)])
|
||||
(lambda (x y)
|
||||
(let* ([bc-tri (ormap (point-in-triangle? (make-posn x y)) triangles)])
|
||||
(if bc-tri
|
||||
(let* ([bc (car bc-tri)]
|
||||
[triangle-triple (cdr bc-tri)]
|
||||
[to-p (find-euclid (triangles-to triangle-triple) bc)]
|
||||
[to-x (posn-x to-p)]
|
||||
[to-y (posn-y to-p)]
|
||||
[from-p (find-euclid (triangles-from triangle-triple) bc)]
|
||||
[from-x (posn-x from-p)]
|
||||
[from-y (posn-y from-p)])
|
||||
(set-car! triangles triangle-triple)
|
||||
(values (+ (* w from-x) (* 1-w to-x))
|
||||
(+ (* w from-y) (* 1-w to-y))
|
||||
(+ (* w (src-lookup from-x from-y))
|
||||
(* 1-w (dest-lookup to-x to-y)))))
|
||||
(values x
|
||||
y
|
||||
(begin '(/ (+ (src-lookup x y) (dest-lookup x y)) 2)
|
||||
1))))))))
|
||||
|
||||
'(define engine engine-simple)
|
||||
|
||||
(define get-points
|
||||
(lambda (node)
|
||||
(let ([value (graph:value node)])
|
||||
(values (car value) (cdr value)))))
|
||||
|
||||
;; this returns either #f or a pair, the triangle and the barycentric
|
||||
;; coordinates of (x,y) with respect to that triangle.
|
||||
(define point-in-triangle?
|
||||
(lambda (posn)
|
||||
(lambda (triangle-triple)
|
||||
(let* ([intermediate-triangle (triangles-intermediate triangle-triple)]
|
||||
[bary (find-barycentric-area intermediate-triangle posn)])
|
||||
(if (and (<= 0 (bary-a bary))
|
||||
(<= 0 (bary-b bary))
|
||||
(<= 0 (bary-c bary)))
|
||||
(cons bary triangle-triple)
|
||||
#f)))))
|
||||
|
||||
;; This maps over a list pairwise, e.g.
|
||||
;; (for-each-pairwise (list 1 2 3) f)
|
||||
;; =
|
||||
;; (begin (f 1 2) (f 2 3) (f 3 1))
|
||||
|
||||
(define for-each-pairwise
|
||||
(lambda (l f)
|
||||
(cond
|
||||
[(<= (length l) 1) (void)]
|
||||
[(= 2 (length l)) (f (first l) (second l))]
|
||||
[else (letrec ([first-ele (car l)]
|
||||
[helper
|
||||
(lambda (l)
|
||||
(cond
|
||||
[(null? (cdr l)) (begin '(f (first l) first-ele)
|
||||
(void))]
|
||||
[else (f (first l) (second l))
|
||||
(helper (cdr l))]))])
|
||||
(helper l))])))
|
||||
|
||||
(define-struct triangles (from intermediate to))
|
||||
|
||||
(define build-triangles
|
||||
(lambda (w mesh)
|
||||
(let* ([triangles null]
|
||||
[1-w (- 1 w)]
|
||||
[combine
|
||||
(lambda (p q)
|
||||
(make-posn (+ (* w (posn-x p)) (* 1-w (posn-x q)))
|
||||
(+ (* w (posn-y p)) (* 1-w (posn-y q)))))])
|
||||
(graph:traverse
|
||||
mesh
|
||||
(lambda (node)
|
||||
(let-values ([(left right) (get-points node)])
|
||||
(let ([children (graph:children node)])
|
||||
(when (= (length children) 3)
|
||||
(let ([one (first children)]
|
||||
[two (second children)]
|
||||
[three (third children)])
|
||||
(let-values ([(left-one right-one) (get-points one)]
|
||||
[(left-two right-two) (get-points two)]
|
||||
[(left-three right-three) (get-points three)])
|
||||
(let* ([int (combine left right)]
|
||||
[int-one (combine left-one right-one)]
|
||||
[int-two (combine left-two right-two)]
|
||||
[int-three (combine left-three right-three)]
|
||||
[left-tri1 (build-tri left left-one left-two)]
|
||||
[int-tri1 (build-tri int int-one int-two)]
|
||||
[right-tri1 (build-tri right right-one right-two)]
|
||||
[left-tri2 (build-tri left left-three left-one)]
|
||||
[int-tri2 (build-tri int int-three int-one)]
|
||||
[right-tri2 (build-tri right right-three right-one)])
|
||||
(set! triangles
|
||||
(list*
|
||||
(make-triangles left-tri1 int-tri1 right-tri1)
|
||||
(make-triangles left-tri2 int-tri2 right-tri2)
|
||||
triangles))))))))))
|
||||
(if (null? triangles)
|
||||
(error 'build-triangles "empty mesh")
|
||||
triangles))))
|
@ -0,0 +1,15 @@
|
||||
(for-each (lambda (x)
|
||||
(printf "loading ~s...~n" x)
|
||||
(flush-output)
|
||||
(load-relative x))
|
||||
'("setup.ss"
|
||||
"debug.ss"
|
||||
"2darray.ss"
|
||||
"coord.ss"
|
||||
"mesh.ss"
|
||||
"utils.ss"
|
||||
"ui.ss"
|
||||
"pager.ss"
|
||||
"engine.ss"
|
||||
"main.ss"))
|
||||
(printf "done loading~n")
|
@ -0,0 +1,76 @@
|
||||
(define main
|
||||
(lambda (mesh src-mem-dc dest-mem-dc src-2dvec dest-2dvec total)
|
||||
(letrec* ([width (max (ivar src-2dvec width) (ivar dest-2dvec width))]
|
||||
[dummy-name-width width]
|
||||
[height (max (ivar src-2dvec height) (ivar dest-2dvec height))]
|
||||
|
||||
[src-lookup (ivar src-2dvec lookup)]
|
||||
[dest-lookup (ivar dest-2dvec lookup)]
|
||||
|
||||
[build-w
|
||||
(lambda (w)
|
||||
(debug-print main "building image percent" w)
|
||||
(let* ([new-point (engine mesh
|
||||
src-lookup
|
||||
dest-lookup
|
||||
w)]
|
||||
[memory-dc (make-object wx:memory-dc%)]
|
||||
[set-pixel (ivar memory-dc set-pixel)]
|
||||
[bitmap (make-object wx:bitmap% width height)]
|
||||
[scale (1- num-colors)])
|
||||
(send memory-dc select-object bitmap)
|
||||
(send memory-dc begin-set-pixel)
|
||||
(let loop ([x width] [y height])
|
||||
(let-values ([(draw-x draw-y color) (new-point x y)])
|
||||
(set-pixel draw-x draw-y
|
||||
(vector-ref colors
|
||||
(floor (* color
|
||||
scale))))
|
||||
(cond
|
||||
[(and (zero? y) (zero? x)) (void)]
|
||||
[(zero? x) (begin (when (= 0 (modulo y 15))
|
||||
(debug-print main 'y y))
|
||||
(loop width (1- y)))]
|
||||
[else (loop (1- x) y)])))
|
||||
(send memory-dc end-set-pixel)
|
||||
memory-dc))]
|
||||
|
||||
[memory-dcs1
|
||||
'(list->vector
|
||||
(reverse
|
||||
(cons dest-mem-dc
|
||||
(let loop ([i 1])
|
||||
(if (= i (- total 1)) (list src-mem-dc)
|
||||
(cons (build-w (/ i (1- total)))
|
||||
(loop (1+ i))))))))]
|
||||
|
||||
[memory-dcs2
|
||||
'(list->vector
|
||||
(let loop ([i total])
|
||||
(if (zero? i)
|
||||
(list (build-w (/ i (1- total))))
|
||||
(cons (build-w (/ i (1- total)))
|
||||
(loop (1- i))))))]
|
||||
|
||||
[sub-pager%
|
||||
(make-class pager%
|
||||
(public
|
||||
[width dummy-name-width]
|
||||
[picture-height height]
|
||||
[memory-dcs
|
||||
(list->vector
|
||||
(reverse
|
||||
(cons dest-mem-dc
|
||||
(let loop ([i 1])
|
||||
(if (= i (- total 1)) (list src-mem-dc)
|
||||
(cons (build-w (/ i (1- total)))
|
||||
(loop (1+ i))))))))])
|
||||
(lambda ()
|
||||
(super-init)))])
|
||||
'(debug-print main memory-dcs)
|
||||
(send src-2dvec set-default 1)
|
||||
(send dest-2dvec set-default 1)
|
||||
(mred:show-busy-cursor
|
||||
(lambda ()
|
||||
(make-object sub-pager%))))))
|
||||
|
@ -0,0 +1,138 @@
|
||||
;; graph:node takes a value to be stored on a node and creates a new node.
|
||||
;; graph:edge takes two edges and joins them
|
||||
;; graph:value takes a node and returns it's value
|
||||
|
||||
(define-values (graph:node
|
||||
graph:edge
|
||||
graph:value
|
||||
graph:children
|
||||
graph:parents
|
||||
graph:connections
|
||||
graph:traverse
|
||||
graph:fprintf
|
||||
graph:read
|
||||
graph:id
|
||||
find-closest)
|
||||
(local
|
||||
[(define counter 0)
|
||||
|
||||
(define-struct node (value children parents visited? id))
|
||||
|
||||
(define graph:id node-id)
|
||||
|
||||
(define graph:node
|
||||
(lambda (value)
|
||||
(make-node value null null #f
|
||||
(begin0 counter
|
||||
(set! counter (add1 counter))))))
|
||||
; from n1 to n2. n1 is n2's parent
|
||||
(define graph:edge
|
||||
(lambda (n1 n2)
|
||||
(set-node-children! n1 (cons n2 (node-children n1)))
|
||||
(set-node-parents! n2 (cons n1 (node-parents n2)))))
|
||||
(define graph:value node-value)
|
||||
(define graph:children node-children)
|
||||
(define graph:parents node-parents)
|
||||
(define graph:connections (lambda (x)
|
||||
(append (graph:parents x)
|
||||
(graph:children x))))
|
||||
(define graph:traverse
|
||||
(lambda (node f)
|
||||
(unless (node? node)
|
||||
(error 'graph:traverse "expected a node, found ~s" node))
|
||||
(letrec ([to-reset null]
|
||||
[helper
|
||||
(lambda (node)
|
||||
(when (not (node-visited? node))
|
||||
(f node)
|
||||
(set! to-reset (cons node to-reset))
|
||||
(set-node-visited?! node #t)
|
||||
(for-each helper (node-children node))))])
|
||||
(helper node)
|
||||
(for-each (lambda (node)
|
||||
(set-node-visited?! node #f))
|
||||
to-reset))))
|
||||
|
||||
(define graph:fprintf
|
||||
(lambda (port node fprintf-node-value)
|
||||
(unless (node? node)
|
||||
(error 'graph:fprintf "expected a node, found ~s" node))
|
||||
(let ([min (node-id node)] [max (node-id node)])
|
||||
(graph:traverse
|
||||
node (lambda (x)
|
||||
(when (< max (node-id x))
|
||||
(set! max (node-id x)))
|
||||
(when (< (node-id x) min)
|
||||
(set! min (node-id x)))))
|
||||
(fprintf port "~s ; min~n~s ; max~n; nodes~n" min max))
|
||||
(graph:traverse
|
||||
node
|
||||
(lambda (node)
|
||||
(fprintf port "~s ~s ~s " (node-id node)
|
||||
(map node-id (node-children node))
|
||||
(map node-id (node-parents node)))
|
||||
(fprintf-node-value port (node-value node))
|
||||
(fprintf port "~n")))
|
||||
(fprintf port "~s~n" 'double-check)
|
||||
(fprintf port "~s~n" (node-id node))))
|
||||
|
||||
(define graph:read
|
||||
(opt-lambda (read-value [port (current-input-port)])
|
||||
(let* ([min (read port)]
|
||||
[max (read port)]
|
||||
[v (tabulate (add1 (- max min)) (lambda (x)
|
||||
(graph:node x)))])
|
||||
(let loop ([i (- max min)])
|
||||
(when (<= 0 i)
|
||||
(let* ([index (- (read port) min)]
|
||||
[node (vector-ref v index)]
|
||||
[chili (lambda (i) (vector-ref v (- i min)))]
|
||||
[children (read port)]
|
||||
[parents (read port)])
|
||||
(set-node-children! node (map chili children))
|
||||
(set-node-parents! node (map chili parents))
|
||||
(set-node-value! node (read-value port))
|
||||
(debug-print graph (+ index min) 'children children
|
||||
'parents parents
|
||||
'node node))
|
||||
(loop (sub1 i))))
|
||||
(when (not (eq? 'double-check (read port)))
|
||||
(error 'graph:read "input corrupted"))
|
||||
(let ([node-count (read port)])
|
||||
(debug-print graph 'important-node node-count
|
||||
'min min
|
||||
(vector-ref v (- node-count min)))
|
||||
(vector-ref v (- node-count min))))))
|
||||
|
||||
(define find-closest
|
||||
(lambda (node x y node-value-get)
|
||||
(let* ([mouse-posn (make-posn x y)]
|
||||
[closest node]
|
||||
[value (graph:value node)]
|
||||
[posn (node-value-get value)]
|
||||
[current-dist-sq (distance-sq mouse-posn posn)])
|
||||
(graph:traverse node
|
||||
(lambda (node)
|
||||
(let* ([value (graph:value node)]
|
||||
[this-posn (node-value-get value)]
|
||||
[this-dist-sq
|
||||
(distance-sq mouse-posn this-posn)])
|
||||
(when (< this-dist-sq current-dist-sq)
|
||||
(set! posn this-posn)
|
||||
(set! current-dist-sq this-dist-sq)
|
||||
(set! closest node)))))
|
||||
closest)))]
|
||||
|
||||
|
||||
|
||||
(values graph:node
|
||||
graph:edge
|
||||
graph:value
|
||||
graph:children
|
||||
graph:parents
|
||||
graph:connections
|
||||
graph:traverse
|
||||
graph:fprintf
|
||||
graph:read
|
||||
graph:id
|
||||
find-closest)))
|
@ -0,0 +1,120 @@
|
||||
(define pager%
|
||||
(make-class ()
|
||||
(public
|
||||
[x-pos 650]
|
||||
[y-pos 60]
|
||||
[width 300]
|
||||
[picture-height 300]
|
||||
[slider-height 50]
|
||||
[button-width 30]
|
||||
[slider-width (- width button-width)]
|
||||
[memory-dcs (vector)]
|
||||
[save-images
|
||||
(lambda (fn)
|
||||
(let loop ([i (1- (vector-length memory-dcs))])
|
||||
(when (<= 0 i)
|
||||
(let* ([this-name (string-append
|
||||
fn (number->string (1+ i)) ".pgm")]
|
||||
[port (open-output-file this-name 'replace)]
|
||||
[memory-dc (vector-ref memory-dcs i)]
|
||||
[get-pixel (ivar memory-dc get-pixel)]
|
||||
[color (make-object wx:colour% "white")]
|
||||
[get-colors (ivar color get)]
|
||||
[bgreen (box 0)]
|
||||
[bred (box 0)]
|
||||
[bblue (box 0)])
|
||||
(debug-print pager% 'writing 'image this-name)
|
||||
(fprintf port
|
||||
"P2~n# Robby's Morpher via MrEd~n~s ~s~n255~n"
|
||||
width picture-height)
|
||||
(let loop ([x 0] [y 0])
|
||||
(if (get-pixel x y color)
|
||||
(get-colors bred bgreen bblue)
|
||||
(set-box! bgreen 255))
|
||||
(fprintf port "~s" (unbox bgreen))
|
||||
(fprintf port (if (= x width) "~n" " "))
|
||||
(cond [(and (= x (1- width)) (= y (1- picture-height))) (void)]
|
||||
[(= x (1- width)) (loop 0 (1+ y))]
|
||||
[else (loop (1+ x) y)]))
|
||||
(debug-print pager% 'wrote this-name)
|
||||
(close-output-port port))
|
||||
(loop (1- i)))))]
|
||||
[frame%
|
||||
(make-class mred:menu-frame%
|
||||
(rename [super-make-menu-bar make-menu-bar])
|
||||
(inherit make-menu show)
|
||||
(public
|
||||
[make-menu-bar
|
||||
(lambda ()
|
||||
(let ([bar (super-make-menu-bar)]
|
||||
[file-menu (make-menu)])
|
||||
(send file-menu append-item "Save"
|
||||
(lambda ()
|
||||
(let ([fn (mred:common-put-file '()
|
||||
"Please Specify a prefix for the images.")])
|
||||
(debug-print pager% 'fn fn)
|
||||
(when fn
|
||||
(debug-print pager% 'fn fn)
|
||||
(save-images fn)))))
|
||||
(send file-menu append-item "Close" (lambda () (show #f)))
|
||||
(send bar append file-menu "File")
|
||||
bar))]))]
|
||||
[frame (make-object frame% '() "Morph")]
|
||||
[panel (ivar frame panel)]
|
||||
[canvas%
|
||||
(make-class mred:canvas%
|
||||
(inherit clear set-background)
|
||||
(public
|
||||
[w-brush (make-object wx:brush% "white" wx:const-solid)]
|
||||
[on-paint
|
||||
(lambda ()
|
||||
'(send dc destroy-clipping-region)
|
||||
'(send dc set-clipping-region 0 0 (1+ width) (1+ picture-height))
|
||||
(set-background w-brush)
|
||||
(clear)
|
||||
(when slider
|
||||
(send dc blit 0 0 width picture-height
|
||||
(vector-ref memory-dcs (send slider get-value))
|
||||
0 0 wx:const-copy)))]))]
|
||||
[canvas (make-object canvas% panel)]
|
||||
[s-panel (make-object mred:horizontal-panel% panel)]
|
||||
[slider
|
||||
(let ([show-arg
|
||||
(lambda (s e)
|
||||
(send canvas on-paint))])
|
||||
(if (> (vector-length memory-dcs) 1)
|
||||
(make-object mred:slider% s-panel show-arg ""
|
||||
0 0 (sub1 (vector-length memory-dcs)) slider-width)
|
||||
#f))]
|
||||
[button-click
|
||||
(lambda args
|
||||
(mred:show-busy-cursor
|
||||
(lambda ()
|
||||
(let ([old-slider-pos (send slider get-value)])
|
||||
(let loop ([img 0])
|
||||
(when (< img (vector-length memory-dcs))
|
||||
(send slider set-value img)
|
||||
(send canvas on-paint)
|
||||
(wx:flush-display)
|
||||
(sleep 0.5)
|
||||
(loop (1+ img))))
|
||||
'(send slider set-value old-slider-pos)
|
||||
(send canvas on-paint)))))]
|
||||
[button
|
||||
(when (> (vector-length memory-dcs) 1)
|
||||
(make-object mred:button% s-panel button-click "Play"))]
|
||||
[dc (send canvas get-dc)]
|
||||
[shutdown (lambda () (send frame show #f))])
|
||||
(lambda ()
|
||||
(send panel stretchable-in-y #f)
|
||||
(let ([w (box 0)]
|
||||
[h (box 0)])
|
||||
(send canvas get-client-size w h)
|
||||
(let ([diff (- (send canvas get-width) (unbox w))])
|
||||
(send canvas user-min-width (+ diff width))
|
||||
(send canvas user-min-height (+ diff picture-height))))
|
||||
(send canvas stretchable-in-x #f)
|
||||
(send canvas stretchable-in-y #f)
|
||||
(send frame show #t)
|
||||
(send canvas on-paint))))
|
||||
|
@ -0,0 +1,46 @@
|
||||
(print-struct #t)
|
||||
(print-graph #t)
|
||||
(define last
|
||||
(lambda (x)
|
||||
(cond
|
||||
[(null? x) (error 'last "empty list")]
|
||||
[(null? (cdr x)) (car x)]
|
||||
[else (last (cdr x))])))
|
||||
|
||||
(define foldl2
|
||||
(lambda (f init l)
|
||||
(letrec ([helper
|
||||
(lambda (l sofar)
|
||||
(cond
|
||||
[(null? l) sofar]
|
||||
[else (helper (cdr l) (f (car l) sofar))]))])
|
||||
(helper l init))))
|
||||
|
||||
(define tabulate
|
||||
(lambda (n f)
|
||||
(letrec ([build (lambda (i)
|
||||
(cond
|
||||
[(= i n) null]
|
||||
[else (cons (f i) (build (1+ i)))]))])
|
||||
(list->vector (build 0)))))
|
||||
|
||||
(define vector-for-each
|
||||
(lambda (f v)
|
||||
(let ([size (vector-length v)])
|
||||
(let loop ([n 0])
|
||||
(when (< n size)
|
||||
(f i (vector-ref v i))
|
||||
(loop))))))
|
||||
|
||||
'(define remove
|
||||
(lambda (list f)
|
||||
(letrec ([helper
|
||||
(lambda (l)
|
||||
(cond [(null? l) null]
|
||||
[(f (car l)) (helper (cdr l))]
|
||||
[else (cons (car l) (helper (cdr l)))]))])
|
||||
(helper list))))
|
||||
|
||||
(define-macro package
|
||||
(lambda (x . args)
|
||||
(car 'package)))
|
@ -0,0 +1,407 @@
|
||||
(define num-colors 200)
|
||||
(define mesh-color (make-object wx:colour% 50 155 50))
|
||||
(define mesh-pen (make-object wx:pen% mesh-color 1 wx:const-solid))
|
||||
|
||||
(define black-pen (make-object wx:pen% "BLACK" 1 wx:const-solid))
|
||||
|
||||
(define colors
|
||||
(tabulate num-colors
|
||||
(lambda (i)
|
||||
(make-object wx:colour%
|
||||
(* 255 (expt (/ i (1- num-colors)) 1/2))
|
||||
(* 255 (/ i (1- num-colors)))
|
||||
(* 255 (expt (/ i (1- num-colors)) 1/2))))))
|
||||
|
||||
(define mesh%
|
||||
(make-class mred:menu-frame%
|
||||
(rename [super-make-menu-bar make-menu-bar]
|
||||
; [super-on-paint on-paint]
|
||||
)
|
||||
(inherit make-menu show panel)
|
||||
(public
|
||||
[mesh #f]
|
||||
|
||||
[filename #f]
|
||||
[margin 10]
|
||||
|
||||
[on-paint
|
||||
(lambda ()
|
||||
(send left-canvas on-paint)
|
||||
(send right-canvas on-paint))]
|
||||
|
||||
[canvas%
|
||||
(make-class mred:canvas%
|
||||
(inherit set-background get-dc clear get-client-size)
|
||||
(rename [super-on-event on-event])
|
||||
(private
|
||||
[w-brush (make-object wx:brush% "white" wx:const-solid)])
|
||||
(public
|
||||
[node-value-get (void)]
|
||||
[node-value-update (void)]
|
||||
[memory-dc (make-object wx:memory-dc%)]
|
||||
[set-memory-dc! (lambda (mdc) (set! memory-dc mdc))]
|
||||
[draw-line (void)]
|
||||
[dc (void)]
|
||||
[on-event
|
||||
(let* ([dragging-node (void)]
|
||||
[connections null]
|
||||
[orig-x (void)]
|
||||
[orig-y (void)]
|
||||
[last-x -1]
|
||||
[last-y -1]
|
||||
[lines (lambda ()
|
||||
(for-each
|
||||
(lambda (x)
|
||||
(let ([p (node-value-get (graph:value x))])
|
||||
(draw-line (posn-x p) (posn-y p)
|
||||
last-x last-y)))
|
||||
connections))])
|
||||
(lambda (event)
|
||||
(cond
|
||||
[(send event dragging?)
|
||||
(let ([x (send event get-x)]
|
||||
[y (send event get-y)])
|
||||
(when (and (not (and (= x last-x)
|
||||
(= x last-y)))
|
||||
'(inside-triangles dragging-node x y))
|
||||
(lines)
|
||||
(set! last-x x)
|
||||
(set! last-y y)
|
||||
(lines)))]
|
||||
[(send event button-down?)
|
||||
(let ([x (send event get-x)]
|
||||
[y (send event get-y)])
|
||||
(send dc set-logical-function wx:const-xor)
|
||||
(when mesh
|
||||
(set! dragging-node (find-closest mesh x y node-value-get))
|
||||
(set! connections (graph:connections dragging-node)))
|
||||
(set! last-x x)
|
||||
(set! last-y y)
|
||||
(set! orig-x x)
|
||||
(set! orig-y y)
|
||||
(lines))]
|
||||
[(send event button-up?)
|
||||
(lines)
|
||||
(send dc set-logical-function wx:const-copy)
|
||||
(unless (void? dragging-node)
|
||||
(node-value-update (graph:value dragging-node)
|
||||
(make-posn last-x last-y)))
|
||||
(let* ([posns (cons (make-posn last-x last-y)
|
||||
(map (lambda (x)
|
||||
(node-value-get (graph:value x)))
|
||||
connections))]
|
||||
[box-width (box 0)]
|
||||
[box-height (box 0)]
|
||||
[min-x orig-x]
|
||||
[min-y orig-y]
|
||||
[max-x orig-x]
|
||||
[max-y orig-y])
|
||||
(for-each (lambda (p)
|
||||
(let ([x (posn-x p)]
|
||||
[y (posn-y p)])
|
||||
(when (< max-x x) (set! max-x x))
|
||||
(when (< max-y y) (set! max-y y))
|
||||
(when (< x min-x) (set! min-x x))
|
||||
(when (< y min-y) (set! min-y y))))
|
||||
posns)
|
||||
'(send dc set-clipping-region min-x min-y
|
||||
(1+ (- max-x min-x))
|
||||
(1+ (- max-y min-y)))
|
||||
(on-paint)
|
||||
(get-client-size box-width box-height)
|
||||
(send dc set-clipping-region
|
||||
0 0 (unbox box-width) (unbox box-height)))
|
||||
(set! dragging-node (void))
|
||||
(set! connections (void))
|
||||
(set! orig-x (void))
|
||||
(set! orig-y (void))
|
||||
(set! last-x (void))
|
||||
(set! last-y (void))]
|
||||
[else (super-on-event event)])))]
|
||||
[on-paint
|
||||
(lambda ()
|
||||
(let* ([get-points
|
||||
(lambda (node)
|
||||
(let* ([value (graph:value node)]
|
||||
[p (node-value-get value)])
|
||||
(values (posn-x p)(posn-y p))))]
|
||||
[traverse
|
||||
(lambda (node)
|
||||
(let-values ([(b-x b-y) (get-points node)])
|
||||
(let* ([children (graph:children node)]
|
||||
[chili
|
||||
(lambda (child)
|
||||
(let-values ([(e-x e-y) (get-points child)])
|
||||
(draw-line b-x b-y e-x e-y)))])
|
||||
(for-each chili children))))]
|
||||
[dc (get-dc)]
|
||||
[by (box 0)]
|
||||
[bx (box 0)])
|
||||
(get-client-size bx by)
|
||||
(set-background w-brush)
|
||||
(clear)
|
||||
(send dc set-pen black-pen)
|
||||
(send dc blit 0 0 (unbox bx) (unbox by)
|
||||
memory-dc 0 0 wx:const-copy)
|
||||
(when mesh
|
||||
(send dc set-pen mesh-pen)
|
||||
'(send dc set-logical-function wx:const-xor)
|
||||
(graph:traverse mesh traverse)
|
||||
'(send dc set-logical-function wx:const-copy))))])
|
||||
(lambda (get update . args)
|
||||
(apply super-init args)
|
||||
(set! dc (get-dc))
|
||||
(set! draw-line (ivar dc draw-line))
|
||||
(set! node-value-get get)
|
||||
(set! node-value-update update)))]
|
||||
|
||||
[left-filename #f]
|
||||
[right-filename #f]
|
||||
[left-2dvec #f]
|
||||
[right-2dvec #f]
|
||||
[left-canvas #f]
|
||||
[right-canvas #f]
|
||||
[default-size 200]
|
||||
|
||||
[canvas-size-diff 0]
|
||||
|
||||
[get-sizes
|
||||
(lambda ()
|
||||
(let* ([left-width (if left-2dvec
|
||||
(ivar left-2dvec width)
|
||||
default-size)]
|
||||
[left-height (if left-2dvec
|
||||
(ivar left-2dvec height)
|
||||
default-size)]
|
||||
[right-width (if right-2dvec
|
||||
(ivar right-2dvec width)
|
||||
default-size)]
|
||||
[right-height (if right-2dvec
|
||||
(ivar right-2dvec height)
|
||||
default-size)])
|
||||
(values left-width left-height right-width right-height)))]
|
||||
[resize-panels
|
||||
(lambda ()
|
||||
(let-values ([(left-width left-height right-width right-height)
|
||||
(get-sizes)])
|
||||
(send left-canvas user-min-width (+ canvas-size-diff left-width))
|
||||
(send left-canvas user-min-height (+ canvas-size-diff left-height))
|
||||
(send right-canvas user-min-width (+ canvas-size-diff right-width))
|
||||
(send right-canvas user-min-height (+ canvas-size-diff right-height))))]
|
||||
[open
|
||||
(lambda (fn)
|
||||
(mred:show-busy-cursor
|
||||
(lambda ()
|
||||
(let* ([port (open-input-file fn)]
|
||||
[local-mesh #f]
|
||||
[read-value
|
||||
(lambda (port)
|
||||
(let ([left (read port)]
|
||||
[right (read port)])
|
||||
(cons (apply make-posn left)
|
||||
(apply make-posn right))))])
|
||||
(set! left-filename (read port))
|
||||
(set! right-filename (read port))
|
||||
(when (read port)
|
||||
(set! local-mesh (graph:read read-value port)))
|
||||
(close-input-port port)
|
||||
(debug-print mesh% 'read 'file)
|
||||
(set! left-2dvec (build-image left-filename))
|
||||
(set! right-2dvec (build-image right-filename))
|
||||
(debug-print mesh% 'built-2dvecs)
|
||||
(send left-canvas set-memory-dc! (build-memory-dc left-2dvec))
|
||||
(send right-canvas set-memory-dc! (build-memory-dc right-2dvec))
|
||||
(debug-print mesh% 'updated 'canvases)
|
||||
(set! mesh local-mesh)
|
||||
(set! filename fn)
|
||||
(resize-panels)
|
||||
(on-paint)))))]
|
||||
[save
|
||||
(lambda ()
|
||||
(if filename
|
||||
(begin
|
||||
(let ([port (open-output-file filename 'replace)]
|
||||
[print-value
|
||||
(lambda (port v)
|
||||
(let ([left (car v)]
|
||||
[right (cdr v)])
|
||||
(fprintf port "~s ~s"
|
||||
(list (posn-x left) (posn-y left))
|
||||
(list (posn-x right) (posn-y right)))))])
|
||||
(fprintf port ";;; data req'd to setup a morph~n~n")
|
||||
(fprintf port "~s ; source filename~n" left-filename)
|
||||
(fprintf port "~s ; destination filename~n" right-filename)
|
||||
(fprintf port "~n;; mesh~n")
|
||||
(if mesh
|
||||
(begin
|
||||
(fprintf port "#t ; mesh is setup~n")
|
||||
(graph:fprintf port mesh print-value))
|
||||
(fprintf port "#f ; mesh is not setup~n"))
|
||||
(close-output-port port)))
|
||||
(save-as)))]
|
||||
[save-as
|
||||
(lambda ()
|
||||
(let ([fn (mred:common-put-file)])
|
||||
(when fn
|
||||
(set! filename fn)
|
||||
(save))))]
|
||||
|
||||
[make-menu-bar
|
||||
(lambda ()
|
||||
(let ([bar (super-make-menu-bar)]
|
||||
[file-menu (make-menu)]
|
||||
[picture-menu (make-menu)]
|
||||
[mesh-menu (make-menu)]
|
||||
[morph-menu (make-menu)])
|
||||
(send file-menu append-item "Open..."
|
||||
(lambda ()
|
||||
(let ([fn (mred:common-get-file)])
|
||||
(when fn (open fn)))))
|
||||
(send file-menu append-item "Save..." save)
|
||||
(send file-menu append-item "Save As..." save-as)
|
||||
(send file-menu append-separator)
|
||||
(send file-menu append-item "Close" (lambda () (show #f)))
|
||||
(send picture-menu append-item "Select Source Image..."
|
||||
(lambda ()
|
||||
(let ([fn (mred:common-get-file
|
||||
'() "Please choose an image.")])
|
||||
(when fn
|
||||
(mred:show-busy-cursor
|
||||
(lambda ()
|
||||
(set! left-filename fn)
|
||||
(time (set! left-2dvec (build-image fn)))
|
||||
(time (send left-canvas set-memory-dc!
|
||||
(build-memory-dc left-2dvec)))
|
||||
(set! mesh #f)
|
||||
(resize-panels)
|
||||
(on-paint)))))))
|
||||
(send picture-menu append-item "Select Destination Image..."
|
||||
(lambda ()
|
||||
(let ([fn (mred:common-get-file
|
||||
'() "Please choose an image.")])
|
||||
(when fn
|
||||
(mred:show-busy-cursor
|
||||
(lambda ()
|
||||
(set! right-filename fn)
|
||||
(set! right-2dvec (build-image fn))
|
||||
(send right-canvas set-memory-dc!
|
||||
(build-memory-dc right-2dvec))
|
||||
(set! mesh #f)
|
||||
(resize-panels)
|
||||
(on-paint)))))))
|
||||
(send picture-menu append-item "Exchange Images"
|
||||
(lambda ()
|
||||
(let ([left-mdc (ivar left-canvas memory-dc)]
|
||||
[right-mdc (ivar right-canvas memory-dc)]
|
||||
[tmp left-2dvec]
|
||||
[exchange
|
||||
(lambda (node)
|
||||
(let* ([value (graph:value node)]
|
||||
[left (car value)])
|
||||
(set-car! value (cdr value))
|
||||
(set-cdr! value left)))])
|
||||
(set! left-2dvec right-2dvec)
|
||||
(set! right-2dvec tmp)
|
||||
(send right-canvas set-memory-dc! left-mdc)
|
||||
(send left-canvas set-memory-dc! right-mdc)
|
||||
(graph:traverse mesh exchange)
|
||||
(resize-panels)
|
||||
(on-paint))))
|
||||
(send mesh-menu append-item "Fresh Mesh..."
|
||||
(lambda ()
|
||||
(fresh-mesh (get-number-from-user
|
||||
"How large should the mesh be?"
|
||||
"Mesh Size" "5"))
|
||||
(on-paint)))
|
||||
(send morph-menu append-item "Morph..."
|
||||
(lambda () (morph (get-number-from-user
|
||||
"How many steps in the morph?"
|
||||
"Morph Size" "3"))))
|
||||
(send bar append file-menu "File")
|
||||
(send bar append picture-menu "Images")
|
||||
(send bar append mesh-menu "Mesh")
|
||||
(send bar append morph-menu "Morph")
|
||||
bar))]
|
||||
[morph
|
||||
(lambda (steps)
|
||||
(if (and left-2dvec right-2dvec mesh)
|
||||
(main mesh (ivar left-canvas memory-dc)
|
||||
(ivar right-canvas memory-dc)
|
||||
left-2dvec right-2dvec steps)
|
||||
(wx:message-box "Please choose images and mesh.")))]
|
||||
[fresh-mesh
|
||||
(lambda (n)
|
||||
(let-values ([(left-width left-height right-width right-height)
|
||||
(get-sizes)])
|
||||
(let* ([nodes
|
||||
(let loop ([row (1- n)] [column (1- n)])
|
||||
(let ([row-percent (/ row (1- n))]
|
||||
[column-percent (/ column (1- n))])
|
||||
(cons
|
||||
(graph:node
|
||||
(cons (make-posn (* left-width row-percent)
|
||||
(* left-height column-percent))
|
||||
(make-posn (* right-width row-percent)
|
||||
(* right-height column-percent))))
|
||||
(cond
|
||||
[(and (= row 0) (= column 0)) null]
|
||||
[(= row 0) (loop (1- n) (1- column))]
|
||||
[else (loop (1- row) column)]))))]
|
||||
[2dvec (make-object 2d-vector% n n 0)]
|
||||
[lookup (ivar 2dvec lookup)]
|
||||
[update (ivar 2dvec update)])
|
||||
(send 2dvec bend (reverse nodes))
|
||||
|
||||
(if (< 2 n)
|
||||
(begin
|
||||
'(graph:edge (lookup 0 (1- n)) (lookup 1 (1- n)))
|
||||
(let loop ([x (- n 2)] [y (- n 2)])
|
||||
(graph:edge (lookup x y) (lookup x (1+ y)))
|
||||
(graph:edge (lookup x y) (lookup (1+ x) y))
|
||||
(graph:edge (lookup x y) (lookup (1+ x) (1+ y)))
|
||||
(cond [(and (= x 0) (= y 0)) (void)]
|
||||
[(= x 0) (loop (- n 2) (1- y))]
|
||||
[else (loop (1- x) y)]))
|
||||
(let loop ([i (- n 2)])
|
||||
(when (<= 0 i)
|
||||
(graph:edge (lookup (1- n) i) (lookup (1- n) (1+ i)))
|
||||
(graph:edge (lookup i (1- n)) (lookup (1+ i) (1- n)))
|
||||
(loop (1- i)))))
|
||||
(begin
|
||||
(graph:edge (lookup 0 0) (lookup 0 1))
|
||||
(graph:edge (lookup 0 0) (lookup 1 0))
|
||||
(graph:edge (lookup 0 0) (lookup 1 1))
|
||||
(graph:edge (lookup 1 0) (lookup 1 1))
|
||||
(graph:edge (lookup 0 1) (lookup 1 1))))
|
||||
|
||||
(set! mesh (lookup 0 0)))))])
|
||||
|
||||
(lambda ()
|
||||
(super-init '() "Mesh Construction")
|
||||
(send panel stretchable-in-x #f)
|
||||
(send panel stretchable-in-y #f)
|
||||
(let ([p (make-object mred:horizontal-panel% panel)]
|
||||
[init
|
||||
(lambda (c)
|
||||
(send c user-min-height default-size)
|
||||
(send c user-min-width default-size)
|
||||
(send c stretchable-in-x #f)
|
||||
(send c stretchable-in-y #f))])
|
||||
(send p stretchable-in-x #f)
|
||||
(send p stretchable-in-y #f)
|
||||
(set! left-canvas (make-object canvas% car set-car! p))
|
||||
(init left-canvas)
|
||||
(set! right-canvas (make-object canvas% cdr set-cdr! p))
|
||||
(init right-canvas))
|
||||
(let ([w (box 0)]
|
||||
[h (box 0)])
|
||||
(send right-canvas get-client-size w h)
|
||||
(set! canvas-size-diff (- (send right-canvas get-width) (unbox w))))
|
||||
(show #t))))
|
||||
|
||||
(define mesh
|
||||
(begin (when (defined? 'mesh)
|
||||
(send mesh show #f))
|
||||
(make-object mesh%)))
|
||||
'(send mesh open "/home/robby/class/graphics/lab5/test/rd.morph")
|
||||
'(send mesh morph 3)
|
@ -0,0 +1,114 @@
|
||||
(define build-pgm-image
|
||||
(lambda (filename)
|
||||
(let* ([comment #\#]
|
||||
[coords
|
||||
(call-with-input-file
|
||||
filename
|
||||
(lambda (p)
|
||||
(let ([tmp null])
|
||||
(let loop ([line (read-line p)])
|
||||
(unless (eof-object? line)
|
||||
(unless (char=? comment (string-ref line 0))
|
||||
(let ([sp (open-input-string line)])
|
||||
(let loop ([object (read sp)])
|
||||
(unless (eof-object? object)
|
||||
(set! tmp (cons object tmp))
|
||||
(loop (read sp))))))
|
||||
(loop (read-line p))))
|
||||
(reverse tmp))))])
|
||||
(when (< (length coords) 4)
|
||||
(error 'build-image "found less than four numbers in file: ~s"
|
||||
filename))
|
||||
(let* ([tag (first coords)]
|
||||
[width (second coords)]
|
||||
[height (third coords)]
|
||||
[top-value (exact->inexact (fourth coords))]
|
||||
[data (list-tail coords 4)]
|
||||
[2dvec (make-object 2d-vector% width height top-value)]
|
||||
[normalized-data
|
||||
(map (lambda (x) (/ x top-value))
|
||||
data)])
|
||||
(when (not (= (* width height) (length data)))
|
||||
(error 'build-image
|
||||
"data sizes incorrect in file ~s, found ~s expected ~s"
|
||||
filename (length data) (* width height)))
|
||||
(send 2dvec bend normalized-data)
|
||||
2dvec))))
|
||||
|
||||
(define build-image
|
||||
(lambda (filename)
|
||||
(let ([error
|
||||
(lambda ()
|
||||
(error 'build-image "The file \"~a\" could not be loaded."
|
||||
filename)
|
||||
#f)])
|
||||
(if (regexp-match "\\.gif" filename)
|
||||
(let ([b (make-object wx:bitmap% filename wx:const-bitmap-type-gif)])
|
||||
(if (send b ok?)
|
||||
(let ([m (make-object wx:memory-dc%)])
|
||||
(send m select-object b)
|
||||
(if (send m ok?)
|
||||
(let* ([w (send b get-width)]
|
||||
[h (send b get-height)]
|
||||
[2dvec (make-object 2d-vector% w h 255)]
|
||||
[update (ivar 2dvec update)]
|
||||
[c (make-object wx:colour%)]
|
||||
[r (ivar c red)]
|
||||
[g (ivar c green)]
|
||||
[b (ivar c blue)])
|
||||
(let iloop ([i (sub1 w)])
|
||||
(let jloop ([j (sub1 h)])
|
||||
(send m get-pixel i j c)
|
||||
(let ([r (exact->inexact (r))]
|
||||
[g (exact->inexact (g))]
|
||||
[b (exact->inexact (b))])
|
||||
(update i j (/ (sqrt (/ (+ (* r r) (* g g) (* b b)) 3)) 255)))
|
||||
(unless (zero? j)
|
||||
(jloop (sub1 j))))
|
||||
(unless (zero? i)
|
||||
(iloop (sub1 i))))
|
||||
2dvec)
|
||||
(error)))
|
||||
(error)))
|
||||
(build-pgm-image filename)))))
|
||||
|
||||
(define build-memory-dc
|
||||
(lambda (2dvec)
|
||||
(let* ([memory-dc (make-object wx:memory-dc%)]
|
||||
[set-pixel (ivar memory-dc set-pixel)]
|
||||
[lookup (ivar 2dvec lookup)]
|
||||
[width (ivar 2dvec width)]
|
||||
[height (ivar 2dvec height)]
|
||||
[bitmap (make-object wx:bitmap% width height)]
|
||||
[scale (1- num-colors)])
|
||||
(send memory-dc select-object bitmap)
|
||||
(send memory-dc begin-set-pixel)
|
||||
(let loop ([x (1- width)] [y (1- height)])
|
||||
(let* ([l (lookup x y)])
|
||||
(set-pixel x y (vector-ref colors (floor (* scale l)))))
|
||||
(cond
|
||||
[(and (zero? y) (zero? x)) (void)]
|
||||
[(zero? x) (loop (1- width) (1- y))]
|
||||
[else (loop (1- x) y)]))
|
||||
(send memory-dc end-set-pixel)
|
||||
memory-dc)))
|
||||
|
||||
(define get-number-from-user
|
||||
(lambda (message title default)
|
||||
(let* ([input (wx:get-text-from-user message title default)]
|
||||
[read-in
|
||||
(read-string
|
||||
input
|
||||
(lambda (debug string . rest)
|
||||
(wx:message-box
|
||||
(string-append
|
||||
string
|
||||
(apply
|
||||
string-append
|
||||
(map expr->string rest))))
|
||||
(apply reg-error debug string rest)))])
|
||||
(if (and (number? read-in)
|
||||
(positive? read-in)
|
||||
(integer? read-in))
|
||||
read-in
|
||||
(wx:message-box "Expected a positive integer")))))
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,163 @@
|
||||
|
||||
(define lookup-number
|
||||
(let ([phonebook '(("Mr. Bumpy" "555-BUMP" "555-SNOT")
|
||||
("Squishington" "555-SQSH" "555-BOWL")
|
||||
("Miss Molly" "555-MOLL" "555-COMF"))])
|
||||
(lambda (name home?)
|
||||
(sleep 2) ; artificial database delay
|
||||
(let loop ([pb phonebook])
|
||||
(cond
|
||||
[(null? pb) #f]
|
||||
[(regexp-match name (caar pb))
|
||||
((if home? cadar caddar) pb)]
|
||||
[else (loop (cdr pb))])))))
|
||||
|
||||
(define a-frame
|
||||
(make-object mred:frame%
|
||||
null ; No parent frame
|
||||
"Phone Book")) ; The frame's title
|
||||
|
||||
(define a-panel
|
||||
(make-object mred:vertical-panel%
|
||||
a-frame)) ; Panel is in a-frame
|
||||
|
||||
(define h-panel
|
||||
(make-object mred:horizontal-panel%
|
||||
a-panel)) ; Panel is in a-frame
|
||||
|
||||
(define name-text
|
||||
(make-object mred:text%
|
||||
h-panel
|
||||
(lambda (self event) (refresh-number-info))
|
||||
"Name" ; label
|
||||
"")) ; initial value
|
||||
(define quit-button
|
||||
(make-object mred:button%
|
||||
h-panel
|
||||
(lambda (self event)
|
||||
(send a-frame show #f))
|
||||
"Quit")) ; Button label
|
||||
|
||||
(define number-selector
|
||||
(make-object mred:radio-box%
|
||||
a-panel
|
||||
(lambda (self event) (refresh-number-info))
|
||||
"" ; No label
|
||||
-1 -1 -1 -1 ; Default position and size
|
||||
(list "Home Number" "Office Number")))
|
||||
|
||||
(define number-text
|
||||
(make-object mred:text%
|
||||
a-panel
|
||||
(lambda (self event) #f) ; No event-handling
|
||||
"Number"
|
||||
"(Unknown)"))
|
||||
(send number-text set-editable #f)
|
||||
|
||||
;; First revision: unthreaded
|
||||
|
||||
(define refresh-number-info
|
||||
(lambda ()
|
||||
(let* ([name (send name-text get-value)]
|
||||
[home? (zero? (send number-selector get-selection))]
|
||||
[number (lookup-number name home?)]
|
||||
[number-string (if number
|
||||
number
|
||||
"(Unknown)")])
|
||||
(send number-text set-value number-string))))
|
||||
|
||||
;; Second revision: threaded
|
||||
|
||||
(define refresh-number-info
|
||||
(let ([adj-cancel-sema (make-semaphore 1)]
|
||||
[previous-cancel (box #f)])
|
||||
(lambda ()
|
||||
(let ([this-cancel (box #f)])
|
||||
(semaphore-wait adj-cancel-sema)
|
||||
(set-box! previous-cancel #t)
|
||||
(set! previous-cancel this-cancel)
|
||||
(semaphore-post adj-cancel-sema)
|
||||
(thread
|
||||
(lambda ()
|
||||
(send number-text set-value "(Searching...)")
|
||||
(let* ([name (send name-text get-value)]
|
||||
[home? (zero? (send number-selector get-selection))]
|
||||
[number (lookup-number name home?)] ; May take a while...
|
||||
[number-string (if number
|
||||
number
|
||||
"(Unknown)")])
|
||||
(semaphore-wait adj-cancel-sema)
|
||||
(unless (unbox this-cancel)
|
||||
(send number-text set-value number-string))
|
||||
(semaphore-post adj-cancel-sema))))))))
|
||||
|
||||
;; Make a class:
|
||||
|
||||
(define pb-session%
|
||||
(class null ()
|
||||
(public
|
||||
[refresh-number-info
|
||||
(let ([adj-cancel-sema (make-semaphore 1)]
|
||||
[previous-cancel (box #f)])
|
||||
(lambda ()
|
||||
(let ([this-cancel (box #f)])
|
||||
(semaphore-wait adj-cancel-sema)
|
||||
(set-box! previous-cancel #t)
|
||||
(set! previous-cancel this-cancel)
|
||||
(semaphore-post adj-cancel-sema)
|
||||
(thread
|
||||
(lambda ()
|
||||
(send number-text set-value "(Searching...)")
|
||||
(let* ([name (send name-text get-value)]
|
||||
[home? (zero? (send number-selector get-selection))]
|
||||
[number (lookup-number name home?)] ; May take a while...
|
||||
[number-string (if number
|
||||
number
|
||||
"(Unknown)")])
|
||||
(semaphore-wait adj-cancel-sema)
|
||||
(unless (unbox this-cancel)
|
||||
(send number-text set-value number-string))
|
||||
(semaphore-post adj-cancel-sema)))))))])
|
||||
(public
|
||||
(a-frame (make-object mred:frame% null "Phonebook"))
|
||||
(a-panel (make-object mred:vertical-panel% a-frame)))
|
||||
(private
|
||||
(h-panel (make-object mred:horizontal-panel% a-panel))
|
||||
(name-text (make-object mred:text% h-panel
|
||||
(lambda (self event) (refresh-number-info))
|
||||
"Name" ""))
|
||||
(quit-button (make-object mred:button% h-panel
|
||||
(lambda (self event) (send a-frame show #f))
|
||||
"Quit"))
|
||||
(number-selector (make-object mred:radio-box% a-panel
|
||||
(lambda (self event) (refresh-number-info))
|
||||
"" -1 -1 -1 -1 (list "Home Number" "Office Number")))
|
||||
(number-text (make-object mred:text% a-panel
|
||||
(lambda (self event) #f)
|
||||
"Number" "(Unknown)")))
|
||||
(sequence
|
||||
(send a-frame show #t)
|
||||
(send number-text set-editable #f))))
|
||||
|
||||
|
||||
|
||||
(define pb-counted-session%
|
||||
(class pb-session% ()
|
||||
(inherit a-frame a-panel) ; We need to access the panel object...
|
||||
(rename [basic-refresh-number-info refresh-number-info]) ; and old refresh
|
||||
(private [search-counter 0]) ; Counter value
|
||||
(public
|
||||
[refresh-number-info ; Increment the counter and call old refresh
|
||||
(lambda ()
|
||||
(set! search-counter (add1 search-counter))
|
||||
(send counter-text set-value (number->string search-counter))
|
||||
(basic-refresh-number-info))])
|
||||
(sequence
|
||||
(super-init)) ; Do base class initialization
|
||||
(private
|
||||
(counter-text (make-object mred:text% a-panel
|
||||
(lambda (self event) #f)
|
||||
"Number of Searches Started"
|
||||
"0")))
|
||||
(sequence
|
||||
(send counter-text set-editable #f))))
|
@ -0,0 +1 @@
|
||||
(require-library "sig.ss" "system")
|
Binary file not shown.
@ -0,0 +1,377 @@
|
||||
;; Toy proof checkers implemented with MrEd and units
|
||||
;; Kathi Fisler
|
||||
;; September 3, 1996
|
||||
|
||||
;; This code demonstrates the combined use of MrEd and units to
|
||||
;; implement a collection of simple proof checkers.
|
||||
|
||||
;; Proof Checker Architecture:
|
||||
;;
|
||||
;; A proof checker consists of two main components: a list of
|
||||
;; operations supported by the checker and the interface through which
|
||||
;; the user invokes the checker. Each of these components is
|
||||
;; implemented as a unit in the code below.
|
||||
;;
|
||||
;; The "operations" unit, (signature prover-core^) provides a list
|
||||
;; containing the names of the operations, a list containing the
|
||||
;; operations corresponding to the names, and a default operation.
|
||||
;;
|
||||
;; The "interface" unit (signature interface^) is a compound unit with
|
||||
;; subunits corresponding to the various pieces of the interface.
|
||||
;; Subunits exist for how the user inputs data to the checker, how the
|
||||
;; checker displays results to the user, how the user selects from
|
||||
;; among the possible operations, how the user instructs the checker
|
||||
;; to check the current data against the selected operation, and how
|
||||
;; the user exits the checker. The interface unit combines these
|
||||
;; subunits into a main interface and provides a function
|
||||
;; (create-interface) that can be invoked to create a checker with the
|
||||
;; specified interface components and the specified operations from
|
||||
;; the operations unit.
|
||||
|
||||
;; The Collection of Checkers
|
||||
;;
|
||||
;; Each of the implemented checkers contains three objects into which
|
||||
;; the user can enter data and one object through which the checker
|
||||
;; displays results. Two operations units are provided:
|
||||
;; proof-core-calculator@ and proof-core-tester@. The former computes
|
||||
;; simple arithmetic functions over the three inputs and the latter
|
||||
;; tests boolean-valued relationships between the three inputs. The
|
||||
;; checker displays the values returned by either type of operation.
|
||||
;;
|
||||
;; Two types of interfaces are possible: one in which the operations
|
||||
;; are selected through radio boxes and the other in which the
|
||||
;; operations are selected through menu options.
|
||||
;;
|
||||
;; Three checkers are defined explicitly at the end of the code:
|
||||
;; make-calculator/radio, make-checker/radio, and make-checker/menu,
|
||||
;; each taking the appropriate combination of the described interface
|
||||
;; and operations units.
|
||||
|
||||
;;;;; The Implementation ;;;;;
|
||||
|
||||
(require-library "trigger.ss")
|
||||
|
||||
;;;;; Signature Definitions ;;;;;
|
||||
|
||||
(define-signature prover-core^
|
||||
(proof-rule-names proof-rule-checkers default-rule-checker))
|
||||
|
||||
(define-signature num-entry-interface^
|
||||
(create-num-entry-interface get-numbers))
|
||||
|
||||
(define-signature result-display-interface^
|
||||
(create-result-display-interface show-result))
|
||||
|
||||
(define-signature rule-select-interface^
|
||||
(create-rule-select-interface
|
||||
current-proof-rule set-current-proof-rule))
|
||||
|
||||
(define-signature compute-interface^
|
||||
(create-compute-interface))
|
||||
|
||||
(define-signature quit-interface^
|
||||
(create-quit-interface))
|
||||
|
||||
(define-signature main-interface^
|
||||
(create-interface quit-prover))
|
||||
|
||||
(define-signature interface^
|
||||
((open main-interface^)))
|
||||
|
||||
;;;;; Compound Unit Definitions ;;;;;
|
||||
|
||||
(define interface@
|
||||
(lambda (numentry resdisplay ruleselect compute quit main)
|
||||
(compound-unit/sig
|
||||
(import (MRED : mred^) (CORE : prover-core^))
|
||||
(link
|
||||
(NUMENTRY : num-entry-interface^ (numentry MRED))
|
||||
(RESDISPLAY : result-display-interface^ (resdisplay MRED))
|
||||
(RULESELECT : rule-select-interface^ (ruleselect CORE MRED))
|
||||
(COMPUTE : compute-interface^ (compute RESDISPLAY RULESELECT
|
||||
NUMENTRY MRED))
|
||||
(QUIT : quit-interface^ (quit MAIN MRED))
|
||||
(MAIN : main-interface^ (main NUMENTRY RESDISPLAY
|
||||
RULESELECT COMPUTE QUIT MRED))
|
||||
)
|
||||
(export (open MAIN)))))
|
||||
|
||||
(define prover@
|
||||
(lambda (core interface)
|
||||
(compound-unit/sig
|
||||
(import (MRED : mred^))
|
||||
(link
|
||||
(CORE : prover-core^ (core))
|
||||
(INTERFACE : interface^ (interface MRED CORE)))
|
||||
(export (open INTERFACE)))))
|
||||
|
||||
;;;;; Primitive Unit Definitions ;;;;;
|
||||
|
||||
;;;;;;;; Interface Units ;;;;;;;;
|
||||
|
||||
(define main-interface-no-menus@
|
||||
(unit/sig main-interface^
|
||||
(import num-entry-interface^ result-display-interface^
|
||||
rule-select-interface^ compute-interface^
|
||||
quit-interface^ (mred : mred^))
|
||||
(define outer-frame
|
||||
(make-object mred:frame% `() "Toy Prover"))
|
||||
(define v-panel
|
||||
(make-object mred:vertical-panel% outer-frame))
|
||||
(define upper-hpanel
|
||||
(make-object mred:horizontal-panel% v-panel))
|
||||
(define lower-hpanel
|
||||
(make-object mred:horizontal-panel% v-panel))
|
||||
(define create-interface
|
||||
(lambda ()
|
||||
(create-num-entry-interface upper-hpanel)
|
||||
(create-result-display-interface lower-hpanel)
|
||||
(create-compute-interface upper-hpanel)
|
||||
(create-quit-interface upper-hpanel outer-frame)
|
||||
(create-rule-select-interface lower-hpanel)
|
||||
(send outer-frame show #t)))
|
||||
(define quit-prover
|
||||
(lambda ()
|
||||
(send outer-frame show #f)))
|
||||
))
|
||||
|
||||
(define main-interface-menus@
|
||||
(unit/sig main-interface^
|
||||
(import num-entry-interface^ result-display-interface^
|
||||
rule-select-interface^ compute-interface^
|
||||
quit-interface^ (mred : mred^))
|
||||
(define myframe%
|
||||
(class mred:standard-menus-frame% args
|
||||
(rename [super-make-menu-bar make-menu-bar])
|
||||
(public
|
||||
[make-menu-bar
|
||||
(lambda ()
|
||||
(let ([mb (super-make-menu-bar)])
|
||||
(create-rule-select-interface mb)
|
||||
mb))]
|
||||
[panel% mred:vertical-panel%]
|
||||
)
|
||||
(sequence (apply super-init args))))
|
||||
(define outer-frame
|
||||
(make-object myframe% null "Toy Prover"))
|
||||
(define v-panel (ivar outer-frame panel))
|
||||
(define upper-hpanel
|
||||
(make-object mred:horizontal-panel% v-panel))
|
||||
(define lower-hpanel
|
||||
(make-object mred:horizontal-panel% v-panel))
|
||||
(define create-interface
|
||||
(lambda ()
|
||||
(create-num-entry-interface upper-hpanel)
|
||||
(create-result-display-interface lower-hpanel)
|
||||
(create-compute-interface upper-hpanel)
|
||||
(create-quit-interface upper-hpanel outer-frame)
|
||||
(send outer-frame show #t)))
|
||||
(define quit-prover
|
||||
(lambda ()
|
||||
(send outer-frame show #f)))
|
||||
))
|
||||
|
||||
(define num-entry-interface-3text@
|
||||
(unit/sig num-entry-interface^
|
||||
(import (mred : mred^))
|
||||
|
||||
(define num1 (void))
|
||||
(define num2 (void))
|
||||
(define num3 (void))
|
||||
|
||||
(define create-num-entry-interface
|
||||
(lambda (panel)
|
||||
(set! num1
|
||||
(make-object mred:text% panel (lambda (self event) #f)
|
||||
"" ""))
|
||||
(set! num2
|
||||
(make-object mred:text% panel (lambda (self event) #f)
|
||||
"" ""))
|
||||
(set! num3
|
||||
(make-object mred:text% panel (lambda (self event) #f)
|
||||
"" ""))))
|
||||
|
||||
(define get-numbers
|
||||
(lambda ()
|
||||
(map string->number
|
||||
(list (send num1 get-value)
|
||||
(send num2 get-value)
|
||||
(send num3 get-value)))))
|
||||
))
|
||||
|
||||
(define result-display-interface-text@
|
||||
(unit/sig result-display-interface^
|
||||
(import (mred : mred^))
|
||||
|
||||
(define resdisplay (void))
|
||||
|
||||
(define create-result-display-interface
|
||||
(lambda (panel)
|
||||
(set! resdisplay
|
||||
(make-object mred:text% panel (lambda (self event) #f) "Result"))
|
||||
))
|
||||
|
||||
(define show-result
|
||||
(lambda (res)
|
||||
(send resdisplay set-value
|
||||
(cond ((string? res) res)
|
||||
((number? res) (number->string res))
|
||||
((boolean? res) (if res "True" "False"))
|
||||
(error "Argument of Unknown Type")))))
|
||||
))
|
||||
|
||||
(define rule-select-interface-radio@
|
||||
(unit/sig rule-select-interface^
|
||||
(import prover-core^ (mred : mred^))
|
||||
|
||||
(define current-proof-rule default-rule-checker)
|
||||
|
||||
(define set-current-proof-rule
|
||||
(lambda (rule)
|
||||
(set! current-proof-rule rule)))
|
||||
|
||||
(define create-rule-select-interface
|
||||
(lambda (panel)
|
||||
(make-object mred:radio-box%
|
||||
panel
|
||||
(lambda (self event)
|
||||
(set-current-proof-rule
|
||||
(list-ref proof-rule-checkers
|
||||
(send self get-selection))))
|
||||
"" -1 -1 -1 -1
|
||||
proof-rule-names)))
|
||||
))
|
||||
|
||||
(define rule-select-interface-menus@
|
||||
(unit/sig rule-select-interface^
|
||||
(import prover-core^ (mred : mred^))
|
||||
(define current-proof-rule default-rule-checker)
|
||||
|
||||
(define set-current-proof-rule
|
||||
(lambda (rule)
|
||||
(set! current-proof-rule rule)))
|
||||
|
||||
(define create-rule-select-interface
|
||||
(lambda (mb)
|
||||
(let ([rules-menu (make-object mred:menu%)])
|
||||
(map
|
||||
(lambda (name checker)
|
||||
(send rules-menu append-item name
|
||||
(lambda ()
|
||||
(set-current-proof-rule checker))))
|
||||
proof-rule-names
|
||||
proof-rule-checkers)
|
||||
(send mb append rules-menu "Rules"))))
|
||||
))
|
||||
|
||||
(define compute-interface-button@
|
||||
(unit/sig compute-interface^
|
||||
(import result-display-interface^ rule-select-interface^
|
||||
num-entry-interface^ (mred : mred^))
|
||||
(define create-compute-interface
|
||||
(lambda (panel)
|
||||
(make-object mred:button%
|
||||
panel
|
||||
(lambda (self event)
|
||||
(show-result
|
||||
(apply current-proof-rule (get-numbers))))
|
||||
"Apply Rule")))))
|
||||
|
||||
(define quit-interface-button@
|
||||
(unit/sig quit-interface^
|
||||
(import main-interface^ (mred : mred^))
|
||||
(define create-quit-interface
|
||||
(lambda (panel outer-frame)
|
||||
(make-object mred:button%
|
||||
panel
|
||||
(lambda (self event) (quit-prover))
|
||||
"Quit")))))
|
||||
|
||||
;;;;;;;; Prover Core Units ;;;;;;;;
|
||||
|
||||
(define proof-core-calculator@
|
||||
(unit/sig prover-core^
|
||||
(import)
|
||||
(define-struct proof-rule (name checker))
|
||||
|
||||
(define proof-rules
|
||||
(list
|
||||
(make-proof-rule "Add" +)
|
||||
(make-proof-rule "Mult" *)
|
||||
(make-proof-rule "Max" max)))
|
||||
|
||||
(define proof-rule-names (map proof-rule-name proof-rules))
|
||||
(define proof-rule-checkers (map proof-rule-checker proof-rules))
|
||||
(define default-rule-checker (car proof-rule-checkers))))
|
||||
|
||||
(define proof-core-tester@
|
||||
(unit/sig prover-core^
|
||||
(import)
|
||||
(define-struct proof-rule (name checker))
|
||||
|
||||
(define square
|
||||
(lambda (num)
|
||||
(* num num)))
|
||||
|
||||
(define proof-rules
|
||||
(list
|
||||
(make-proof-rule "Test Add"
|
||||
(lambda (num-1 num-2 num-3)
|
||||
(= num-3 (+ num-1 num-2))))
|
||||
(make-proof-rule "Test Mult"
|
||||
(lambda (num-1 num-2 num-3)
|
||||
(= num-3 (* num-1 num-2))))
|
||||
(make-proof-rule "Test Increasing"
|
||||
(lambda (num-1 num-2 num-3)
|
||||
(and (< num-1 num-2)
|
||||
(< num-2 num-3))))
|
||||
(make-proof-rule "Test Triangle"
|
||||
(lambda (num-1 num-2 num-3)
|
||||
(= (square num-3)
|
||||
(+ (square num-1) (square num-2)))))
|
||||
))
|
||||
|
||||
(define proof-rule-names (map proof-rule-name proof-rules))
|
||||
(define proof-rule-checkers (map proof-rule-checker proof-rules))
|
||||
(define default-rule-checker (car proof-rule-checkers))))
|
||||
|
||||
;;;;; Creating Provers ;;;;;
|
||||
|
||||
(define make-calculator/radio
|
||||
(lambda ()
|
||||
(invoke-open-unit/sig
|
||||
(prover@ proof-core-calculator@
|
||||
(interface@ num-entry-interface-3text@
|
||||
result-display-interface-text@
|
||||
rule-select-interface-radio@
|
||||
compute-interface-button@
|
||||
quit-interface-button@
|
||||
main-interface-no-menus@))
|
||||
#f (mred : mred^))
|
||||
(create-interface)))
|
||||
|
||||
(define make-checker/radio
|
||||
(lambda ()
|
||||
(invoke-open-unit/sig
|
||||
(prover@ proof-core-tester@
|
||||
(interface@ num-entry-interface-3text@
|
||||
result-display-interface-text@
|
||||
rule-select-interface-radio@
|
||||
compute-interface-button@
|
||||
quit-interface-button@
|
||||
main-interface-no-menus@))
|
||||
#f (mred : mred^))
|
||||
(create-interface)))
|
||||
|
||||
(define make-checker/menu
|
||||
(lambda ()
|
||||
(invoke-open-unit/sig
|
||||
(prover@ proof-core-tester@
|
||||
(interface@ num-entry-interface-3text@
|
||||
result-display-interface-text@
|
||||
rule-select-interface-menus@
|
||||
compute-interface-button@
|
||||
quit-interface-button@
|
||||
main-interface-menus@))
|
||||
#f (mred : mred^))
|
||||
(create-interface)))
|
Binary file not shown.
@ -0,0 +1,5 @@
|
||||
|
||||
(require-library "turtle.ss" "graphics")
|
||||
(require-library "turex.ss" "graphics")
|
||||
|
||||
(turtles)
|
@ -0,0 +1,343 @@
|
||||
;; Tframe.ss - creates MrSpidey frames
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
; Global variable to record the most-recently created frame
|
||||
(define tf (void))
|
||||
|
||||
(define shake-it-repetitions 25)
|
||||
|
||||
(define spidey:frame%
|
||||
(class
|
||||
(mred:make-searchable-frame% mred:simple-menu-frame%)
|
||||
(arg-main arg-filename summary-edit . init-locs)
|
||||
|
||||
(inherit show get-canvas ;; get-canvas%
|
||||
make-menu create-status-line set-status-text
|
||||
get-position get-size set-icon panel
|
||||
set-title file-menu set-title-prefix
|
||||
set-size)
|
||||
|
||||
;; ----------
|
||||
|
||||
(rename
|
||||
[super-on-close on-close]
|
||||
[super-make-menu-bar make-menu-bar])
|
||||
|
||||
;; ----------
|
||||
|
||||
(public
|
||||
|
||||
[get-edit (lambda () program-edit)]
|
||||
[auto-set-wrap #f]
|
||||
[edit% flow-arrow:media-edit%]
|
||||
[get-canvas% (lambda () mred:wrapping-canvas%)]
|
||||
[on-close
|
||||
(lambda ignored
|
||||
(send main on-frame-close filename)
|
||||
(send this show #f)
|
||||
(remq-callback-sdl-alg-changed! flush-type-cache)
|
||||
(super-on-close))]
|
||||
|
||||
[set-show-mode
|
||||
(lambda (which)
|
||||
(pretty-debug-gui `(set-show-mode ,which))
|
||||
(unless (eq? which canvas-show-mode)
|
||||
(set! canvas-show-mode which)
|
||||
(send summary-canvas stretchable-in-y (eq? which 'summary))
|
||||
(send panel change-children
|
||||
(lambda (ignore)
|
||||
(filter
|
||||
(lambda (x) x)
|
||||
(list
|
||||
(and (or (eq? which 'program) (eq? which 'both))
|
||||
program-canvas)
|
||||
(and (or (eq? which 'summary) (eq? which 'both))
|
||||
summary-canvas)))))))]
|
||||
|
||||
;; ---------- Set up the menus
|
||||
[file-menu:new #f]
|
||||
[file-menu:open #f]
|
||||
[file-menu:revert #f]
|
||||
[file-menu:save #f]
|
||||
[file-menu:save-as #f]
|
||||
;;[file-menu:print #f]
|
||||
;;[file-menu:between-print-and-close (lambda args (void))]
|
||||
[file-menu:between-save-and-print (lambda args (void))]
|
||||
|
||||
[edit-menu:undo #f]
|
||||
[edit-menu:redo #f]
|
||||
[edit-menu:cut #f]
|
||||
[edit-menu:paste #f]
|
||||
[edit-menu:delete #f]
|
||||
;;[edit-menu:find #f]
|
||||
[edit-menu:replace #f]
|
||||
[edit-menu:between-replace-and-preferences (lambda args (void))]
|
||||
|
||||
[file-menu:close on-close]
|
||||
[file-menu:between-open-and-save
|
||||
(lambda (file-menu)
|
||||
(send file-menu
|
||||
append-item
|
||||
"Open ..."
|
||||
(lambda () (send main open-analyzed-file-choice)))
|
||||
(send file-menu
|
||||
append-item
|
||||
"Open All"
|
||||
(lambda () (wrap-busy-cursor (lambda () (send main open-all #t)))))
|
||||
(send file-menu
|
||||
append-item
|
||||
"Load All"
|
||||
(lambda () (wrap-busy-cursor (lambda () (send main open-all #f)))))
|
||||
(send file-menu
|
||||
append-item
|
||||
"Reanalyze"
|
||||
(lambda () (wrap-busy-cursor (lambda () (send main reanalyze)))))
|
||||
(send file-menu append-separator))]
|
||||
[file-menu:between-close-and-quit
|
||||
(lambda (file-menu)
|
||||
(send file-menu
|
||||
append-item
|
||||
"Close All"
|
||||
;;(format "Close ~a" st:name)
|
||||
(lambda ()
|
||||
(wrap-busy-cursor
|
||||
(lambda ()
|
||||
(send main close-all-frames))))))]
|
||||
|
||||
[flush-type-cache (lambda () (void))]
|
||||
|
||||
[calc-show
|
||||
(lambda ()
|
||||
(set-show-mode 'program)
|
||||
(when (and
|
||||
summary-canvas
|
||||
;; Show summary only if some real content
|
||||
(> (send summary-edit last-line) 3))
|
||||
;;(printf "Summary-edit size ~s~n" (send summary-edit last-line))
|
||||
(set-show-mode 'both)))]
|
||||
|
||||
[make-menu-bar
|
||||
(lambda ()
|
||||
(let ([menu-bar (super-make-menu-bar)])
|
||||
(let ([show-menu (make-menu)])
|
||||
(send menu-bar append show-menu "Show")
|
||||
(set! init-show-menu
|
||||
(lambda ()
|
||||
(send show-menu
|
||||
append-check-set
|
||||
(list
|
||||
(cons "Program Only" 'program)
|
||||
(cons "Summary Only" 'summary)
|
||||
(cons "Both" 'both))
|
||||
set-show-mode
|
||||
(case canvas-show-mode
|
||||
[(program) 0]
|
||||
[(summary) 1]
|
||||
[(both) 2]
|
||||
[else 0]))))
|
||||
|
||||
'(send show-menu append-separator)
|
||||
'(send show-menu
|
||||
append-check-set
|
||||
(map (lambda (mode) (cons (mode-name mode) mode))
|
||||
modes)
|
||||
set-display-mode))
|
||||
|
||||
(let ([clear-menu (make-menu)])
|
||||
(send menu-bar append clear-menu "Clear")
|
||||
(send* clear-menu
|
||||
(append-item
|
||||
"Arrows+Types"
|
||||
(lambda ()
|
||||
(wrap-busy-cursor
|
||||
(lambda ()
|
||||
(send* program-edit
|
||||
(delete-arrows)
|
||||
(delete-types))))
|
||||
"Removes both types and arrows from the window"))
|
||||
(append-item
|
||||
"Arrows"
|
||||
(lambda ()
|
||||
(wrap-busy-cursor
|
||||
(lambda ()
|
||||
(send program-edit delete-arrows))))
|
||||
"Removes all arrows from the window")
|
||||
(append-item
|
||||
"Types"
|
||||
(lambda ()
|
||||
(wrap-busy-cursor
|
||||
(lambda ()
|
||||
(send program-edit delete-types))))
|
||||
"Removes all types from the window"))
|
||||
(unless st:restricted
|
||||
(send clear-menu append-item
|
||||
"Shake Buffer"
|
||||
(lambda () (for i 0 shake-it-repetitions (shake-it)))
|
||||
"Sends random inputs to buffer")
|
||||
(send clear-menu append-item
|
||||
"Rewrite Buffer"
|
||||
(lambda ()
|
||||
(wrap-busy-cursor
|
||||
(lambda ()
|
||||
(set-display-mode display-mode))))
|
||||
"Removes all types and arrows from the window")))
|
||||
|
||||
(let ([filter-menu (make-menu)])
|
||||
(send menu-bar append filter-menu "Filter")
|
||||
(send filter-menu
|
||||
append-check-set
|
||||
(analysis-get-filters)
|
||||
analysis-set-arrow-filter!)
|
||||
(analysis-set-arrow-filter! #f))
|
||||
|
||||
|
||||
|
||||
menu-bar))]
|
||||
|
||||
[init-show-menu #f]
|
||||
)
|
||||
|
||||
;; ----------
|
||||
|
||||
(public
|
||||
[main arg-main] ; parent containing the global state
|
||||
program-canvas
|
||||
program-edit
|
||||
summary-canvas ; or #f if no summary
|
||||
[filename arg-filename]
|
||||
|
||||
[canvas-show-mode 'none] ; 'program, 'summary, or 'both
|
||||
[display-mode (car modes)] ; which display mode
|
||||
|
||||
[set-display-mode
|
||||
(lambda (which)
|
||||
(set! display-mode which)
|
||||
(pretty-debug-gui `(set-display-mode ,display-mode ,filename))
|
||||
;; Call main to create a new edit buffer,
|
||||
;; and to load and annotate file
|
||||
(set! program-edit
|
||||
(send main annotated-edit display-mode filename program-canvas))
|
||||
(send program-canvas set-media program-edit))]
|
||||
|
||||
[focus-def
|
||||
(lambda (pos)
|
||||
(unless (memq display-mode '(program both))
|
||||
(set-show-mode 'both))
|
||||
(let* ( [real-pos (send program-edit real-start-position pos)]
|
||||
[end (mred:scheme-forward-match
|
||||
program-edit real-pos
|
||||
(send program-edit last-position))])
|
||||
(thread
|
||||
(lambda ()
|
||||
(sleep)
|
||||
(send program-canvas set-focus)
|
||||
(send program-edit
|
||||
set-position-bias-scroll -1 real-pos end)))))]
|
||||
|
||||
[shake-it
|
||||
(lambda ()
|
||||
(send program-edit shake-it))]
|
||||
|
||||
;; ----------
|
||||
|
||||
)
|
||||
|
||||
(sequence
|
||||
(pretty-debug-gui
|
||||
`(Tframe ,arg-main ,arg-filename ,summary-edit ,@init-locs))
|
||||
(match init-locs
|
||||
[(w h x y)
|
||||
(pretty-debug-gui `(send this set-size ,(+ x 15) ,(+ y 15) ,w ,h))
|
||||
(set-size x y w h)]
|
||||
[() (void)])
|
||||
(pretty-debug-gui `(Tframe super-init))
|
||||
(let ([t (format "~a: ~a"
|
||||
st:name (file-name-from-path arg-filename))])
|
||||
(super-init t)
|
||||
(pretty-debug-gui `(Tframe super-init done))
|
||||
(set-title-prefix t)))
|
||||
|
||||
|
||||
;; ---------------------------------------------------------
|
||||
|
||||
(sequence
|
||||
(set! flush-type-cache
|
||||
(lambda ()
|
||||
(pretty-debug-gui '(Tframe flush-type-cache))
|
||||
(unless (void? program-edit)
|
||||
(send program-edit flush-type-cache))))
|
||||
|
||||
(add-callback-sdl-alg-changed! flush-type-cache)
|
||||
|
||||
(pretty-debug-gui
|
||||
`(Tframe ,arg-main ,arg-filename ,summary-edit ,@init-locs))
|
||||
(set! tf this)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; build the canvases
|
||||
|
||||
(pretty-debug-gui '(setting summary-canvas))
|
||||
(set! summary-canvas
|
||||
(and summary-edit
|
||||
(let ([c
|
||||
;(make-object (get-canvas%) panel)
|
||||
(make-object (class-asi mred:one-line-canvas%
|
||||
(public
|
||||
[lines 5]
|
||||
[style-flags 0]))
|
||||
panel)
|
||||
])
|
||||
;;(send c set-lines 2)
|
||||
(send c set-media summary-edit)
|
||||
c)))
|
||||
(assert (is-a? summary-canvas mred:connections-media-canvas%))
|
||||
(pretty-debug-gui '(setting program-canvas))
|
||||
(set! program-canvas (get-canvas))
|
||||
(set-display-mode (car modes))
|
||||
(pretty-debug-gui '(done setting canvases))
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; install the icon
|
||||
|
||||
'(let ([icon (make-object wx:icon%
|
||||
(build-absolute-path
|
||||
(collection-path "mrspidey") ; MATTHEW: got rid of plt-home
|
||||
"icon.gif")
|
||||
wx:const-bitmap-type-gif
|
||||
)])
|
||||
(when (send icon ok?) (set-icon icon)))
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; status help line
|
||||
|
||||
;;(unless (eq? mred:platform 'macintosh)
|
||||
;; (create-status-line))
|
||||
|
||||
;;(set-status-text
|
||||
;; "Mouse: Left-type/parents Midde-Ancestors Right-Close")
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
|
||||
;;(set-display-mode display-mode)
|
||||
(calc-show)
|
||||
(init-show-menu)
|
||||
(show #t)
|
||||
|
||||
)))
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,137 @@
|
||||
; arrow.ss
|
||||
; defines arrow:media-edit%, an extention of graphics:media-edit% with arrows
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define arrow:media-edit%
|
||||
(let* ([pi (* 2 (asin 1))]
|
||||
[arrow-head-angle (/ pi 8)]
|
||||
[cos-angle (cos arrow-head-angle)]
|
||||
[sin-angle (sin arrow-head-angle)]
|
||||
[arrow-head-size 10]
|
||||
[arrow-root-radius 3.5]
|
||||
[cursor-arrow (make-object wx:cursor% wx:const-cursor-arrow)])
|
||||
|
||||
(class-asi graphics:media-edit%
|
||||
(inherit delete-graphic draw-graphics add-graphic set-cursor)
|
||||
(public
|
||||
[delete-arrow (lambda (arrow) (delete-graphic arrow))]
|
||||
[draw-arrows (lambda () (draw-graphics))]
|
||||
[add-arrow
|
||||
(lambda (start-pos start-dx start-dy
|
||||
end-pos end-dx end-dy
|
||||
delta brush pen
|
||||
clickback-head clickback-root)
|
||||
(pretty-debug-gui (list 'add-arrow
|
||||
start-pos start-dx start-dy
|
||||
end-pos end-dx end-dy
|
||||
delta clickback-head clickback-root))
|
||||
(add-graphic
|
||||
(list start-pos end-pos)
|
||||
(match-lambda
|
||||
[((start-x . start-y) (end-x . end-y))
|
||||
(pretty-debug-gui
|
||||
`(locs ,start-x ,start-y ,end-x ,end-y
|
||||
,start-dx ,start-dy ,end-dx ,end-dy))
|
||||
(let*
|
||||
([start-x (+ start-x start-dx)]
|
||||
[start-y (+ start-y start-dy)]
|
||||
[end-x (+ end-x end-dx)]
|
||||
[end-y (+ end-y end-dy)]
|
||||
[ofs-x (- start-x end-x)]
|
||||
[ofs-y (- start-y end-y)]
|
||||
[len (sqrt (+ (* ofs-x ofs-x) (* ofs-y ofs-y)))]
|
||||
[ofs-x (/ ofs-x len)]
|
||||
[ofs-y (/ ofs-y len)]
|
||||
[head-x (* ofs-x arrow-head-size)]
|
||||
[head-y (* ofs-y arrow-head-size)]
|
||||
[end-x (+ end-x (* ofs-x delta))]
|
||||
[end-y (+ end-y (* ofs-y delta))]
|
||||
[pt1 (make-object wx:point% end-x end-y)]
|
||||
[pt2 (make-object
|
||||
wx:point%
|
||||
(+ end-x (* cos-angle head-x)
|
||||
(* sin-angle head-y))
|
||||
(+ end-y (- (* sin-angle head-x))
|
||||
(* cos-angle head-y)))]
|
||||
[pt3 (make-object
|
||||
wx:point%
|
||||
(+ end-x (* cos-angle head-x)
|
||||
(- (* sin-angle head-y)))
|
||||
(+ end-y (* sin-angle head-x)
|
||||
(* cos-angle head-y)))]
|
||||
[pts (list pt1 pt2 pt3)]
|
||||
[draw-fn
|
||||
(lambda (dc dx dy)
|
||||
'(pretty-debug-gui
|
||||
(list 'draw-line (+ start-x dx) (+ start-y dy)
|
||||
(+ end-x dx) (+ end-y dy)))
|
||||
(let ([old-brush (send dc get-brush)]
|
||||
[old-pen (send dc get-pen)]
|
||||
[old-logfn (send dc get-logical-function)])
|
||||
(send dc set-brush brush)
|
||||
(send dc set-pen pen)
|
||||
;; (send dc set-logical-function wx:const-or)
|
||||
(send dc draw-line
|
||||
(+ start-x dx) (+ start-y dy)
|
||||
(+ end-x dx) (+ end-y dy))
|
||||
(send dc draw-polygon pts dx dy)
|
||||
(send dc draw-ellipse
|
||||
(- (+ start-x dx) arrow-root-radius)
|
||||
(- (+ start-y dy) arrow-root-radius)
|
||||
(* 2 arrow-root-radius)
|
||||
(* 2 arrow-root-radius))
|
||||
(send dc set-brush old-brush)
|
||||
(send dc set-pen old-pen)
|
||||
(send dc set-logical-function old-logfn)))]
|
||||
[on-head?
|
||||
(lambda (x y)
|
||||
(let*
|
||||
([xs (map (lambda (pt) (send pt get-x)) pts)]
|
||||
[ys (map (lambda (pt) (send pt get-y)) pts)]
|
||||
[min-x (apply min xs)]
|
||||
[min-y (apply min ys)]
|
||||
[max-x (apply max xs)]
|
||||
[max-y (apply max ys)])
|
||||
(and (>= x min-x)
|
||||
(<= x max-x)
|
||||
(>= y min-y)
|
||||
(<= y max-y))))]
|
||||
[on-root?
|
||||
(lambda (x y)
|
||||
(and (>= x (- start-x arrow-root-radius))
|
||||
(<= x (+ start-x arrow-root-radius))
|
||||
(>= y (- start-y arrow-root-radius))
|
||||
(<= y (+ start-y arrow-root-radius))))]
|
||||
[event-fn
|
||||
(lambda (event x y)
|
||||
(cond
|
||||
[(on-head? x y)
|
||||
(set-cursor cursor-arrow)
|
||||
(clickback-head event)]
|
||||
[(on-root? x y)
|
||||
(set-cursor cursor-arrow)
|
||||
(clickback-root event)]
|
||||
[else
|
||||
;; Back to default cursor
|
||||
;; (set-cursor '())
|
||||
#f]))])
|
||||
|
||||
;; Return draw-thunk and event function
|
||||
(cons draw-fn event-fn))])))]))))
|
||||
|
||||
;; ----------------------------------------
|
@ -0,0 +1,108 @@
|
||||
; deltas.ss
|
||||
; Loads configuration from .Xresources
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;; Given a resource name, this returns a style delta corresponding to the
|
||||
;; attributes of the file or the default if there are none.
|
||||
|
||||
(define (get-resource-maybe s2 default)
|
||||
(let ([val-box (box default)])
|
||||
(wx:get-resource
|
||||
(if (wx:colour-display?) "mrspidey" "mrspidey-bw")
|
||||
s2
|
||||
val-box)
|
||||
(unbox val-box)))
|
||||
|
||||
(define delta-eval-namespace (make-namespace))
|
||||
(parameterize ([current-namespace delta-eval-namespace])
|
||||
(invoke-open-unit/sig wx@ wx))
|
||||
|
||||
(define delta-add-string!
|
||||
(lambda (delta string)
|
||||
(let ([p (open-input-string string)])
|
||||
(recur loop ()
|
||||
(let ([e (read p)])
|
||||
(unless (eof-object? e)
|
||||
(apply (uq-ivar delta (car e)) (eval `(list ,@(cdr e)) delta-eval-namespace))
|
||||
(loop)))))))
|
||||
|
||||
(define set-resource-delta
|
||||
(lambda (name default-string default-string-bw delta)
|
||||
(delta-add-string! delta
|
||||
(if (wx:colour-display?)
|
||||
default-string
|
||||
default-string-bw))
|
||||
(delta-add-string! delta (get-resource-maybe name ""))))
|
||||
|
||||
(define make-resource-delta
|
||||
(lambda (name default-string default-string-bw)
|
||||
(let ([delta (make-object wx:style-delta%
|
||||
wx:const-change-alignment wx:const-align-top)])
|
||||
'(set-resource-delta "base-delta"
|
||||
"(set-delta wx:const-change-normal) \
|
||||
(set-delta wx:const-change-family wx:const-modern) \
|
||||
(set-alignment-on wx:const-align-top) "
|
||||
"(set-delta wx:const-change-normal) \
|
||||
(set-delta wx:const-change-family wx:const-modern) \
|
||||
(set-alignment-on wx:const-align-top)"
|
||||
delta)
|
||||
(set-resource-delta name default-string default-string-bw delta)
|
||||
delta)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; These deltas are defined when the application starts, either from defaults
|
||||
;; or from resources, their names and their strings agree.
|
||||
|
||||
(define base-delta
|
||||
(make-resource-delta "base-delta"
|
||||
"(set-delta wx:const-change-normal) \
|
||||
(set-delta wx:const-change-family wx:const-modern) \
|
||||
(set-alignment-on wx:const-align-top) "
|
||||
"(set-delta wx:const-change-normal) \
|
||||
(set-delta wx:const-change-family wx:const-modern) \
|
||||
(set-alignment-on wx:const-align-top)"))
|
||||
|
||||
(define normal-delta
|
||||
(make-resource-delta "normal-delta"
|
||||
"" ""))
|
||||
|
||||
(define type-link-delta
|
||||
(make-resource-delta "type-link-delta"
|
||||
"(set-delta wx:const-change-bold)"
|
||||
"(set-delta wx:const-change-bold)"))
|
||||
(define type-delta
|
||||
(make-resource-delta "type-link-delta"
|
||||
""
|
||||
""))
|
||||
|
||||
(define check-delta
|
||||
(make-resource-delta "check-delta"
|
||||
"(set-delta-foreground \"RED\")"
|
||||
"(set-delta wx:const-change-underline 1)"))
|
||||
(define uncheck-delta
|
||||
(make-resource-delta "uncheck-delta"
|
||||
"(set-delta-foreground \"FORESTGREEN\")"
|
||||
""))
|
||||
|
||||
(define check-link-delta
|
||||
(make-resource-delta "check-link-delta"
|
||||
"(set-delta-foreground \"BLUE\") \
|
||||
(set-delta wx:const-change-underline 1)"
|
||||
"(set-delta wx:const-change-underline 1)"))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
@ -0,0 +1,193 @@
|
||||
; dyn-edit
|
||||
;
|
||||
; Defines spidey:dynamic+margin-edit%, a subclass of spidey:static-edit%
|
||||
; with an insert-line method that also inserts a margin
|
||||
; and it handles adding and deleting snips
|
||||
; while still allowing static positions in the buffer
|
||||
;
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define spidey:dynamic+margin-edit%
|
||||
(class spidey:static-edit% (arg-margin . init-args)
|
||||
(inherit
|
||||
set-auto-set-wrap
|
||||
load-file last-position position-line
|
||||
lock get-style-list
|
||||
begin-edit-sequence end-edit-sequence edit-sequence
|
||||
|
||||
change-style
|
||||
set-clickback
|
||||
flash-on
|
||||
set-position
|
||||
scroll-to-position
|
||||
get-text
|
||||
insert
|
||||
delete
|
||||
set-tabs
|
||||
)
|
||||
|
||||
(public
|
||||
;; ----------
|
||||
margin
|
||||
margin-length
|
||||
;[margin " "]
|
||||
;[margin-length 2]
|
||||
|
||||
;; keeps a list of all the snips in their source-locations
|
||||
[sniplist ()]
|
||||
|
||||
[insert-line
|
||||
(lambda (s)
|
||||
(insert margin)
|
||||
(insert s)
|
||||
(insert (string #\newline)))]
|
||||
|
||||
;; ----------
|
||||
|
||||
[account-for-margin
|
||||
(lambda (pos)
|
||||
(recur loop ([try pos])
|
||||
;;(pretty-debug-gui `(accout-for-margin ,pos ,try))
|
||||
(let ([better
|
||||
(+ pos
|
||||
(* margin-length (add1 (position-line (+ try 0)))))])
|
||||
(if (= better try)
|
||||
try
|
||||
(loop better)))))]
|
||||
[real-start-position
|
||||
(lambda (pos)
|
||||
(account-for-margin
|
||||
(let loop ([l sniplist])
|
||||
(cond
|
||||
[(null? l) pos]
|
||||
[(> pos (car l)) (add1 (loop (cdr l)))]
|
||||
[else (loop (cdr l))]))))]
|
||||
[real-end-position
|
||||
(lambda (pos)
|
||||
(account-for-margin
|
||||
(let loop ([l sniplist])
|
||||
(cond
|
||||
[(null? l) pos]
|
||||
[(>= pos (car l)) (add1 (loop (cdr l)))]
|
||||
[else (loop (cdr l))]))))]
|
||||
[old-real-end-position
|
||||
(lambda (pos)
|
||||
(let ([pos pos])
|
||||
(let loop ([l sniplist][pos pos])
|
||||
(cond
|
||||
[(null? l) (account-for-margin pos)]
|
||||
[(>= pos (car l))
|
||||
(loop (cdr l) (add1 pos))]
|
||||
[else (loop (cdr l) pos)]))))]
|
||||
[frame-pos->source-pos
|
||||
(lambda (pos)
|
||||
(assert (number? pos) 'frame-pos->source-pos)
|
||||
(let ([pos (- pos (* margin-length (add1 (position-line pos))))])
|
||||
(let loop ([l sniplist])
|
||||
(cond
|
||||
[(null? l) pos]
|
||||
[(> pos (car l))
|
||||
(sub1 (loop (cdr l)))]
|
||||
[else (loop (cdr l))]))))]
|
||||
|
||||
;; ----------
|
||||
|
||||
[relocate-change-style
|
||||
(lambda (delta src-start src-end)
|
||||
(let ([s (real-start-position src-start)]
|
||||
[e (real-end-position src-end)])
|
||||
(pretty-debug-gui `(change-style ,src-start ,src-end ,s ,e))
|
||||
(change-style delta s e)))]
|
||||
|
||||
[relocate-set-clickback
|
||||
(lambda (src-start src-end . args)
|
||||
(apply set-clickback
|
||||
(real-start-position src-start)
|
||||
(real-end-position src-end)
|
||||
args))]
|
||||
[relocate-flash-on
|
||||
(lambda (src-start src-end a b c)
|
||||
(flash-on (real-start-position src-start)
|
||||
(real-end-position src-end) a b c))]
|
||||
[relocate-scroll-to-position
|
||||
(lambda (pos)
|
||||
(let ([real-pos (real-start-position pos)])
|
||||
'(pretty-print `(scroll-to-position ,pos ,real-pos))
|
||||
(set-position real-pos)
|
||||
(scroll-to-position real-pos)))]
|
||||
;;
|
||||
;; watch this function......
|
||||
[relocate-set-position
|
||||
(opt-lambda
|
||||
(pos [end -1][eol #f][scroll #t])
|
||||
(let ([end (if (= end -1) -1 (real-end-position end))])
|
||||
(set-position (real-start-position pos) end
|
||||
eol scroll)))]
|
||||
[match-paren-forward
|
||||
(lambda (source-start)
|
||||
(frame-pos->source-pos (mred:scheme-forward-match
|
||||
this (real-start-position source-start)
|
||||
(last-position))))]
|
||||
|
||||
[relocate-get-text
|
||||
(opt-lambda ([start -1][end -1][flat #f])
|
||||
(get-text (real-start-position start)
|
||||
(real-end-position end) flat))]
|
||||
[select-snip
|
||||
(lambda (pos snip)
|
||||
(edit-sequence
|
||||
(lambda ()
|
||||
(send (send snip get-this-media) own-caret #f)
|
||||
(set-position
|
||||
(real-end-position pos) (real-start-position pos)))))]
|
||||
[relocate-insert-snip
|
||||
(lambda (snip pos)
|
||||
;;(lock #f)
|
||||
(when (member pos sniplist)
|
||||
(error "Cannot put two snips in the same position~n"))
|
||||
(let ([real-pos (real-start-position pos)])
|
||||
(set! sniplist (cons pos sniplist))
|
||||
(insert snip real-pos))
|
||||
;;(lock #t)
|
||||
)]
|
||||
[relocate-delete-snip
|
||||
(lambda (pos)
|
||||
(unless (member pos sniplist)
|
||||
(error "Cannot remove snip from ~s" pos))
|
||||
(set! sniplist (remv pos sniplist))
|
||||
(let ([pos (real-start-position pos)])
|
||||
(delete pos (add1 pos))))]
|
||||
)
|
||||
|
||||
(sequence
|
||||
(apply super-init init-args)
|
||||
(set! margin arg-margin)
|
||||
(set! margin-length (string-length margin))
|
||||
|
||||
(set-auto-set-wrap #f)
|
||||
;; set-tabs doesn't work right past list of specified tabs
|
||||
;; so specify all tabs to column 200
|
||||
(set-tabs
|
||||
(recur loop ([p margin-length])
|
||||
(if (< p 200)
|
||||
(cons p (loop (+ p 8)))
|
||||
'()))
|
||||
8
|
||||
#f)
|
||||
)))
|
||||
|
@ -0,0 +1,147 @@
|
||||
; graphics.ss
|
||||
; Defines graphics:media-edit%, a subclass of spidey:dynamic+margin-edit%
|
||||
; with facilities for graphics on top of text
|
||||
;
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-structure (graphic pos* locs->thunks draw-fn click-fn))
|
||||
|
||||
(define graphics:media-edit%
|
||||
(class spidey:dynamic+margin-edit% args
|
||||
(inherit set-cursor)
|
||||
(rename
|
||||
[super-after-insert after-insert]
|
||||
[super-after-delete after-delete]
|
||||
[super-on-paint on-paint]
|
||||
[super-on-event on-event]
|
||||
[super-resized resized]
|
||||
[super-size-cache-invalid size-cache-invalid])
|
||||
|
||||
(public
|
||||
[graphics-list ()]
|
||||
[pos->locs
|
||||
(lambda (pos)
|
||||
(let* ([xb (box 0)]
|
||||
[yb (box 0)]
|
||||
[real-pos (send this real-start-position pos)] )
|
||||
(send this position-location real-pos xb yb #t)
|
||||
(pretty-debug-gui
|
||||
`(pos->locs ,pos ,real-pos ,(unbox xb) ,(unbox yb)))
|
||||
(cons (unbox xb) (unbox yb))))]
|
||||
[calc-graphic-thunks!
|
||||
(lambda (graphic)
|
||||
(match-let*
|
||||
([locs (map pos->locs (graphic-pos* graphic))]
|
||||
[locs->thunks (graphic-locs->thunks graphic)]
|
||||
[(draw-fn . click-fn) (locs->thunks locs)])
|
||||
(set-graphic-draw-fn! graphic draw-fn)
|
||||
(set-graphic-click-fn! graphic click-fn)))]
|
||||
[recalc-graphics
|
||||
(lambda ()
|
||||
'(pretty-debug-gui `(recalc-graphics ,@graphics-list))
|
||||
(for-each calc-graphic-thunks! graphics-list))]
|
||||
[add-graphic
|
||||
(lambda (pos* locs->thunks)
|
||||
(pretty-debug-gui (list 'add-graphic pos* locs->thunks))
|
||||
(let ([graphic (make-graphic pos* locs->thunks 0 0)])
|
||||
(calc-graphic-thunks! graphic)
|
||||
(set! graphics-list (cons graphic graphics-list))
|
||||
graphic))]
|
||||
[delete-graphic
|
||||
(lambda (graphic)
|
||||
'(pretty-debug-gui `(delete-graphic ,graphic))
|
||||
(set! graphics-list (remv graphic graphics-list)))]
|
||||
[draw-graphics
|
||||
(lambda ()
|
||||
(let ([admin (send this get-admin)])
|
||||
(pretty-debug-gui `(draw-graphics))
|
||||
(send this invalidate-bitmap-cache)
|
||||
|
||||
;; Kludge to get redrawing right
|
||||
;;(send super before-insert 0 1)
|
||||
;;(send super after-insert 0 1)
|
||||
|
||||
'(unless (null? admin)
|
||||
(send admin needs-update 0 0 100000 100000))
|
||||
'(pretty-debug-gui `(draw-graphics-done))))]
|
||||
|
||||
;; overwritten methods
|
||||
[resized
|
||||
(lambda (snip redraw-now)
|
||||
'(pretty-debug-gui `(resized ,snip ,redraw-now))
|
||||
(super-resized snip redraw-now)
|
||||
(recalc-graphics)
|
||||
(when redraw-now (draw-graphics)))]
|
||||
|
||||
[after-delete
|
||||
(lambda (start len)
|
||||
'(pretty-debug-gui `(after-delete ,start ,len))
|
||||
(super-after-delete start len)
|
||||
(recalc-graphics)
|
||||
(draw-graphics))]
|
||||
|
||||
[after-insert
|
||||
(lambda (start len)
|
||||
'(pretty-debug-gui `(after-insert ,start ,len))
|
||||
(super-after-insert start len)
|
||||
(recalc-graphics)
|
||||
(draw-graphics))]
|
||||
[size-cache-invalid
|
||||
(lambda ()
|
||||
(super-size-cache-invalid)
|
||||
(recalc-graphics))]
|
||||
|
||||
[on-paint
|
||||
(lambda (before dc left top right bottom dx dy draw-caret)
|
||||
(super-on-paint
|
||||
before dc left top right bottom
|
||||
dx dy draw-caret)
|
||||
(unless before
|
||||
'(pretty-debug-gui `(on-paint))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ graphic pos* locs->thunks draw-fn click-fn)
|
||||
'(pretty-debug-gui (list 'on-paint-graphic pos*))
|
||||
(draw-fn dc dx dy)])
|
||||
graphics-list)))]
|
||||
|
||||
[on-event
|
||||
(lambda (event)
|
||||
(set-cursor '())
|
||||
(let* ([admin (send this get-admin)]
|
||||
[root-x (box 0)]
|
||||
[root-y (box 0)])
|
||||
(send admin get-dc root-x root-y)
|
||||
(let ([actual-x (+ (send event get-x) (unbox root-x))]
|
||||
[actual-y (+ (send event get-y) (unbox root-y))])
|
||||
|
||||
;; Now try to find a clickback to handle it
|
||||
(let loop ([graphics graphics-list])
|
||||
(match graphics
|
||||
[() (super-on-event event)]
|
||||
[(($ graphic _ _ _ click-fn) . rest-graphics)
|
||||
(or (click-fn event actual-x actual-y)
|
||||
;; Otherwise try next graphic
|
||||
(loop rest-graphics))])))))]
|
||||
)
|
||||
(sequence
|
||||
;;(pretty-debug-gui `(init graphic:media-edit% ,@init))
|
||||
(apply super-init args)
|
||||
)))
|
||||
|
||||
;; ----------------------------------------
|
@ -0,0 +1,29 @@
|
||||
;; load.ss - loads gui files
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(load-relative "deltas.ss")
|
||||
(load-relative "statedit.ss")
|
||||
(load-relative "dyn-edit.ss")
|
||||
(load-relative "graphics.ss")
|
||||
(load-relative "arrow.ss")
|
||||
(load-relative "annotat.ss")
|
||||
;(load-relative "paramenu.ss")
|
||||
;(load-relative "option.ss")
|
||||
(load-relative "prefs.ss")
|
||||
(load-relative "Tframe.ss")
|
||||
(load-relative "main.ss")
|
@ -0,0 +1,42 @@
|
||||
;; loadu.ss - loads graphic files into a unit
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey-gui^ (spidey))
|
||||
|
||||
(define mrspidey-gui@
|
||||
(unit/sig mrspidey-gui^
|
||||
(import
|
||||
[wx : wx^]
|
||||
[mred : mred^]
|
||||
mzlib:unprefixed-core^
|
||||
mrspidey:sba^
|
||||
mrspidey:interaction^)
|
||||
|
||||
(include "deltas.ss")
|
||||
(include "statedit.ss")
|
||||
(include "dyn-edit.ss")
|
||||
(include "graphics.ss")
|
||||
(include "arrow.ss")
|
||||
(include "annotat.ss")
|
||||
;(include "paramenu.ss")
|
||||
;(include "option.ss")
|
||||
(include "prefs.ss")
|
||||
(include "Tframe.ss")
|
||||
(include "main.ss")
|
||||
|
||||
))
|
@ -0,0 +1,553 @@
|
||||
; main.ss
|
||||
; Defines main MrSpidey class
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-structure (fileinfo filename frame thunk-port annotations))
|
||||
;; annotations may also be (-> zodiac:parsed)
|
||||
|
||||
(define NUM-EXTRA-LINES 20)
|
||||
|
||||
(define-struct exn:flow-arrow-exists ())
|
||||
|
||||
(define (wrap-busy-cursor thunk)
|
||||
(dynamic-wind
|
||||
(lambda () (wx:begin-busy-cursor))
|
||||
thunk
|
||||
(lambda () (wx:end-busy-cursor))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
(define tm (void))
|
||||
|
||||
(define MrSpidey%
|
||||
(class null ()
|
||||
|
||||
(public
|
||||
|
||||
[fileinfo* '()]
|
||||
[multiple-files
|
||||
(lambda ()
|
||||
(not (= (length fileinfo*) 1)))]
|
||||
;; ------------------------------
|
||||
;; Progress frame
|
||||
|
||||
[progress-frame 'progress-frame]
|
||||
[progress-canvas 'progress-canvas]
|
||||
[progress-edit 'progress-edit]
|
||||
|
||||
[init-progress-frame!
|
||||
(lambda ()
|
||||
(pretty-debug-gui `(init-progress-frame))
|
||||
(let* ( [f (parameterize
|
||||
([wx:current-eventspace (wx:make-eventspace)])
|
||||
(make-object mred:frame% '()
|
||||
(format "~a Progress" st:name)))]
|
||||
[p (make-object mred:vertical-panel% f)]
|
||||
[c (make-object mred:wrapping-canvas% p)]
|
||||
[ph (make-object mred:horizontal-panel% p)]
|
||||
[_ (send ph stretchable-in-y #f)]
|
||||
[_ (make-object mred:horizontal-panel% ph)]
|
||||
[b (make-object mred:button% ph
|
||||
(lambda _ (send f show #f))
|
||||
"Hide")]
|
||||
[e (make-object mred:media-edit%)])
|
||||
(set! progress-frame f)
|
||||
(set! progress-canvas c)
|
||||
(set! progress-edit e)
|
||||
(send p add-child c)
|
||||
;;(send c set-media e)
|
||||
(send progress-frame set-size -1 -1 400 200);; ht was 130
|
||||
(send progress-frame show #f)))]
|
||||
|
||||
[new-progress-frame!
|
||||
(lambda ()
|
||||
(pretty-debug-gui `(new-progress-frame))
|
||||
(set! progress-edit (make-object mred:media-edit%))
|
||||
(send progress-edit lock #t)
|
||||
(send progress-canvas set-media progress-edit)
|
||||
(send progress-frame show #t)
|
||||
(send progress-frame iconize #f)
|
||||
(pretty-debug-gui `(new-progress-frame-done)))]
|
||||
|
||||
[with-progress-frame
|
||||
(lambda (thunk)
|
||||
(let*
|
||||
( [old-progress-handler (mrspidey:progress-handler)]
|
||||
[current '()]
|
||||
|
||||
[current-start-time 0]
|
||||
[width 6]
|
||||
[total-width 18])
|
||||
(letrec
|
||||
([insert-numbers
|
||||
(lambda (n)
|
||||
(send progress-edit insert
|
||||
(format "~a ~ams"
|
||||
(padl
|
||||
(if (eq? n 'done) "" (format "~a" n))
|
||||
width)
|
||||
(padl (- (current-process-milliseconds)
|
||||
(current-gc-milliseconds)
|
||||
current-start-time)
|
||||
width))
|
||||
(send progress-edit last-position)))]
|
||||
[f (match-lambda*
|
||||
[((? string? name) line)
|
||||
(if (equal? name current)
|
||||
(let ([end (send progress-edit last-position)])
|
||||
(send progress-edit delete
|
||||
(- end total-width) end)
|
||||
(insert-numbers line))
|
||||
(begin
|
||||
(f 'fresh-line)
|
||||
(set! current name)
|
||||
(set! current-start-time
|
||||
(- (current-process-milliseconds)
|
||||
(current-gc-milliseconds)))
|
||||
(send progress-edit insert
|
||||
(padr name 30))
|
||||
(insert-numbers line)))]
|
||||
[((? string? str))
|
||||
(f 'fresh-line)
|
||||
(send progress-edit insert str)
|
||||
(f #\newline)]
|
||||
[(#\newline)
|
||||
(send progress-edit insert (format "~n"))
|
||||
(set! current '())]
|
||||
[('fresh-line)
|
||||
(unless (null? current) (f #\newline))])]
|
||||
[g (lambda args
|
||||
(send progress-edit lock #f)
|
||||
(apply f args)
|
||||
(send progress-edit lock #t))])
|
||||
(parameterize
|
||||
([mrspidey:progress-handler
|
||||
(lambda args
|
||||
;;(apply old-progress-handler args)
|
||||
(apply g args)
|
||||
(wx:flush-display))])
|
||||
(send progress-frame show #t)
|
||||
(begin0
|
||||
(thunk)
|
||||
(mrspidey:progress
|
||||
"=Done======================================"))))))]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[filename->fileinfo
|
||||
(lambda (file)
|
||||
(pretty-debug-gui `(filename->fileinfo ,file))
|
||||
(or
|
||||
(ormap
|
||||
(match-lambda
|
||||
[(and fi ($ fileinfo filename frame))
|
||||
(and (string? file)
|
||||
(string=? filename file)
|
||||
fi)])
|
||||
fileinfo*)
|
||||
(assert #f 'filename->fileinfo file)))]
|
||||
|
||||
[filename->frame
|
||||
(lambda (file)
|
||||
(let ([x (filename->fileinfo file)])
|
||||
(and x (fileinfo-frame x))))]
|
||||
|
||||
[filename->edit
|
||||
(lambda (file)
|
||||
(let ([x (filename->frame file)])
|
||||
(and x (ivar x program-edit))))]
|
||||
|
||||
[for-each-frame
|
||||
(lambda (f)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ fileinfo filename frame)
|
||||
(when frame (f frame))])
|
||||
fileinfo*))]
|
||||
|
||||
[focus-def
|
||||
(lambda (loc)
|
||||
(assert (zodiac:location? loc) 'focus-def loc)
|
||||
(let* ([file (zodiac:location-file loc)]
|
||||
[frame (filename->frame file)])
|
||||
(if frame
|
||||
(send frame focus-def (zodiac:location-offset loc))
|
||||
(wx:message-box
|
||||
(format "File ~s is not loaded" (file-name-from-path file))
|
||||
"Error"
|
||||
(bitwise-ior wx:const-ok)))))]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[open-analyzed-file-choice
|
||||
(lambda ()
|
||||
(let ([choice
|
||||
(wx:get-single-choice
|
||||
"Select referenced unit file to open"
|
||||
"Open Unit"
|
||||
(sort string<? (map fileinfo-filename fileinfo*))
|
||||
'() -1 -1 #t 500 300)])
|
||||
(when (string? choice)
|
||||
(open-fileinfo (filename->fileinfo choice) #t))))]
|
||||
|
||||
[open-fileinfo
|
||||
(match-lambda*
|
||||
[((and fi ($ fileinfo filename frame)) show)
|
||||
(if frame
|
||||
(when show
|
||||
(send frame show #t)
|
||||
(send frame iconize #f))
|
||||
(add-frame fi show))])]
|
||||
|
||||
[open-all
|
||||
(lambda (show)
|
||||
(for-each
|
||||
(lambda (fi) (open-fileinfo fi show))
|
||||
fileinfo*))]
|
||||
|
||||
[add-frame
|
||||
(match-lambda*
|
||||
[( (and fi ($ fileinfo filename frame thunk-port thunk-expression))
|
||||
show
|
||||
. first-frame-locs)
|
||||
(pretty-debug-gui
|
||||
`(add-no-show-frame ,filename ,fi ,@first-frame-locs))
|
||||
(assert (not frame))
|
||||
(let ([summary-edit (make-object mred:media-edit%)])
|
||||
(initialize-summary summary-edit)
|
||||
(pretty-debug-gui `(summary-initialized))
|
||||
(parameterize
|
||||
([mrspidey:add-summary-handler (add-summary summary-edit)])
|
||||
(with-progress-frame
|
||||
(lambda ()
|
||||
(pretty-debug-gui '(progress-frame-initialized))
|
||||
(mrspidey:progress
|
||||
"===========================================")
|
||||
'(mrspidey:progress
|
||||
(format "Analyzing ~a" (file-name-from-path filename)))
|
||||
(let* ([annotations
|
||||
(calc-annotations (thunk-expression))]
|
||||
[_ (set-fileinfo-annotations! fi annotations)]
|
||||
[_ (pretty-debug-gui `(calling-Tframe ,filename))]
|
||||
[frame (apply make-object spidey:frame%
|
||||
;; only use margin
|
||||
this
|
||||
filename summary-edit
|
||||
first-frame-locs)])
|
||||
(pretty-debug-gui `(Have-Tframe ,filename))
|
||||
(when show (send frame show #t))
|
||||
(unless show (send frame show #t) (send frame show #f))
|
||||
(set-fileinfo-frame! fi frame)
|
||||
(update-arrows)
|
||||
)))))])]
|
||||
|
||||
[initialize-summary
|
||||
(lambda (edit)
|
||||
(let* ([delta (make-object wx:style-delta%
|
||||
wx:const-change-family
|
||||
wx:const-decorative)]
|
||||
[click-delta (make-object wx:style-delta%)])
|
||||
(send delta set-delta wx:const-change-size 10)
|
||||
(send click-delta copy delta)
|
||||
(send click-delta set-delta-foreground "BLUE")
|
||||
(send click-delta set-delta wx:const-change-underline 1)
|
||||
|
||||
(let ( [insert
|
||||
(lambda (s)
|
||||
(let ([before (send edit get-end-position)])
|
||||
(send edit insert s)
|
||||
(let ([after (send edit get-end-position)])
|
||||
(values before after))))])
|
||||
(let*-values
|
||||
( [(s1 e1) (insert "Welcome to ")]
|
||||
[(s2 e2) (insert "MrSpidey")]
|
||||
[(s3 e3) (insert (format ", version ~a." (mred:version)))]
|
||||
[(s4 e4) (insert (format "~n"))])
|
||||
(send edit change-style delta s1 e1)
|
||||
(send edit change-style click-delta s2 e2)
|
||||
(send edit change-style delta s3 e3)
|
||||
(send edit set-clickback s2 e2
|
||||
(lambda args
|
||||
(make-object mred:hyper-view-frame%
|
||||
(string-append
|
||||
"file:"
|
||||
(build-path
|
||||
(collection-path "mrspidey") ; MATTHEW: got rid of plt-home
|
||||
"about.html"))))
|
||||
click-delta)))))]
|
||||
|
||||
[local-record-analyzed-file
|
||||
(lambda (filename thunk-port thunk-expression)
|
||||
(pretty-debug-gui
|
||||
`(local-record-analyzed-file ,filename
|
||||
,thunk-port
|
||||
,thunk-expression))
|
||||
(set! fileinfo*
|
||||
(append fileinfo*
|
||||
(list (make-fileinfo filename #f
|
||||
thunk-port
|
||||
thunk-expression)))))]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[add-summary
|
||||
(lambda (summary-edit)
|
||||
(lambda line
|
||||
(send summary-edit lock #f)
|
||||
(match line
|
||||
[(str loc word-ofs)
|
||||
(cond
|
||||
[(zodiac:zodiac? loc)
|
||||
((add-summary summary-edit) str
|
||||
(zodiac:zodiac-start loc) word-ofs)]
|
||||
[(zodiac:location? loc)
|
||||
(let* ( [click (lambda ignore (focus-def loc))]
|
||||
[init-pos-box (box 0)]
|
||||
[_ (send summary-edit get-position init-pos-box)]
|
||||
[_ (send summary-edit insert str)]
|
||||
[_ (send summary-edit insert
|
||||
(format " in file ~s line ~s"
|
||||
(file-name-from-path
|
||||
(zodiac:location-file loc))
|
||||
(zodiac:location-line loc)))]
|
||||
[_ (send summary-edit insert #\newline)]
|
||||
;; Find start and end of word
|
||||
[end (unbox init-pos-box)]
|
||||
[_
|
||||
(for i 0 (add1 word-ofs)
|
||||
(set! end (mred:scheme-forward-match
|
||||
summary-edit end
|
||||
(send summary-edit last-position))))]
|
||||
[start (mred:scheme-backward-match summary-edit end 0)])
|
||||
|
||||
'(pretty-debug-gui
|
||||
`(send summary-edit change-style check-link-delta
|
||||
,(send check-link-delta get-underlined-on)
|
||||
,start ,end))
|
||||
;; Paranoia - check have proper locations
|
||||
(if (and start end)
|
||||
(begin
|
||||
(send summary-edit set-clickback start end click)
|
||||
(send summary-edit change-style check-link-delta
|
||||
start end))
|
||||
;; Error
|
||||
(pretty-print
|
||||
`(Error: annotate-summary
|
||||
,str ,loc ,word-ofs ,start ,end))))]
|
||||
[else
|
||||
(begin
|
||||
(printf
|
||||
"Bad location in main:add-summary-handler ~s~n"
|
||||
loc)
|
||||
(mrspidey:add-summary str))])]
|
||||
[(str)
|
||||
(send summary-edit insert str)
|
||||
(send summary-edit insert #\newline)]
|
||||
[x (printf "add-summary, can't handle ~s~n" x)])
|
||||
(send summary-edit lock #t)))]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[on-frame-close
|
||||
(lambda (filename)
|
||||
(void))]
|
||||
|
||||
[close-all-frames
|
||||
(lambda ()
|
||||
(send progress-frame show #f)
|
||||
(close-all-frames-except-progress)
|
||||
)]
|
||||
|
||||
[close-all-frames-except-progress
|
||||
(lambda ()
|
||||
(for-each-frame (lambda (frame) (send frame on-close)))
|
||||
)]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[annotated-edit
|
||||
(lambda (mode filename canvas)
|
||||
;; create edit buffer, load file and add annotations
|
||||
(pretty-debug-gui `(annotate-edit ,mode ,filename))
|
||||
(match (filename->fileinfo filename)
|
||||
[($ fileinfo filename frame thunk-port annotations)
|
||||
(let* ( [port (thunk-port)]
|
||||
[edit (make-object
|
||||
(mode-edit-class mode)
|
||||
(if (multiple-files) " " "")
|
||||
this canvas)])
|
||||
(send edit set-filename filename)
|
||||
(send edit edit-sequence
|
||||
(lambda ()
|
||||
(pretty-debug-gui "loading!")
|
||||
(let ([s (format "Loading ~a: "
|
||||
(file-name-from-path filename))])
|
||||
(recur loop ([n 1])
|
||||
(when (zero? (modulo n 50))
|
||||
(mrspidey:progress s n))
|
||||
(let ([r (read-line port)])
|
||||
;;(pretty-debug-gui `(inserting ,r))
|
||||
(if (eof-object? r)
|
||||
(mrspidey:progress s (sub1 n))
|
||||
(begin
|
||||
(send edit insert-line r)
|
||||
(loop (add1 n))))))
|
||||
(when (multiple-files)
|
||||
(for i 0 NUM-EXTRA-LINES (send edit insert-line ""))))
|
||||
(close-input-port port)
|
||||
(pretty-debug-gui `(last-line ,(send edit last-line)))
|
||||
(send edit change-style base-delta
|
||||
0 (send edit last-position))
|
||||
|
||||
(pretty-debug-gui "annotating!")
|
||||
(annotate! filename edit mode annotations)
|
||||
|
||||
(send edit set-position 0)
|
||||
(pretty-debug-gui `(annotate-buffer done))))
|
||||
|
||||
edit)]))]
|
||||
|
||||
[annotate!
|
||||
(lambda (filename edit mode annotations)
|
||||
(let ([s (format "Annotating ~a:" (file-name-from-path filename))])
|
||||
(mrspidey:progress s '...)
|
||||
(pretty-debug-gui `(annotate! ,filename ,edit ,mode ,annotations))
|
||||
(let ([annotation-fn-list (mode-annotation-fn-list mode)])
|
||||
(for-each
|
||||
(lambda (annotation-fn annotations)
|
||||
(when annotation-fn
|
||||
(for-each
|
||||
(let ([fn (uq-ivar edit annotation-fn)])
|
||||
(match-lambda
|
||||
[(and annotation ($ annotation loc))
|
||||
(when (string=? (zodiac:location-file loc)
|
||||
filename)
|
||||
;; Call the method named func to annotate etc.
|
||||
(fn annotation))]))
|
||||
annotations)))
|
||||
annotation-fn-list
|
||||
(vector->list annotations)))
|
||||
(mrspidey:progress s 'done)))]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[shake-it
|
||||
'(lambda ()
|
||||
(let* ([n (random (vector-length fileinfo*))]
|
||||
[fi (vector-ref fileinfo* n)]
|
||||
[frame (fileinfo-frame fi)])
|
||||
(send frame shake-it)))]
|
||||
|
||||
;; ------------------------------
|
||||
;; Arrows
|
||||
|
||||
[list-flow-arrows '()]
|
||||
[add-flow-arrow
|
||||
(lambda (src dest)
|
||||
(assert (and (FlowType? src) (FlowType? dest)))
|
||||
(pretty-debug-gui
|
||||
`(main:add-flow-arrow
|
||||
,(FlowType->pretty src) ,(FlowType->pretty dest)))
|
||||
(with-handlers
|
||||
([exn:flow-arrow-exists? (lambda (exn) (void))])
|
||||
(let ([flow-arrow (make-object flow-arrow% this src dest)])
|
||||
(when flow-arrow
|
||||
(set! list-flow-arrows (cons flow-arrow list-flow-arrows))))))]
|
||||
[draw-arrows
|
||||
(lambda ()
|
||||
(pretty-debug-gui `(main:draw-arrows))
|
||||
(for-each-frame
|
||||
(lambda (frame)
|
||||
(send (ivar frame program-edit) draw-arrows))))]
|
||||
[update-arrows
|
||||
(lambda ()
|
||||
(pretty-debug-gui `(main:update-arrows))
|
||||
(for-each
|
||||
(lambda (arrow) (send arrow update))
|
||||
list-flow-arrows)
|
||||
(draw-arrows))]
|
||||
[delete-arrow
|
||||
(lambda (arrow)
|
||||
(send arrow delete-local)
|
||||
(set! list-flow-arrows (remv arrow list-flow-arrows)))]
|
||||
[delete-arrow-refresh
|
||||
(lambda (arrow)
|
||||
(delete-arrow arrow)
|
||||
(draw-arrows))]
|
||||
[delete-arrows
|
||||
(lambda ()
|
||||
(for-each
|
||||
(lambda (arrow) (send arrow delete-local))
|
||||
list-flow-arrows)
|
||||
(set! list-flow-arrows '())
|
||||
(draw-arrows))]
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
[reanalyze 'reanalyze]
|
||||
|
||||
[run-mrspidey
|
||||
|
||||
(lambda (file . first-frame-locs)
|
||||
|
||||
(pretty-debug-gui `(run-mrspidey ,file))
|
||||
(set! reanalyze
|
||||
(lambda () (apply run-mrspidey file first-frame-locs)))
|
||||
|
||||
(close-all-frames-except-progress)
|
||||
(pretty-debug-gui `(frames-closed))
|
||||
(set! fileinfo* '())
|
||||
(new-progress-frame!)
|
||||
|
||||
(let ([file (normalize-path (normalize-path file))])
|
||||
;; Following calls record-anlyzed-file
|
||||
(st:analyze-and-make-annotations file)
|
||||
(apply add-frame (filename->fileinfo file) #t first-frame-locs)
|
||||
|
||||
))])
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(sequence
|
||||
(set! tm this)
|
||||
(record-analyzed-file-hook local-record-analyzed-file)
|
||||
(init-progress-frame!))))
|
||||
|
||||
(define spidey (make-object MrSpidey%))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; mode says for each set of annotations,
|
||||
;; either #f or fn to handle annotation.
|
||||
|
||||
(define-const-structure (mode name edit-class annotation-fn-list))
|
||||
|
||||
(define modes
|
||||
(list
|
||||
(make-mode
|
||||
"Types and Checks"
|
||||
flow-arrow:media-edit%
|
||||
(list
|
||||
'add-type-annotation
|
||||
'add-check-annotation
|
||||
'add-uncheck-annotation))
|
||||
(make-mode "Normal"
|
||||
spidey:static-edit%
|
||||
(list #f #f #f))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
@ -0,0 +1,330 @@
|
||||
;; prefs.ss - loads preferences
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define parameter-radio-boxes
|
||||
(lambda (name param sym p major-dim direction)
|
||||
(mred:set-preference-default sym (param)
|
||||
(lambda (x)
|
||||
(with-handlers ((exn? (lambda (exn) #f)))
|
||||
(param x)
|
||||
#t)))
|
||||
(param (mred:get-preference sym))
|
||||
(let* ([o
|
||||
(make-object
|
||||
mred:radio-box% p
|
||||
(lambda (bx event)
|
||||
;;(printf "~s~n" (param '?))
|
||||
(match
|
||||
(list-ref (param '?)
|
||||
(send event get-command-int))
|
||||
[(tag . _)
|
||||
(param tag)
|
||||
(mred:set-preference sym tag)]))
|
||||
name
|
||||
-1 -1 -1 -1
|
||||
(map cadr (param '?))
|
||||
major-dim
|
||||
direction)]
|
||||
[pairs
|
||||
(map
|
||||
(match-lambda [(tag name . _) (cons name tag)])
|
||||
(param '?))]
|
||||
[default-ndx
|
||||
(recur loop ([n 0][pairs pairs])
|
||||
(cond
|
||||
[(null? pairs)
|
||||
(error 'make-parameter-menu
|
||||
"Can't find para in pairs ~s" (param))]
|
||||
[(equal? (param) (cdar pairs)) n]
|
||||
[else (loop (add1 n) (cdr pairs))]))])
|
||||
(send o stretchable-in-x #t)
|
||||
(send o set-selection default-ndx)
|
||||
o
|
||||
)))
|
||||
|
||||
(define parameter-check-box
|
||||
(lambda (name param sym p)
|
||||
(mred:set-preference-default sym (param)
|
||||
(lambda (x)
|
||||
(with-handlers ((exn? (lambda (exn) #f)))
|
||||
(param x)
|
||||
#t)))
|
||||
(param (mred:get-preference sym))
|
||||
(let* ( [hp (make-object mred:horizontal-panel% p)]
|
||||
[o
|
||||
(make-object
|
||||
mred:check-box% hp
|
||||
(lambda (bx event)
|
||||
;;(printf "~s~n" (param '?))
|
||||
(match
|
||||
(list-ref (param '?)
|
||||
(send event get-command-int))
|
||||
[(tag . _)
|
||||
(param tag)
|
||||
(mred:set-preference sym tag)]))
|
||||
name
|
||||
-1 -1 -1 -1)]
|
||||
[_ (make-object mred:horizontal-panel% hp)])
|
||||
(send o set-value (param))
|
||||
o
|
||||
)))
|
||||
|
||||
;; ======================================================================
|
||||
;; MrSpidey Type Display
|
||||
|
||||
(define callbacks-sdl-alg-changed '())
|
||||
|
||||
(define (add-callback-sdl-alg-changed! fn)
|
||||
(set! callbacks-sdl-alg-changed (cons fn callbacks-sdl-alg-changed)))
|
||||
|
||||
(define (remq-callback-sdl-alg-changed! fn)
|
||||
(set! callbacks-sdl-alg-changed (remq fn callbacks-sdl-alg-changed)))
|
||||
|
||||
(define (sdl-alg-changed)
|
||||
(for-each
|
||||
(lambda (f) (f))
|
||||
callbacks-sdl-alg-changed))
|
||||
|
||||
(define (param-ctrls-sdl-alg param)
|
||||
(lambda args
|
||||
(sdl-alg-changed)
|
||||
(apply param args)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(mred:set-preference-default 'st:const-merge-size (st:const-merge-size)
|
||||
(lambda (x)
|
||||
(with-handlers ((exn? (lambda (exn) #f)))
|
||||
(st:const-merge-size x)
|
||||
#t)))
|
||||
(st:const-merge-size (mred:get-preference 'st:const-merge-size))
|
||||
|
||||
(define mrspidey-mk-analysis-pref-panel
|
||||
(lambda (panel)
|
||||
(let*
|
||||
( [p (make-object mred:vertical-panel% panel)]
|
||||
|
||||
[vp (make-object mred:vertical-panel% p -1 -1 -1 -1)]
|
||||
[_ (parameter-check-box
|
||||
"Accurate constant types"
|
||||
st:constants 'st:constants
|
||||
vp)]
|
||||
[g (make-object mred:slider% vp
|
||||
(lambda (slider event)
|
||||
(st:const-merge-size (send event get-command-int))
|
||||
(mred:set-preference 'st:const-merge-size
|
||||
(send event get-command-int)))
|
||||
"Constant merge size"
|
||||
(st:const-merge-size)
|
||||
1 100
|
||||
100)]
|
||||
[_ (send g enable #t)]
|
||||
[_ (parameter-check-box
|
||||
"If splitting"
|
||||
st:if-split 'st:if-split
|
||||
vp)]
|
||||
[_ (parameter-check-box
|
||||
"Flow sensitivity"
|
||||
st:flow-sensitive 'st:flow-sensitive
|
||||
vp)]
|
||||
[_ (parameter-check-box
|
||||
"Accurate analysis of numeric operations"
|
||||
st:numops 'st:numops
|
||||
vp)]
|
||||
[_2 (parameter-radio-boxes
|
||||
"Polymorphism:"
|
||||
st:polymorphism
|
||||
'st:polymorphism
|
||||
p 0 wx:const-horizontal)]
|
||||
|
||||
[vp (make-object mred:vertical-panel% p -1 -1 -1 -1)]
|
||||
[vphp (make-object mred:horizontal-panel% vp)]
|
||||
[_0 (make-object mred:message% vphp
|
||||
"Polymorphism simplification algorithms:")]
|
||||
[vphphp (make-object mred:horizontal-panel% vphp)]
|
||||
[_1 (parameter-radio-boxes
|
||||
" "
|
||||
st:constraint-simplification-poly
|
||||
'st:constraint-simplification-poly
|
||||
vp 0 wx:const-vertical)]
|
||||
|
||||
[_ (parameter-radio-boxes
|
||||
"Save .za files in:"
|
||||
st:save-za-in
|
||||
'st:save-za-in
|
||||
p
|
||||
0 wx:const-horizontal)]
|
||||
)
|
||||
|
||||
p)))
|
||||
|
||||
(mred:add-preference-panel
|
||||
"MrSpidey Analysis"
|
||||
mrspidey-mk-analysis-pref-panel)
|
||||
|
||||
(mrspidey-mk-analysis-pref-panel
|
||||
(make-object mred:horizontal-panel%
|
||||
(make-object mred:frame% '() "dummy")))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
;(mred:set-preference-default 'st:sdl-size-k (st:sdl-size-k))
|
||||
;(st:sdl-size-k (mred:get-preference 'st:sdl-size-k))
|
||||
|
||||
(define (indented-vertical-radio-box p name param sym)
|
||||
(let*
|
||||
( [vp (make-object mred:vertical-panel% p -1 -1 -1 -1)]
|
||||
[vphp1 (make-object mred:horizontal-panel% vp)]
|
||||
[_0 (make-object mred:message% vphp1 name)]
|
||||
[vphp2 (make-object mred:horizontal-panel% vp)]
|
||||
[spc (make-object mred:horizontal-panel% vphp2)]
|
||||
[_ (send spc user-min-width 20)]
|
||||
[_ (send spc stretchable-in-x #f)]
|
||||
[radio-box
|
||||
(parameter-radio-boxes
|
||||
'()
|
||||
param sym
|
||||
vphp2 0 wx:const-vertical)]
|
||||
[_ (send radio-box stretchable-in-x #t)]
|
||||
[_ (make-object mred:horizontal-panel% vphp2)])
|
||||
(void)))
|
||||
|
||||
(define mrspidey-mk-type-display-prefs-panel
|
||||
(lambda (panel)
|
||||
(let*
|
||||
( [p (make-object mred:vertical-panel% panel )])
|
||||
|
||||
(let*
|
||||
(
|
||||
[sdl-fo-container-panel
|
||||
(make-object mred:horizontal-panel% p)]
|
||||
[sdl-fo-sub-panel
|
||||
(make-object mred:horizontal-panel% p)]
|
||||
[spc (make-object mred:horizontal-panel% sdl-fo-sub-panel)]
|
||||
[_ (send spc user-min-width 20)]
|
||||
[_ (send spc stretchable-in-x #f)]
|
||||
[sdl-fo-sub-sub-panel
|
||||
(make-object mred:vertical-panel% sdl-fo-sub-panel)]
|
||||
[see-ivars-panel
|
||||
(parameter-check-box
|
||||
"Show instance variables"
|
||||
(param-ctrls-sdl-alg st:sdl-fo-ivars)
|
||||
'st:sdl-fo-ivars
|
||||
sdl-fo-sub-sub-panel)]
|
||||
[see-struct-fields-panel
|
||||
(parameter-check-box
|
||||
"Show structure fields"
|
||||
(param-ctrls-sdl-alg st:sdl-fo-struct-fields)
|
||||
'st:sdl-fo-struct-fields
|
||||
sdl-fo-sub-sub-panel)]
|
||||
[_ (parameter-radio-boxes
|
||||
"Show types as:"
|
||||
(match-lambda*
|
||||
[('?) (st:sdl-fo '?)]
|
||||
[() (st:sdl-fo)]
|
||||
[(x)
|
||||
(sdl-alg-changed)
|
||||
(let ([enable-sub-controls (eq? x 'basic-types)])
|
||||
(for-each
|
||||
(lambda (control)
|
||||
(send control enable enable-sub-controls))
|
||||
(list
|
||||
see-ivars-panel
|
||||
see-struct-fields-panel)))
|
||||
(st:sdl-fo x)])
|
||||
'st:sdl-fo
|
||||
sdl-fo-container-panel
|
||||
0 wx:const-horizontal)])
|
||||
(void))
|
||||
|
||||
(indented-vertical-radio-box p
|
||||
"Constraint simplification algorithms:"
|
||||
(param-ctrls-sdl-alg st:sdl-constraint-simplification)
|
||||
'st:sdl-constraint-simplification)
|
||||
|
||||
(parameter-radio-boxes
|
||||
"Type naming:"
|
||||
(param-ctrls-sdl-alg st:naming-strategy)
|
||||
'st:naming-strategy
|
||||
p 0 wx:const-horizontal)
|
||||
(parameter-radio-boxes
|
||||
"Primitive types:"
|
||||
(param-ctrls-sdl-alg st:primitive-types)
|
||||
'st:primitive-types
|
||||
p 0 wx:const-horizontal)
|
||||
|
||||
(let*
|
||||
(
|
||||
[st:expand-output-type-container-panel
|
||||
(make-object mred:horizontal-panel% p)]
|
||||
[st:expand-output-type-sub-panel
|
||||
(make-object mred:horizontal-panel% p)]
|
||||
[spc (make-object mred:horizontal-panel%
|
||||
st:expand-output-type-sub-panel)]
|
||||
[_ (send spc user-min-width 20)]
|
||||
[_ (send spc stretchable-in-x #f)]
|
||||
[sdl-tidy-object
|
||||
(parameter-check-box
|
||||
"Uses equivalences that make types tidy"
|
||||
(param-ctrls-sdl-alg st:sdl-tidy)
|
||||
'st:sdl-tidy
|
||||
st:expand-output-type-sub-panel)]
|
||||
[_ (parameter-check-box
|
||||
"Use equivalences to simplify types"
|
||||
(match-lambda*
|
||||
[('?) (st:expand-output-type '?)]
|
||||
[() (st:expand-output-type)]
|
||||
[(x)
|
||||
(sdl-alg-changed)
|
||||
(send sdl-tidy-object enable x)
|
||||
(st:expand-output-type x)])
|
||||
'st:expand-output-type
|
||||
st:expand-output-type-container-panel)])
|
||||
(void))
|
||||
|
||||
p)))
|
||||
|
||||
(mred:add-preference-panel
|
||||
"MrSpidey Type Display"
|
||||
mrspidey-mk-type-display-prefs-panel)
|
||||
|
||||
(mrspidey-mk-type-display-prefs-panel
|
||||
(make-object mred:horizontal-panel%
|
||||
(make-object mred:frame% '() "dummy")))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
'(define (make-parameter-menu parameter)
|
||||
(let* ([pairs
|
||||
(map
|
||||
(match-lambda [(tag name . _) (cons name tag)])
|
||||
(parameter '?))]
|
||||
[default-ndx
|
||||
(recur loop ([n 0][pairs pairs])
|
||||
(cond
|
||||
[(null? pairs)
|
||||
(error 'make-parameter-menu "Can't find para in pairs")]
|
||||
[(equal? (parameter) (cdar pairs)) n]
|
||||
[else (loop (add1 n) (cdr pairs))]))])
|
||||
(let ([menu (make-object mred:menu%)])
|
||||
(send menu append-check-set pairs parameter default-ndx)
|
||||
;;(parameter (cdar pairs))
|
||||
menu)))
|
||||
|
||||
|
||||
|
@ -0,0 +1,168 @@
|
||||
; progress.ss - not used
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define progress-box%
|
||||
(class mred:frame% (title arg-bar-names . top-left-loc)
|
||||
|
||||
(inherit show set-size)
|
||||
|
||||
(public
|
||||
num-bars
|
||||
bar-names
|
||||
bar-fractions
|
||||
the-canvas
|
||||
[top-margin 12]
|
||||
[bot-margin 24]
|
||||
[right-margin 20]
|
||||
[left-margin 10]
|
||||
[middle-margin 20]
|
||||
[bar-length 150]
|
||||
[line-spacing 8]
|
||||
[barname-width 58]
|
||||
[barname-height 12]
|
||||
[bar-margin 2]
|
||||
[solid-brush (make-object wx:brush% "DARKGREEN" wx:const-solid)]
|
||||
[trans-brush (make-object wx:brush% "DARKGREEN" wx:const-transparent)]
|
||||
[border-pen (make-object wx:pen% "BLACK" 1 wx:const-solid)]
|
||||
[in-pen (make-object wx:pen% "DARKGREEN" 1 wx:const-solid)]
|
||||
|
||||
[mark-progress
|
||||
(lambda (bar-num fraction)
|
||||
(vector-set! bar-fractions bar-num fraction)
|
||||
(send the-canvas on-paint))]
|
||||
)
|
||||
|
||||
(sequence
|
||||
|
||||
(super-init '() title -1 -1 200 200)
|
||||
|
||||
(set! num-bars (length arg-bar-names))
|
||||
(set! bar-names (list->vector arg-bar-names))
|
||||
(set! bar-fractions (make-vector num-bars 0))
|
||||
|
||||
(set! the-canvas
|
||||
(make-object
|
||||
(class wx:canvas% args
|
||||
(inherit get-dc)
|
||||
(public
|
||||
[on-paint
|
||||
(lambda ()
|
||||
(let ([the-dc (send the-canvas get-dc)])
|
||||
;; Draw the text
|
||||
(for i 0 num-bars
|
||||
'(pretty-print
|
||||
`(send the-dc draw-text
|
||||
,(vector-ref bar-names i)
|
||||
,left-margin
|
||||
,(+ top-margin
|
||||
(* (+ barname-height line-spacing) i))))
|
||||
(send the-dc draw-text
|
||||
(vector-ref bar-names i)
|
||||
left-margin
|
||||
(+ top-margin
|
||||
(* (+ barname-height line-spacing) i))))
|
||||
|
||||
; Draw the bar borders
|
||||
(send the-dc set-pen border-pen)
|
||||
(send the-dc set-brush trans-brush)
|
||||
(for i 0 num-bars
|
||||
'(pretty-print `(send the-dc draw-rectangle
|
||||
,(+ left-margin barname-width middle-margin)
|
||||
,(+ top-margin
|
||||
(* (+ barname-height line-spacing) i))
|
||||
,(+ (* bar-length 1) (* 2 bar-margin))
|
||||
,barname-height))
|
||||
(send the-dc draw-rectangle
|
||||
(+ left-margin barname-width middle-margin)
|
||||
(+ top-margin
|
||||
(* (+ barname-height line-spacing) i))
|
||||
(+ (* bar-length 1) (* 2 bar-margin))
|
||||
barname-height))
|
||||
|
||||
;; Draw the bars
|
||||
(send the-dc set-pen in-pen)
|
||||
(send the-dc set-brush solid-brush)
|
||||
(for i 0 num-bars
|
||||
(unless (zero? (vector-ref bar-fractions i))
|
||||
'(pretty-print `(send the-dc draw-rectangle
|
||||
,(+ left-margin barname-width middle-margin
|
||||
bar-margin)
|
||||
,(+ top-margin
|
||||
(* (+ barname-height line-spacing) i)
|
||||
bar-margin)
|
||||
,(vector-ref bar-fractions i)
|
||||
,(* bar-length (vector-ref bar-fractions i))
|
||||
,(- barname-height (* 2 bar-margin))))
|
||||
(send the-dc draw-rectangle
|
||||
(+ left-margin barname-width middle-margin
|
||||
bar-margin)
|
||||
(+ top-margin
|
||||
(* (+ barname-height line-spacing) i)
|
||||
bar-margin)
|
||||
(* bar-length (vector-ref bar-fractions i))
|
||||
(- barname-height (* 2 bar-margin)))))
|
||||
)
|
||||
(wx:flush-display))])
|
||||
|
||||
(sequence
|
||||
(apply super-init args)
|
||||
(let ([the-dc (get-dc)])
|
||||
(send the-dc set-font
|
||||
(make-object wx:font% 12 wx:const-modern
|
||||
wx:const-normal wx:const-normal #f))
|
||||
)))
|
||||
|
||||
this))
|
||||
|
||||
'(let* ([sizes
|
||||
(map
|
||||
(lambda (name)
|
||||
(let ([wb (box 0)]
|
||||
[hb (box 0)])
|
||||
(printf ".") (flush-output)
|
||||
(send (send the-canvas get-dc) get-text-extent name wb hb)
|
||||
(printf ".") (flush-output)
|
||||
(cons (unbox wb) (unbox hb))))
|
||||
arg-bar-names)])
|
||||
|
||||
(pretty-print `(sizes ,sizes))
|
||||
(set! barname-width (apply max (map car sizes)))
|
||||
(set! barname-height (apply max (map cdr sizes))))
|
||||
|
||||
;; Set the frame size + position
|
||||
(let ([w (+ left-margin barname-width middle-margin
|
||||
bar-length (* 2 bar-margin) right-margin)]
|
||||
[h (+ top-margin
|
||||
(* (+ barname-height line-spacing) num-bars)
|
||||
bot-margin)])
|
||||
(match top-left-loc
|
||||
[(x y) (set-size (- x w) y w h)]
|
||||
[() (void)])
|
||||
(set-size w h))
|
||||
;; We're ready
|
||||
(show #t)
|
||||
(wx:flush-display)
|
||||
(wx:yield)
|
||||
)))
|
||||
|
||||
'(begin
|
||||
(define p (make-object progress-box% "title" '("bar-name-1" "bar-name-2")))
|
||||
(send p mark-progress 0 0.3)
|
||||
(send p mark-progress 1 0.6)
|
||||
)
|
||||
|
@ -0,0 +1,72 @@
|
||||
; statedit.ss
|
||||
; Defines spidey:static-edit%, a subclass of mred:media-edit%
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define spidey:static-edit%
|
||||
(class mred:searching-edit% init-args
|
||||
(inherit
|
||||
insert delete flash-on flash-off get-text
|
||||
set-clickback change-style lock
|
||||
set-position load-file
|
||||
get-keymap scroll-to-position
|
||||
last-position get-style-list
|
||||
set-mode
|
||||
begin-edit-sequence end-edit-sequence
|
||||
)
|
||||
|
||||
(public
|
||||
[begin-edit-sequence-and-unlock
|
||||
(lambda ()
|
||||
(wx:begin-busy-cursor)
|
||||
(lock #f)
|
||||
(begin-edit-sequence))]
|
||||
[end-edit-sequence-and-lock
|
||||
(lambda ()
|
||||
(end-edit-sequence)
|
||||
(lock #t)
|
||||
(wx:end-busy-cursor))]
|
||||
[edit-sequence
|
||||
(lambda (thunk)
|
||||
(dynamic-wind
|
||||
begin-edit-sequence-and-unlock
|
||||
thunk
|
||||
end-edit-sequence-and-lock))]
|
||||
[match-paren-forward
|
||||
(lambda (source-start)
|
||||
(mred:scheme-forward-match
|
||||
this source-start (last-position)))]
|
||||
)
|
||||
|
||||
(sequence
|
||||
|
||||
(apply super-init init-args)
|
||||
|
||||
(set-mode (make-object mred:scheme-mode%))
|
||||
;; disable paste for errant right mouse clicks
|
||||
(let ([ k (get-keymap)])
|
||||
(send k add-mouse-function "nothing" (lambda l (void)))
|
||||
(send k map-function "middlebutton" "nothing")
|
||||
(send k map-function "rightbutton" "nothing"))
|
||||
|
||||
;; make snips go down instead of up
|
||||
;; oops - can't do this :-(
|
||||
'(let ([stan (send (get-style-list) find-named-style "Standard")])
|
||||
(when stan (send stan set-delta normal-delta)))
|
||||
|
||||
(lock #t)
|
||||
)))
|
@ -0,0 +1,23 @@
|
||||
;; test-gui.ss
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define test-gui-shake-reps 25)
|
||||
|
||||
(define (shake-test-files) test-files)
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (test-gui-file f)
|
||||
(printf "FILE: ~s~n" f)
|
||||
(let* ([ftd (list f (lambda () (open-input-file f)) #t)]
|
||||
[ftd* (list ftd)])
|
||||
(send spidey do-and-show-analysis ftd*)
|
||||
(for i 0 test-gui-shake-reps
|
||||
(printf "Iteration ~s/~s~n" i test-gui-shake-reps)
|
||||
(send spidey shake-it))
|
||||
(send spidey close-all-frames)))
|
||||
|
||||
(define (test-gui)
|
||||
(for-each test-gui-file (shake-test-files)))
|
||||
|
||||
|
@ -0,0 +1,307 @@
|
||||
;; atenv.ss
|
||||
;; Section for handling environment
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-const-typed-structure
|
||||
atenv ( (: immut (listof (cons zodiac:binding FlowType)))
|
||||
(: notcap (listof (cons zodiac:binding mutable-binding)))
|
||||
(: cap (listof (cons zodiac:binding mutable-binding)))
|
||||
(: flushed (listof (cons zodiac:binding mutable-binding)))
|
||||
(: unflushed (listof (cons zodiac:binding mutable-binding)))
|
||||
(: both (listof (cons zodiac:binding mutable-binding)))))
|
||||
|
||||
(define-const-typed-structure
|
||||
mutable-binding ( (: current FlowType)
|
||||
(: at-transfer Tvar)
|
||||
(: flushed bool)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define atenv:empty (make-atenv '() '() '() '() '() '()))
|
||||
|
||||
(define (atenv:extend-mutated env name ftype tvar)
|
||||
(pretty-debug-atenv `(atenv:extend-mutated ,(atenv->pretty env)))
|
||||
(assert (zodiac:binding? name) 'atenv:extend name)
|
||||
(let ([ftype (link-parsed-ftype! name ftype)])
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(make-atenv
|
||||
i
|
||||
(extend-env n name
|
||||
(make-mutable-binding
|
||||
ftype tvar
|
||||
#f))
|
||||
c f u b)])))
|
||||
|
||||
(define (atenv:extend env name ftype)
|
||||
(pretty-debug-atenv `(atenv:extend ,(atenv->pretty env)))
|
||||
(assert (zodiac:binding? name) 'atenv:extend name)
|
||||
(let ([ftype (link-parsed-ftype! name ftype)])
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(if (zodiac:binding-mutated name)
|
||||
(make-atenv
|
||||
i
|
||||
(extend-env n name
|
||||
(make-mutable-binding
|
||||
ftype
|
||||
(mk-Tvar 'mut-var
|
||||
;;(symbol-append 'mut-var- (zodiac:binding-var name))
|
||||
)
|
||||
#f))
|
||||
c f u b)
|
||||
(make-atenv
|
||||
(extend-env i name ftype)
|
||||
n c f u b))])))
|
||||
|
||||
(define (atenv:extend* env names ftypes)
|
||||
(foldr2 (lambda (name ftype env) (atenv:extend env name ftype))
|
||||
env names ftypes))
|
||||
|
||||
(define (atenv:extend-voids env names)
|
||||
(atenv:extend* env names (map (lambda (x) (mk-tvar-void)) names)))
|
||||
|
||||
(define (atenv:extend-undefineds env names)
|
||||
(atenv:extend* env names (map (lambda (x) (mk-tvar-undefined)) names)))
|
||||
|
||||
(define (atenv:lookup env name)
|
||||
(pretty-debug-atenv `(atenv:lookup ,(atenv->pretty env)))
|
||||
(if (zodiac:binding-mutated name)
|
||||
(match (or
|
||||
(lookup-or-#f (atenv-notcap env) name)
|
||||
(lookup-or-#f (atenv-cap env) name)
|
||||
(lookup-or-#f (atenv-flushed env) name)
|
||||
(lookup-or-#f (atenv-unflushed env) name)
|
||||
(lookup-or-#f (atenv-both env) name))
|
||||
[($ mutable-binding cur) cur]
|
||||
[x x])
|
||||
(lookup-or-#f (atenv-immut env) name)))
|
||||
|
||||
(define (atenv:change-binding env name ftype)
|
||||
(pretty-debug-atenv
|
||||
`(->atenv:change-binding
|
||||
,(zodiac:binding-var name) ,(FlowType->pretty ftype)
|
||||
,(atenv->pretty env)))
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(let/cc k
|
||||
(let*
|
||||
([err
|
||||
(lambda ()
|
||||
(pretty-debug-atenv
|
||||
`(atenv:change-binding
|
||||
,(zodiac:binding-var name)
|
||||
,(map zodiac:binding-var (map car env))))
|
||||
(mrspidey:warning
|
||||
(format "Unbound variable ~s" (zodiac:binding-var name))
|
||||
(zodiac:zodiac-start name)
|
||||
2)
|
||||
(k env))]
|
||||
[result-env
|
||||
(if (zodiac:binding-mutated name)
|
||||
(let ([chg-fn
|
||||
(match-lambda
|
||||
[($ mutable-binding cur at-transfer)
|
||||
(make-mutable-binding ftype at-transfer #f)])])
|
||||
(if (lookup-or-#f n name)
|
||||
(make-atenv
|
||||
i
|
||||
(env:change-binding n name chg-fn err)
|
||||
c f u b)
|
||||
;; Must be in one of c f u b
|
||||
;; Lift out to captured
|
||||
(if (lookup-or-#f c name)
|
||||
(make-atenv
|
||||
i n
|
||||
(env:change-binding c name chg-fn err)
|
||||
f u b)
|
||||
(let*-vals
|
||||
([(bind f u b)
|
||||
(cond
|
||||
[(lookup-or-#f f name)
|
||||
(let*-vals ([(bind f) (env:remove f name)])
|
||||
(values bind f u b))]
|
||||
[(lookup-or-#f u name)
|
||||
(let*-vals ([(bind u) (env:remove u name)])
|
||||
(values bind f u b))]
|
||||
[(lookup-or-#f b name)
|
||||
(let*-vals ([(bind b) (env:remove b name)])
|
||||
(values bind f u b))]
|
||||
[else (err)])])
|
||||
(make-atenv
|
||||
i n
|
||||
(extend-env c name (chg-fn bind))
|
||||
f u b)))))
|
||||
(make-atenv
|
||||
(env:change-binding i name (lambda (old) ftype) err)
|
||||
n c f u b))])
|
||||
(pretty-debug-atenv
|
||||
`(->atenv:change-binding-returns ,(atenv->pretty result-env)))
|
||||
result-env))]))
|
||||
|
||||
(define (atenv:change-bindings env bindings ftypes)
|
||||
(foldr2
|
||||
(lambda (binding ftype env)
|
||||
(atenv:change-binding env binding ftype))
|
||||
env bindings ftypes))
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
(define (atenv:capture-locs env bindings)
|
||||
(pretty-debug-atenv
|
||||
`(atenv:capture-locs ,(atenv->pretty env) ,(map zodiac:binding-var bindings)))
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(recur loop ([n n][n-ok '()][c c])
|
||||
(if (null? n)
|
||||
(make-atenv i n-ok c f u b)
|
||||
(if (and
|
||||
(memq (caar n) bindings)
|
||||
;; ### KLUDGE FOR DECENT, BUT POSSIBLY WRONG, POLYMORPHISM
|
||||
(not (poly-atype? (FlowType->Atype
|
||||
(mutable-binding-current (cdar n))))))
|
||||
(loop (cdr n) n-ok (cons (car n) c))
|
||||
(loop (cdr n) (cons (car n) n-ok) c))))]))
|
||||
|
||||
(define (atenv:unflush env)
|
||||
(pretty-debug-atenv `(atenv:unflush ,(atenv->pretty env)))
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(let ([upd
|
||||
(match-lambda
|
||||
[(name . ($ mutable-binding cur trans))
|
||||
(cons name (make-mutable-binding trans trans #t))])])
|
||||
(make-atenv
|
||||
i n '() '()
|
||||
(append (map upd c) u)
|
||||
(append (map upd f) b)))]))
|
||||
|
||||
(define (atenv:flush! env)
|
||||
(pretty-debug-atenv `(atenv:flush! ,(atenv->pretty env)))
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(let ([upd
|
||||
(match-lambda
|
||||
[(name . (and bind ($ mutable-binding cur trans flushed)))
|
||||
(unless flushed
|
||||
(new-edge! (FlowType->Tvar cur) trans)
|
||||
(set-mutable-binding-flushed! bind #t))])])
|
||||
(for-each upd c)
|
||||
(for-each upd u)
|
||||
(make-atenv i n '() (append c f) '() (append u b)))]))
|
||||
|
||||
(define (atenv->pretty env)
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(let ([p (match-lambda
|
||||
[(name . ($ mutable-binding cur trans))
|
||||
(list (zodiac:binding-var name)
|
||||
(list
|
||||
(FlowType->pretty cur)
|
||||
(FlowType->pretty trans)))])])
|
||||
|
||||
(list
|
||||
(map (match-lambda
|
||||
[(name . ftype)
|
||||
(list
|
||||
(zodiac:binding-var name)
|
||||
(FlowType->pretty ftype))])
|
||||
i)
|
||||
(map p n)
|
||||
(map p c)
|
||||
(map p f)
|
||||
(map p u)
|
||||
(map p b)))]))
|
||||
|
||||
(define (atenv:domain env)
|
||||
(match env
|
||||
[($ atenv i n c f u b)
|
||||
(map car (append i n c f u b))]))
|
||||
|
||||
(define (atenv:ok? e)
|
||||
(and
|
||||
(atenv? e)
|
||||
(match e
|
||||
[($ atenv i n c f u b)
|
||||
(and
|
||||
(list? i)
|
||||
(andmap
|
||||
(match-lambda
|
||||
[(($ zodiac:binding) . ($ FlowType)) #t]
|
||||
[_ #f])
|
||||
i)
|
||||
(andmap
|
||||
(lambda (n)
|
||||
(and
|
||||
(list? n)
|
||||
(andmap
|
||||
(match-lambda
|
||||
[(($ zodiac:binding) . ($ mutable-binding)) #t]
|
||||
[_ #f])
|
||||
n)))
|
||||
(list n c f u b)))])))
|
||||
|
||||
'(defmacro check-atenv-fn-ok (fn)
|
||||
(let ( [old-fn (gensym)])
|
||||
`(begin
|
||||
(define ,old-fn ,fn)
|
||||
(define ,fn
|
||||
(let ([env-ok atenv:ok?])
|
||||
(lambda (env . rest)
|
||||
;;(printf "Entering ~s~n" (quote ,fn))
|
||||
(unless (env-ok env)
|
||||
(pretty-print env)
|
||||
(error (quote ,fn) "Bad env on entry"))
|
||||
(let ([r (apply ,old-fn env rest)])
|
||||
;;(printf "exiting ~s~n" (quote ,fn))
|
||||
(unless (env-ok env)
|
||||
(error (quote ,fn) "Bad env on exit"))
|
||||
r)))))))
|
||||
|
||||
;(check-atenv-fn-ok atenv:extend)
|
||||
;(check-atenv-fn-ok atenv:extend*)
|
||||
;(check-atenv-fn-ok atenv:extend-voids)
|
||||
;(check-atenv-fn-ok atenv:change-binding)
|
||||
;(check-atenv-fn-ok atenv:change-bindings)
|
||||
;(check-atenv-fn-ok atenv:capture-locs)
|
||||
;(check-atenv-fn-ok atenv:unflush)
|
||||
;(check-atenv-fn-ok atenv:flush!)
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (link-parsed-ftype! parsed ftype)
|
||||
(assert (FlowType? ftype) 'link-parsed-ftype! ftype)
|
||||
(if need-label-types
|
||||
(let ([nu-ftype
|
||||
(if (and need-explanation (FlowType-expr ftype))
|
||||
(copy-ftype ftype)
|
||||
ftype)])
|
||||
(pretty-debug-object
|
||||
`(link-parsed-ftype!
|
||||
,(zodiac:stripper parsed)
|
||||
,(zodiac:location-offset (zodiac:zodiac-start parsed))
|
||||
,(FlowType-name ftype)))
|
||||
(zodiac:set-parsed-ftype! parsed nu-ftype)
|
||||
(set-FlowType-expr! nu-ftype #t) ;parsed
|
||||
nu-ftype)
|
||||
ftype))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
|
||||
|
@ -0,0 +1,765 @@
|
||||
;; atlunit.ss
|
||||
;; Handles annotated lazy units - units, cmpd-units and reference-units
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; The structures ...
|
||||
|
||||
(define-const-typed-structure
|
||||
(atlunit-unit struct:atlunit)
|
||||
((: env (listof (cons zodiac:binding FlowType)))
|
||||
(: exp zodiac:unit-form)))
|
||||
|
||||
(define (create-atlunit-unit env exp)
|
||||
(make-atlunit-unit #f env exp))
|
||||
|
||||
;; -----
|
||||
|
||||
(define-const-typed-structure
|
||||
(atlunit-cmpd struct:atlunit)
|
||||
((: cmpd-unit zodiac:compound-unit-form)
|
||||
(: times (listof num))
|
||||
(: ftype* (listof FlowType))))
|
||||
|
||||
(define (create-atlunit-cmpd cmpd-unit time* ftype*)
|
||||
(make-atlunit-cmpd #f cmpd-unit time* ftype*))
|
||||
|
||||
;; -----
|
||||
|
||||
(define-const-typed-structure
|
||||
(atlunit-reference struct:atlunit)
|
||||
((: exp zodiac:sexp)))
|
||||
|
||||
(define (create-atlunit-reference exp)
|
||||
(assert (zodiac:reference-unit-form? exp))
|
||||
(make-atlunit-reference #f exp))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; (: partial-import-list
|
||||
;; (union false (listof (cons (union FlowType false) time))))
|
||||
|
||||
(define (pretty-partial-import-list pil)
|
||||
(and pil
|
||||
(map (match-lambda
|
||||
[(ftype . itime)
|
||||
(cons (and ftype (FlowType->pretty ftype)) itime)])
|
||||
pil)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (apply-unit unit partial-import-list)
|
||||
(: unit FlowType)
|
||||
;; returns (union atunit Tvar)
|
||||
(match (FlowType->Atype unit)
|
||||
[(? atlunit? atlunit) (apply-atlunit atlunit partial-import-list)]
|
||||
[($ atunit imports exports result expr)
|
||||
(let ([imports
|
||||
(cond
|
||||
[(eq? partial-import-list #f) imports]
|
||||
[(= (length imports) (length partial-import-list))
|
||||
(map (match-lambda*
|
||||
[((sym . tvars) (ftype . _))
|
||||
(if ftype
|
||||
(begin
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(new-edge! (FlowType->Tvar ftype) tvar))
|
||||
tvars)
|
||||
(list sym))
|
||||
(cons sym tvars))])
|
||||
imports partial-import-list)]
|
||||
[else
|
||||
(let ([msg (format "Unit takes ~s imports, given ~s"
|
||||
(length imports) (length partial-import-list))])
|
||||
(if (zodiac:parsed? expr)
|
||||
(mrspidey:warning msg expr 0)
|
||||
(mrspidey:warning msg)))
|
||||
imports])])
|
||||
(make-atunit imports exports result expr))]
|
||||
[(? Tvar? tvar-u)
|
||||
(for-each-with-n
|
||||
(match-lambda*
|
||||
[((ftype . _) n)
|
||||
(new-con! tvar-u
|
||||
(create-con (get-unit-import-template n)
|
||||
0 (FlowType->Tvar ftype) #f))])
|
||||
partial-import-list)
|
||||
tvar-u]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (atlunit->atunit atlunit)
|
||||
;; returns atunit
|
||||
(apply-atlunit atlunit #f))
|
||||
|
||||
(define gatlunit (void))
|
||||
|
||||
(define (apply-atlunit atlunit partial-import-list)
|
||||
(: partial-import-list (listof (cons (union FlowType false) num)))
|
||||
;; (returns atunit)
|
||||
(set! gatlunit atlunit)
|
||||
(match atlunit
|
||||
[(and atlunit ($ atlunit ui))
|
||||
(assert (or (eq? ui #f) (atunit? ui)))
|
||||
(when (and ui partial-import-list)
|
||||
(pretty-debug-unit `(ui ,ui partial-import-list ,partial-import-list))
|
||||
(mrspidey:error
|
||||
"Annotated lazy unit invoked more than once"
|
||||
(match atlunit
|
||||
[($ atlunit-unit _ _ exp) exp]
|
||||
[($ atlunit-cmpd _ exp) exp]
|
||||
[($ atlunit-reference _ exp) exp])))
|
||||
(or ui
|
||||
(let* ( [fn
|
||||
(cond
|
||||
[(atlunit-unit? atlunit) apply-atlunit-unit]
|
||||
[(atlunit-cmpd? atlunit) apply-atlunit-cmpd]
|
||||
[(atlunit-reference? atlunit) apply-atlunit-reference]
|
||||
[else (mrspidey:internal-error
|
||||
'apply-atlunit->atunit "Not a lazy unit")])]
|
||||
[ui (fn atlunit partial-import-list)])
|
||||
(set-atlunit-ui! atlunit ui)
|
||||
ui))]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (apply-atlunit-unit atlunit partial-import-list)
|
||||
(match atlunit
|
||||
[($ atlunit-unit _ env
|
||||
(and unit-exp ($ zodiac:unit-form _ s _ _ imports exports body)))
|
||||
(pretty-debug-unit
|
||||
`(apply-atlunit-unit
|
||||
,(zodiac:stripper unit-exp)
|
||||
,(and partial-import-list
|
||||
(map FlowType->pretty (map car partial-import-list))))
|
||||
7)
|
||||
|
||||
(let*-vals
|
||||
( [free-names (zodiac:free-vars-defs body)]
|
||||
[free-names2 (setdiff2 free-names imports)]
|
||||
[init-env (get-default-bindings free-names2)]
|
||||
[env1 (cond
|
||||
[(eq? partial-import-list #f) init-env]
|
||||
[(not (= (length imports) (length partial-import-list)))
|
||||
(mrspidey:error
|
||||
(format
|
||||
"Bad number of imports for unit, expected ~s, given ~s"
|
||||
(length imports)
|
||||
(length partial-import-list)))]
|
||||
[else (foldr2
|
||||
(lambda (name ftype env)
|
||||
(if ftype
|
||||
(atenv:extend env name ftype)
|
||||
env))
|
||||
init-env
|
||||
imports
|
||||
(map car partial-import-list))])]
|
||||
[(env2 refs result) (traverse-defs body env1)]
|
||||
;;[_ (pretty-print `(env2 ,(atenv->pretty env2)))]
|
||||
[env3 (atenv:unflush (atenv:flush! env2))]
|
||||
;;[_ (pretty-print `(env3 ,(atenv->pretty env2)))]
|
||||
[exports
|
||||
(map
|
||||
(match-lambda
|
||||
[(lvr . z-sym)
|
||||
(let* ( [binding (zodiac:varref-binding lvr)]
|
||||
[ftype (atenv:lookup env3 binding)]
|
||||
[_ (assert (FlowType? ftype) 'atlunit-unit->atunit
|
||||
binding)]
|
||||
[ftype (link-parsed-ftype! lvr ftype)])
|
||||
(cons (zodiac:read-object z-sym) ftype))])
|
||||
exports)]
|
||||
[imports
|
||||
(map (lambda (name)
|
||||
(cons (zodiac:binding-var name)
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[(name2 . tvar)
|
||||
(and (eq? name name2) tvar)])
|
||||
refs)))
|
||||
imports)])
|
||||
(make-atunit imports exports result unit-exp))]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (apply-atlunit-cmpd atlunit partial-import-list)
|
||||
(match atlunit
|
||||
[($ atlunit-cmpd _
|
||||
(and cmpd-unit
|
||||
($ zodiac:compound-unit-form _ start _ _
|
||||
import-bindings links exports))
|
||||
times ftype*)
|
||||
(: import-bindings (listof zodiac:lexical-binding))
|
||||
(: links
|
||||
(listof (list sym zodiac:parsed (listof (cons (union sym #f) sym)))))
|
||||
(: times (listof num))
|
||||
(: ftype* (listof FlowType))
|
||||
(: exports (listof (list sym sym sym)))
|
||||
|
||||
(pretty-debug-unit
|
||||
`(apply-atlunit-cmpd
|
||||
,(map zodiac:binding-orig-name import-bindings)
|
||||
,(zodiac:stripper cmpd-unit)
|
||||
,(map FlowType->pretty ftype*)
|
||||
,exports
|
||||
,(and partial-import-list
|
||||
(map FlowType->pretty (map car partial-import-list)))))
|
||||
|
||||
(letrec*
|
||||
( [time-N (zodiac-time cmpd-unit)]
|
||||
[saved-refs '()] ; forward refs and refs to some imports
|
||||
[imports (map zodiac:binding-orig-name import-bindings)]
|
||||
[import-env
|
||||
(cond
|
||||
[(eq? partial-import-list #f) '()]
|
||||
[(not (= (length imports) (length partial-import-list)))
|
||||
(mrspidey:warning
|
||||
(format "Compound-unit requires ~s imports, given ~s"
|
||||
(length imports) (length partial-import-list))
|
||||
start 0)
|
||||
'()]
|
||||
[else
|
||||
(map
|
||||
(lambda (import-binding import ftype-time)
|
||||
(let* ( [ftype (car ftype-time)]
|
||||
[_ (assert (FlowType? ftype) 'atlunit-3 ftype)]
|
||||
[ftype (link-parsed-ftype! import-binding ftype)]
|
||||
[ftype-time (cons ftype (cdr ftype-time))])
|
||||
(cons import ftype-time)))
|
||||
import-bindings
|
||||
imports
|
||||
partial-import-list)])]
|
||||
[import-refs (make-vector (length imports) '())]
|
||||
[access-import
|
||||
(lambda (sym)
|
||||
(match (lookup-or-fail import-env sym (lambda () (cons #f 0)))
|
||||
[(ftype . itime)
|
||||
(values
|
||||
(or ftype
|
||||
(let ([tvar (mk-Tvar 'get-export)]
|
||||
[n (index imports sym)])
|
||||
(if n
|
||||
(vector-set! import-refs n
|
||||
(cons tvar (vector-ref import-refs n)))
|
||||
(mrspidey:warning
|
||||
(format
|
||||
"Symbol ~s not in import list of compound-unit"
|
||||
sym)
|
||||
(zodiac:zodiac-start cmpd-unit) 7))
|
||||
tvar))
|
||||
(max time-N itime))]))]
|
||||
;; alist of tags and function to access exports
|
||||
[tag->access (list (cons #f access-import))]
|
||||
[tag.sym->ftype.time
|
||||
(lambda (tag sym)
|
||||
(assert (or (not tag) (symbol? tag)) tag 'tag.sym->ftype.time2)
|
||||
(assert (symbol? sym) sym 'tag.sym->ftype.time2)
|
||||
(match (lookup-or-#f tag->access tag)
|
||||
[(? procedure? access) (access sym)]
|
||||
[#f (let ([tvar (mk-Tvar 'forward-get-export)])
|
||||
(set! saved-refs (cons (list tag sym tvar) saved-refs))
|
||||
(values tvar time-N))]))]
|
||||
[last-invoked-unit #f]
|
||||
[_
|
||||
(for-each
|
||||
(lambda (link time-U ftype)
|
||||
(match-let*
|
||||
( [(tag _ . i*) link]
|
||||
;; [_ (pretty-print `(i* ,i* tag ,tag link ,link))]
|
||||
;; tag is not a zodiac:parsed, so cant hang type off it
|
||||
;; [ftype (link-parsed-ftype! tag ftype)]
|
||||
[tag (zodiac:read-object tag)]
|
||||
;; Figure out imports
|
||||
[import-ftype.times
|
||||
(map
|
||||
(lambda (i)
|
||||
(let*-vals
|
||||
([(tag sym)
|
||||
(match i
|
||||
[(tag . sym)
|
||||
(values
|
||||
(zodiac:read-object tag)
|
||||
(zodiac:read-object sym))]
|
||||
[($ zodiac:lexical-varref)
|
||||
(values #f
|
||||
(zodiac:binding-orig-name
|
||||
(zodiac:varref-binding i)))])]
|
||||
[_ (assert (or (not tag) (symbol? tag)) 1)]
|
||||
[(ftype itime) (tag.sym->ftype.time tag sym)]
|
||||
;;#[ftype (link-parsed-ftype! i ftype)]
|
||||
)
|
||||
(cons ftype itime)))
|
||||
i*)]
|
||||
[time-export (apply max time-N time-U
|
||||
(map cdr import-ftype.times))]
|
||||
[_ (pretty-debug-unit
|
||||
`(apply-atlunit-cmpd
|
||||
invoking ,tag ,ftype ,import-ftype.times))]
|
||||
[invoked-unit (apply-unit ftype import-ftype.times)]
|
||||
[_ (pretty-debug-unit
|
||||
`(apply-atlunit-cmpd result tag ,tag ,invoked-unit))]
|
||||
[_ (set! last-invoked-unit invoked-unit)]
|
||||
[access-exports
|
||||
(match invoked-unit
|
||||
[($ atunit imports exports)
|
||||
(lambda (sym)
|
||||
(match (lookup-or-#f exports sym)
|
||||
[#f (mrspidey:warning
|
||||
(format
|
||||
"Exported var ~s not in unit tagged ~s in compound-unit"
|
||||
sym tag)
|
||||
cmpd-unit 9)
|
||||
(values (mk-tvar-void) 0)]
|
||||
[ftype (values ftype time-export)]))]
|
||||
[(? Tvar? tvar-u)
|
||||
(lambda (sym)
|
||||
(let ([tvar (mk-Tvar 'get-export)])
|
||||
(new-con! tvar-u
|
||||
(create-con (get-unit-export-template sym)
|
||||
0 tvar #t))
|
||||
(values tvar time-export)))])])
|
||||
|
||||
(set! tag->access (cons (cons tag access-exports) tag->access))
|
||||
(set! saved-refs
|
||||
(filter
|
||||
(match-lambda
|
||||
[(tag2 sym tvar)
|
||||
(if (eq? tag tag2)
|
||||
(let-values ([(ftype _) (access-exports sym)])
|
||||
(new-edge! (FlowType->Tvar ftype) tvar)
|
||||
#f)
|
||||
#t)])
|
||||
saved-refs))))
|
||||
links times ftype*)]
|
||||
|
||||
[unit-imports (map cons imports (vector->list import-refs))]
|
||||
[unit-exports
|
||||
(map
|
||||
(match-lambda
|
||||
[(and export (tag id . e-id))
|
||||
(let*-vals
|
||||
([(ftype _)
|
||||
(tag.sym->ftype.time
|
||||
(zodiac:read-object tag)
|
||||
(zodiac:read-object id))]
|
||||
;;#[ftype (link-parsed-ftype! export ftype)]
|
||||
)
|
||||
(cons (zodiac:read-object e-id) ftype))])
|
||||
exports)]
|
||||
[result
|
||||
(match last-invoked-unit
|
||||
[#f (wrap-value (mk-tvar-void))]
|
||||
[($ atunit _ _ result) result]
|
||||
[(? Tvar? tvar-u)
|
||||
(let ([tvar (mk-Tvar 'cmpd-unit-result)])
|
||||
(new-con! tvar-u (create-con template-unit 0 tvar #t))
|
||||
tvar)])])
|
||||
|
||||
(make-atunit unit-imports
|
||||
unit-exports
|
||||
result
|
||||
cmpd-unit))]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
(define regenerating-ftype (void))
|
||||
|
||||
(define (apply-atlunit-reference atlunit partial-import-list)
|
||||
(match atlunit
|
||||
[($ atlunit-reference _
|
||||
(and N ($ zodiac:reference-unit-form _ _ _ _ file kind)))
|
||||
|
||||
(pretty-debug-unit
|
||||
`(apply-atlunit-reference
|
||||
,(zodiac:location-line (zodiac:zodiac-start N))
|
||||
pil ,(pretty-partial-import-list partial-import-list)))
|
||||
|
||||
(let*-vals
|
||||
( [_ (unless (zodiac:string? file)
|
||||
(mrspidey:error
|
||||
"reference-unit requires a string argument, given ~s"
|
||||
file))]
|
||||
[file (zodiac:read-object file)]
|
||||
[path+file
|
||||
(if (relative-path? file)
|
||||
(build-path (current-directory) file)
|
||||
file)]
|
||||
[file-directory (path-only path+file)]
|
||||
[(_ file _) (split-path path+file)]
|
||||
[za (regexp-replace ".ss$" file ".za")]
|
||||
[_ (when (eq? za file)
|
||||
(mrspidey:error
|
||||
(format "Invalid extension on ~s, requires .ss"
|
||||
file)))]
|
||||
[t-N (zodiac-time* N)]
|
||||
[za (case (st:save-za-in)
|
||||
[(source-directory)
|
||||
(build-path file-directory za)]
|
||||
[(tmp-directory)
|
||||
(build-path
|
||||
(wx:find-path 'temp-dir)
|
||||
(file-name-from-path za))])]
|
||||
[t-za (file-modify-seconds za)]
|
||||
|
||||
;; restrict imports to prims, closed schemas, and atstructs
|
||||
[partial-import-list-restricted
|
||||
(and partial-import-list
|
||||
(map
|
||||
(match-lambda
|
||||
[(ftype . itime)
|
||||
(cons
|
||||
(and (fo-FlowType? ftype)
|
||||
(match (fo-FlowType-def ftype)
|
||||
[(or ($ schema _ _ ()) (? atprim?) (? atstruct?))
|
||||
ftype]
|
||||
[_ #f]))
|
||||
itime)])
|
||||
partial-import-list))]
|
||||
[_ (pretty-debug-unit
|
||||
`(pil-restricted
|
||||
,(pretty-partial-import-list
|
||||
partial-import-list-restricted)))]
|
||||
|
||||
[port-for-included-unit
|
||||
(lambda ()
|
||||
(dynamic-let ([current-directory file-directory])
|
||||
(open-code-file file)))]
|
||||
|
||||
[traverse-included-unit
|
||||
;; (zodiac:parsed -> (union atunit atlunit))
|
||||
(lambda ()
|
||||
(let*-vals
|
||||
([_ (mrspidey:progress
|
||||
(format "Analyzing referenced unit ~a" file))]
|
||||
[_ (extend-file-time-cache! path+file t-N)]
|
||||
[exps (zodiac:read* (port-for-included-unit) path+file)]
|
||||
[(parsed-exps free-names)
|
||||
(dynamic-let
|
||||
([current-directory file-directory])
|
||||
(my-scheme-expand-program exps))]
|
||||
[_ (unless (= (length parsed-exps) 1)
|
||||
(mrspidey:error
|
||||
(format
|
||||
"reference-unit file ~s not a single exp"
|
||||
path+file)))]
|
||||
[parsed-exp (car parsed-exps)]
|
||||
[_ (pretty-debug
|
||||
`(traverse-included-unit
|
||||
,(zodiac:stripper parsed-exp)))]
|
||||
[gtr global-tref-env]
|
||||
[gtd global-tdef-env]
|
||||
[gtb global-tbang-env]
|
||||
[init-env (get-default-bindings free-names)]
|
||||
[(ftype env refs) (traverse-exp parsed-exp init-env)]
|
||||
[ftype (extract-1st-value ftype)]
|
||||
[ftype
|
||||
(case kind
|
||||
[(exp) ftype]
|
||||
[(imp) (create-fo-FlowType
|
||||
(apply-unit ftype
|
||||
partial-import-list-restricted))])]
|
||||
[savable-ftype (make-savable-ftype ftype)]
|
||||
[atunit (FlowType->Atype savable-ftype)]
|
||||
[_ (unless (atunit? atunit)
|
||||
(mrspidey:error
|
||||
(format
|
||||
"reference-unit file did not produce an annotated unit ~s"
|
||||
atunit)
|
||||
N))]
|
||||
[nu-tref (get-prefix global-tref-env gtr)]
|
||||
[nu-tdef (get-prefix global-tdef-env gtd)]
|
||||
[nu-tbang (get-prefix global-tbang-env gtb)]
|
||||
)
|
||||
(init-global-tenv! gtr gtd gtb)
|
||||
(pretty-debug-unit `(nu-tbang ,nu-tbang))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(binding . _)
|
||||
(mrspidey:warning
|
||||
(format
|
||||
"Unit refs imported var ~s of enclosing unit"
|
||||
(zodiac:binding-orig-name binding)))])
|
||||
refs)
|
||||
(values
|
||||
exps parsed-exp
|
||||
savable-ftype nu-tref nu-tdef nu-tbang)))]
|
||||
|
||||
[l-start list-ftype]
|
||||
[(ftype tref tdef tbang regenerate)
|
||||
(if (and (st:unit-read-za) t-za (< t-N t-za))
|
||||
|
||||
;; ------
|
||||
;; Just load from the file for delta-min
|
||||
(let*-vals
|
||||
( [s (format "Loading ~a" (file-name-from-path za))]
|
||||
[_ (mrspidey:progress s '...)]
|
||||
[(delta-min tref tdef tbang) (read-za za)]
|
||||
[_ (mrspidey:progress s 'done)])
|
||||
|
||||
(values delta-min tref tdef tbang traverse-included-unit))
|
||||
|
||||
;; ------
|
||||
;; Regenerate
|
||||
(let*-vals
|
||||
( [separate-S
|
||||
(and
|
||||
(st:unit-separate-S)
|
||||
(not (memq (st:unit-simplify) '(none nonempty))))]
|
||||
[s "Saving kernel state:"]
|
||||
[kernel-state
|
||||
(when separate-S
|
||||
(begin
|
||||
(mrspidey:progress s '...)
|
||||
(begin0
|
||||
(save-kernel-state)
|
||||
(init-kernel!)
|
||||
(mrspidey:progress s 'done))))]
|
||||
[l2 list-ftype]
|
||||
[(exps parsed-exp ftype nu-tref nu-tdef nu-tbang)
|
||||
;; we don't consider indirectly included files
|
||||
;; to be included
|
||||
(parameterize ([record-analyzed-file-hook
|
||||
(lambda (filename . _)
|
||||
(void))])
|
||||
(traverse-included-unit))]
|
||||
[l1 list-ftype]
|
||||
;;[_ (close-constraints (filter Tvar? (get-prefix l1 l2)))]
|
||||
[E (append
|
||||
(savable-ftype-external-vars ftype)
|
||||
(map cdr nu-tref)
|
||||
(map cdr nu-tdef)
|
||||
(map cdr nu-tbang))]
|
||||
[_ (pretty-debug-unit
|
||||
`(external vars
|
||||
,(map FlowType-name E)
|
||||
,(FlowType-name ftype)
|
||||
,(map FlowType-name
|
||||
(savable-ftype-external-vars ftype))
|
||||
,(map FlowType-name (map cdr nu-tref))
|
||||
,(map FlowType-name (map cdr nu-tdef))
|
||||
,(map FlowType-name (map cdr nu-tbang))))]
|
||||
|
||||
;;[_ (show-stat-small)]
|
||||
;; Restore state
|
||||
[s "Restoring kernel state"]
|
||||
[new-kernel-state
|
||||
(when separate-S
|
||||
(mrspidey:progress s '...)
|
||||
(begin0
|
||||
(save-kernel-state)
|
||||
(restore-kernel-state! kernel-state)
|
||||
(mrspidey:progress s 'done)))]
|
||||
|
||||
[s "Simplifying constraints"]
|
||||
[_ (mrspidey:progress s '...)]
|
||||
[l3 list-ftype]
|
||||
[(list-tvar tvar->nu)
|
||||
(minimize-constraints-&-compare
|
||||
(st:unit-simplify) E E l1 l2)]
|
||||
[_ (mrspidey:progress s 'done)]
|
||||
|
||||
;; debugging test
|
||||
[_ '(mrspidey:progress "debugging-test" '...)]
|
||||
[_ '(check-unreachable
|
||||
(get-prefix l1 l2)
|
||||
(get-prefix list-ftype l3))]
|
||||
[_ '(really-check-kernel-ok)]
|
||||
[_ '(mrspidey:progress "debugging-test" 'done)]
|
||||
|
||||
|
||||
[ftype2 (update-ftype ftype tvar->nu)]
|
||||
[upd-binding
|
||||
(match-lambda
|
||||
[(sym . tvar) (cons sym (tvar->nu tvar))])]
|
||||
[upd-tref (map upd-binding nu-tref)]
|
||||
[upd-tdef (map upd-binding nu-tdef)]
|
||||
[upd-tbang (map upd-binding nu-tbang)])
|
||||
|
||||
(when separate-S
|
||||
(when (st:zero-old-constraint-sets)
|
||||
(free-kernel-state! new-kernel-state))
|
||||
(when (st:zero-old-asts)
|
||||
(zodiac:zero! exps)
|
||||
(zodiac:zero! parsed-exp)))
|
||||
;;(show-stat-small)
|
||||
|
||||
;; Stuff to save in list-tvar, ftype2,
|
||||
;; upd-tref, upd-tdef, upd-tbang
|
||||
|
||||
(when (st:unit-write-za)
|
||||
(write-za
|
||||
za list-tvar ftype2
|
||||
upd-tref upd-tdef upd-tbang))
|
||||
|
||||
(values ftype2 upd-tref upd-tdef upd-tbang
|
||||
(if separate-S
|
||||
traverse-included-unit
|
||||
(lambda ()
|
||||
(values
|
||||
exps parsed-exp
|
||||
ftype nu-tref nu-tdef nu-tbang))))))]
|
||||
[_ (ok-ftype ftype)]
|
||||
[l-end list-ftype]
|
||||
[_
|
||||
;; Mark new ftypes as from .za file
|
||||
(for-each
|
||||
(lambda (ftype)
|
||||
(set-FlowType-type-annotation! ftype path+file))
|
||||
(get-prefix l-end l-start))]
|
||||
[atunit (apply-unit ftype partial-import-list)])
|
||||
|
||||
(pretty-debug-unit `(tbang ,tbang))
|
||||
|
||||
(begin
|
||||
(for-each (match-lambda [(s . t) (add-global-tref! s t)]) tref)
|
||||
(for-each (match-lambda [(s . t) (add-global-tdef! s t)]) tdef)
|
||||
(for-each (match-lambda [(s . t) (add-global-tbang! s t)]) tbang))
|
||||
|
||||
(ok-ftype ftype)
|
||||
|
||||
(record-analyzed-file
|
||||
path+file
|
||||
(lambda () (port-for-included-unit))
|
||||
(lambda ()
|
||||
(set! regenerating-ftype ftype)
|
||||
(ok-ftype ftype)
|
||||
|
||||
(let*-vals
|
||||
( [s (format "Regenerating included unit ~a"
|
||||
(file-name-from-path file))]
|
||||
[_ (mrspidey:progress s)]
|
||||
[(exps parsed-exp ftype2 tref2 tdef2 tbang2)
|
||||
((lambda () (regenerate)))])
|
||||
(ok-ftype ftype)
|
||||
(flow-d! ftype2 ftype)
|
||||
(flow-e! tdef2 tdef)
|
||||
(flow-e! tbang2 tbang)
|
||||
(flow-e! tref tref2)
|
||||
(list parsed-exp))))
|
||||
|
||||
(unless (atunit? atunit)
|
||||
(mrspidey:error
|
||||
(format
|
||||
"reference-unit file did not produce an annotated unit ~s"
|
||||
atunit)))
|
||||
|
||||
atunit)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (make-savable-ftype ftype)
|
||||
;; Converts an ftype to a "savable" ftype
|
||||
;; ie a tvar, a closed schema, a primitive, an atstruct
|
||||
;; or an atunit with savable exports and result
|
||||
;; atvalues could also be made savable, if there is any need
|
||||
(if (Tvar? ftype)
|
||||
ftype
|
||||
(match (fo-FlowType-def ftype)
|
||||
[($ schema tvar tvar* '()) ftype]
|
||||
[($ atunit imports exports result exp)
|
||||
(create-fo-FlowType
|
||||
(make-atunit imports
|
||||
(map (match-lambda
|
||||
[(sym . ftype)
|
||||
(cons sym (make-savable-ftype ftype))])
|
||||
exports)
|
||||
(make-savable-ftype result)
|
||||
exp))]
|
||||
[(and atlunit ($ atlunit))
|
||||
(make-savable-ftype (create-fo-FlowType (atlunit->atunit atlunit)))]
|
||||
[(and pi ($ atprim name type)) ftype]
|
||||
[(? atstruct?) ftype]
|
||||
[_ (FlowType->Tvar ftype)])))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define (savable-ftype-external-vars ftype)
|
||||
(if (Tvar? ftype)
|
||||
(list ftype)
|
||||
(match (fo-FlowType-def ftype)
|
||||
[($ schema tvar tvar* '()) (list tvar)]
|
||||
[($ atprim) '()]
|
||||
[($ atunit imports exports result exp)
|
||||
(apply append
|
||||
(append (map cdr imports)
|
||||
(map savable-ftype-external-vars (map cdr exports))
|
||||
(list (savable-ftype-external-vars result))))]
|
||||
[($ atstruct) '()]
|
||||
[x (mrspidey:internal-error 'savable-ftype-external-vars
|
||||
"Bad Atype ~s" x)])))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define (update-ftype ftype tvar->nu)
|
||||
;; Creates a copy of ftype with new type variables
|
||||
(if (Tvar? ftype)
|
||||
(tvar->nu ftype)
|
||||
(create-fo-FlowType
|
||||
(match (fo-FlowType-def ftype)
|
||||
[($ schema tvar tvar* '())
|
||||
(make-schema (tvar->nu tvar) (filter-map tvar->nu tvar*) '())]
|
||||
[(? atprim? atprim) atprim]
|
||||
[($ atunit imports exports result exp)
|
||||
(make-atunit
|
||||
(map (match-lambda
|
||||
[(sym . tvar*) (cons sym (map tvar->nu tvar*))])
|
||||
imports)
|
||||
(map (match-lambda
|
||||
[(sym . ftype)
|
||||
(cons sym (update-ftype ftype tvar->nu))])
|
||||
exports)
|
||||
(update-ftype result tvar->nu)
|
||||
exp)]
|
||||
[(? atstruct? atstruct) atstruct]))))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define (flow-d! ftype2 ftype)
|
||||
(let ([E2 (savable-ftype-external-vars ftype2)]
|
||||
[E (savable-ftype-external-vars ftype)])
|
||||
(pretty-debug-unit
|
||||
`(E ,(map FlowType-name E) E2 ,(map FlowType-name E2)))
|
||||
(unless (= (length E) (length E2))
|
||||
(mrspidey:error
|
||||
(format "The .za file is incompatible, and may be of date (~s ~s)"
|
||||
(length E) (length E2))))
|
||||
(for-each new-bidir-edge! E E2)))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define (ok-ftype ftype)
|
||||
(pretty-debug-unit `(ok-ftype ,(FlowType-name ftype)))
|
||||
(let ([E (savable-ftype-external-vars ftype)])
|
||||
(pretty-debug-unit `(E ,(map FlowType-name E)))
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(assert (list? (FlowType-arrowto tvar))
|
||||
'ok-ftype (FlowType-num ftype)))
|
||||
E)))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define (flow-e! env env2)
|
||||
(assert (= (length env) (length env2)) 'flow-e! env env2)
|
||||
(for-each new-bidir-edge! (map cdr env) (map cdr env2)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
;(trace apply-unit)
|
||||
;(trace apply-atlunit)
|
||||
;(trace apply-atlunit-unit)
|
||||
;(trace apply-atlunit-cmpd)
|
||||
;(trace apply-atlunit-reference)
|
||||
;(trace atlunit->atunit)
|
@ -0,0 +1,343 @@
|
||||
;; atype.ss - handles annotated types
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; FlowType - expr, edgeto, edgefrom, type-annotation
|
||||
;; Tvar - sub-structure of FlowType, is type variable
|
||||
;; fo-FlowType - FlowType with def field containing fo-Atype
|
||||
;; fo-Atype - atprim etc, see below
|
||||
;; Atype - Tvar or fo-Atype
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define-const-typed-structure (fo-FlowType struct:FlowType)
|
||||
( (: def fo-Atype)
|
||||
(: tvar Tvar)))
|
||||
|
||||
(define (FlowType->Atype ftype)
|
||||
(cond
|
||||
[(Tvar? ftype) ftype]
|
||||
[(fo-FlowType? ftype) (fo-FlowType-def ftype)]
|
||||
[else
|
||||
(mrspidey:internal-error 'FlowType->Atype "Bad ftype ~s" ftype)]))
|
||||
|
||||
(define (create-fo-FlowType fo-atype)
|
||||
(assert (fo-Atype? fo-atype) 'create-fo-FlowType fo-atype)
|
||||
(if (and
|
||||
(not (st:use-fo-ftype))
|
||||
(or
|
||||
(atconst? fo-atype)
|
||||
(and (atvalues? fo-atype)
|
||||
(andmap Tvar? (atvalues-values fo-atype)))))
|
||||
(Atype->Tvar fo-atype)
|
||||
(add-FlowType!
|
||||
(make-fo-FlowType num-ftype #f '() '() #f '() #f fo-atype #f))))
|
||||
|
||||
;; ----------
|
||||
|
||||
(define-type fo-Atype
|
||||
(union atconst schema atprim atthunk atstruct atvalues
|
||||
atunit atlunit))
|
||||
|
||||
(define (fo-Atype? x)
|
||||
(or (atconst? x)
|
||||
(schema? x)
|
||||
(atprim? x)
|
||||
(atthunk? x)
|
||||
(atstruct? x)
|
||||
(atvalues? x)
|
||||
(atunit? x)
|
||||
(atlunit? x)))
|
||||
|
||||
(define (poly-atype? x)
|
||||
(or (schema? x)
|
||||
(atthunk? x)))
|
||||
|
||||
;; --------------------
|
||||
;; atconst
|
||||
|
||||
(define-const-typed-structure
|
||||
atconst ((: c (union num bool))))
|
||||
|
||||
;; --------------------
|
||||
;; schema
|
||||
|
||||
(define-const-typed-structure
|
||||
schema ((: tvar Tvar)
|
||||
(: tvar* (listof Tvar))
|
||||
(: edges (listof (cons Tvar Tvar)))))
|
||||
|
||||
;; --------------------
|
||||
;; atprim
|
||||
|
||||
(define-const-typed-structure
|
||||
atprim ((: sym sym)
|
||||
(: type sexp)
|
||||
(: domain-filters (listof filter))
|
||||
predicate-fn
|
||||
attrs
|
||||
orig-type
|
||||
))
|
||||
|
||||
;; filter-domains is a list of filters for various args,
|
||||
;; if no error raised
|
||||
;; inj-predicate is a fn : list-tvar x list-tvar x tvar x bool -> Tvar
|
||||
;; used for (if (pred ... x ...) ...)
|
||||
|
||||
;; --------------------
|
||||
;; atthunk
|
||||
|
||||
(define-const-typed-structure
|
||||
atthunk ((: thunk (-> FlowType))))
|
||||
|
||||
;; --------------------
|
||||
;; atstruct
|
||||
|
||||
(define-const-typed-structure
|
||||
atstruct ((: struct:sym sym)
|
||||
(: super-constructors (listof sym))
|
||||
parent-gen-args
|
||||
parent-match-args
|
||||
parent-field-types
|
||||
parent-list-mutable))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; atvalues
|
||||
|
||||
(define-const-typed-structure
|
||||
atvalues ((: values (listof FlowType))))
|
||||
|
||||
(define (wrap-value x)
|
||||
(let* ([ftype (cond
|
||||
[(FlowType? x) x]
|
||||
[(fo-Atype? x) (create-fo-FlowType x)]
|
||||
[else (mrspidey:internal-error
|
||||
'wrap-value "Bad x ~s" x)])]
|
||||
[ftype (if (or (FlowType-expr ftype)
|
||||
(FlowType-values-ftype ftype))
|
||||
(copy-ftype ftype)
|
||||
ftype)]
|
||||
[r (create-fo-FlowType (make-atvalues (list ftype)))])
|
||||
(set-FlowType-values-ftype! ftype r)
|
||||
(pretty-debug-atype
|
||||
`(wrap-value ,(FlowType-name ftype) ,(FlowType-name r)))
|
||||
r))
|
||||
|
||||
(define (extract-1st-value ftype)
|
||||
(car (multiple-value-components ftype 1)))
|
||||
|
||||
(define (multiple-value-components ftype n)
|
||||
;; returns list of n value components
|
||||
(assert (integer? n) 'multiple-value-components)
|
||||
(cond
|
||||
[(zero? n) '()]
|
||||
[(fo-FlowType? ftype)
|
||||
(match (fo-FlowType-def ftype)
|
||||
[($ atvalues l)
|
||||
(recur loop ([n n][l l])
|
||||
(cond [(zero? n) '()]
|
||||
[(null? l) (cons (mk-tvar-empty) (loop (sub1 n) '()))]
|
||||
[else (let* ( [a (car l)]
|
||||
[b (copy-ftype a) ])
|
||||
;(if (FlowType-expr a) (copy-ftype a) a)
|
||||
(when need-explanation (add-FlowType-arrow! ftype b))
|
||||
(cons b (loop (sub1 n) (cdr l))))]))]
|
||||
[_ #f])]
|
||||
[else
|
||||
(let ( [tvar-mv (FlowType->Tvar ftype)]
|
||||
[tvar (mk-Tvar 'get-mvalues)])
|
||||
(new-con! tvar-mv (create-con template-mvalues 0 tvar #t))
|
||||
(recur loop ([tvar tvar][n n])
|
||||
(let ([a (mk-Tvar 'car-value)])
|
||||
(new-con! tvar (make-con-car a))
|
||||
(when need-explanation (add-FlowType-arrow! tvar-mv a))
|
||||
(cons a
|
||||
(if (= n 1)
|
||||
'()
|
||||
(let ([d (mk-Tvar 'cdr-value)])
|
||||
(new-con! tvar (make-con-cdr d))
|
||||
(loop d (sub1 n))))))))]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Annotated (lazy) unit types
|
||||
|
||||
(define-const-typed-structure
|
||||
atunit
|
||||
((: imports (listof (cons sym (listof Tvar))))
|
||||
(: exports (listof (cons sym FlowType)))
|
||||
(: result FlowType)
|
||||
(: expr zodiac:parsed)))
|
||||
|
||||
(define-const-typed-structure
|
||||
atlunit ((! ui (union false atunit))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
;; (: FlowType->Tvar (FlowType -> Tvar))
|
||||
|
||||
(define (FlowType->Tvar ftype)
|
||||
(let ([tvar
|
||||
(cond
|
||||
[(Tvar? ftype) ftype]
|
||||
[(fo-FlowType? ftype)
|
||||
(or (fo-FlowType-tvar ftype)
|
||||
(let ([tvar (Atype->Tvar (fo-FlowType-def ftype))])
|
||||
(when need-explanation (add-FlowType-arrow! ftype tvar))
|
||||
;(set-fo-FlowType-tvar! ftype tvar)
|
||||
tvar))]
|
||||
[else
|
||||
(mrspidey:internal-error 'FlowType->Tvar "Bad FlowType ~s" ftype)])])
|
||||
(pretty-debug-atype
|
||||
`(FlowType->Tvar ,(FlowType-name ftype) ,(Tvar-name tvar)))
|
||||
tvar
|
||||
))
|
||||
|
||||
(define Atype->Tvar
|
||||
(lambda (atype)
|
||||
(let ([tvar
|
||||
(match atype
|
||||
[(? Tvar? tvar) tvar]
|
||||
[($ atconst c)
|
||||
(let ([tvar (mk-Tvar 'atconst->tvar)])
|
||||
(new-AV! tvar (traverse-const-exact c))
|
||||
tvar)]
|
||||
[($ atstruct) (mk-tvar-void)]
|
||||
[($ atthunk thunk) (thunk)]
|
||||
[(and pi ($ atprim name type))
|
||||
(let ([tvar (mk-Tvar name)])
|
||||
(tschema->con type tvar name pi)
|
||||
tvar)]
|
||||
[($ schema tvar tvar* edges)
|
||||
(copy-constraint-set tvar tvar* edges)]
|
||||
[($ atunit imports exports result)
|
||||
(pretty-debug-atype
|
||||
`(Atype->Tvar (atunit ,imports ,exports ,result)))
|
||||
(let ([tvar-u (mk-Tvar 'inst-unit)])
|
||||
(for-each-with-n
|
||||
(lambda (import n)
|
||||
(map (lambda (tvar)
|
||||
(new-AV! tvar-u
|
||||
(create-AV (get-unit-import-template n)
|
||||
'() (vector) (vector tvar))))
|
||||
(cdr import)))
|
||||
imports)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(sym . ftype)
|
||||
(new-AV! tvar-u
|
||||
(create-AV (get-unit-export-template sym)
|
||||
'() (vector (FlowType->Tvar ftype)) (vector)))])
|
||||
exports)
|
||||
(new-AV! tvar-u
|
||||
(create-AV template-unit '()
|
||||
(vector (FlowType->Tvar result))
|
||||
(vector)))
|
||||
tvar-u)]
|
||||
[(and atlunit ($ atlunit))
|
||||
(Atype->Tvar (atlunit->atunit atlunit))]
|
||||
[($ atvalues ftype*)
|
||||
(let ([tvar-list
|
||||
(foldr
|
||||
(lambda (ftype tvar-rest)
|
||||
(let* ([tvar (mk-Tvar 'atvalues->tvar)])
|
||||
(new-AV! tvar
|
||||
(make-AV-cons (FlowType->Tvar ftype)
|
||||
tvar-rest))
|
||||
tvar))
|
||||
(mk-tvar-nil)
|
||||
ftype*)]
|
||||
[tvar (mk-Tvar 'atvalues->values)])
|
||||
(new-AV! tvar
|
||||
(create-AV template-mvalues '()
|
||||
(vector tvar-list) (vector)))
|
||||
tvar)]
|
||||
[x (mrspidey:internal-error 'Atype->Tvar "Bad Atype ~s" x)])])
|
||||
(pretty-debug-atype
|
||||
`(atype->tvar ,(Atype->pretty atype) ,(Tvar-name tvar)))
|
||||
tvar)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define FlowType->pretty
|
||||
(lambda (ftype)
|
||||
(cond
|
||||
[(Tvar? ftype) (Tvar-name ftype)]
|
||||
[(fo-FlowType? ftype)
|
||||
(Atype->pretty (fo-FlowType-def ftype))])))
|
||||
|
||||
(define Atype->pretty
|
||||
(match-lambda
|
||||
[($ atconst c) `(const ,c)]
|
||||
[($ atthunk thunk) 'thunk]
|
||||
[(and pi ($ atprim name _ _ _ attrs type)) `(prim ,name ,type)]
|
||||
[($ schema tvar tvar* edges)
|
||||
`(schema ,(Tvar-name tvar) ,(map Tvar-name tvar*))]
|
||||
[($ atunit imports exports result)
|
||||
`(atunit
|
||||
(imports ,@(map (match-lambda
|
||||
[(sym . tvar*)
|
||||
(cons sym (map Tvar-name tvar*))])
|
||||
imports))
|
||||
(exports ,@(map (match-lambda
|
||||
[(sym . ftype)
|
||||
(list sym (FlowType->pretty ftype))])
|
||||
exports))
|
||||
(result ,(FlowType->pretty result)))]
|
||||
[($ atlunit thunk) `(lazy-unit)]
|
||||
[($ atstruct A B C D E F) (list 'struct: A B C D E F)]
|
||||
[($ atvalues ftype*) `(values ,@(map FlowType->pretty ftype*))]
|
||||
[x
|
||||
(mrspidey:internal-error 'Atype->pretty "Bad fo-Atype ~s" x)]))
|
||||
|
||||
(define FlowType->SDL
|
||||
(lambda (ftype)
|
||||
(pretty-debug-sdl2
|
||||
`(FlowType->SDL ,(FlowType-name ftype) ,(FlowType->pretty ftype)))
|
||||
(cond
|
||||
[(Tvar? ftype) (Tvar->SDL ftype)]
|
||||
[(fo-FlowType? ftype)
|
||||
(match (fo-FlowType-def ftype)
|
||||
[($ atconst c) `(const ,c)]
|
||||
[($ atthunk thunk) `(thunk ,(Tvar->SDL (thunk)))]
|
||||
[($ atprim name _ _ _ _ type) `(prim ,type)]
|
||||
[($ schema tvar tvar* edges) `(schema ,(Tvar->SDL tvar))]
|
||||
[(and def ($ atunit imports exports result))
|
||||
`(unit ,(Tvar->SDL (FlowType->Tvar ftype)))]
|
||||
[(and ($ atlunit thunk) lui)
|
||||
`(lazy ,(FlowType->SDL (create-fo-FlowType (atlunit->atunit lui))))]
|
||||
[($ atstruct) 'struct:]
|
||||
[($ atvalues (ftype)) (FlowType->SDL ftype)]
|
||||
[($ atvalues ftype*) `(values ,@(map FlowType->SDL ftype*))]
|
||||
[x (mrspidey:internal-error 'FlowType->SDL "Bad fo-Atype ~s" x)])]
|
||||
[else (mrspidey:internal-error 'FlowType->SDL "Bad ftype ~s" ftype)])))
|
||||
|
||||
(define (copy-ftype ftype)
|
||||
(cond
|
||||
[(Tvar? ftype)
|
||||
(let ([tvar (mk-Tvar 'copy)])
|
||||
(new-edge! ftype tvar)
|
||||
tvar)]
|
||||
[(fo-FlowType? ftype)
|
||||
(let ([nu-ftype (create-fo-FlowType (fo-FlowType-def ftype))])
|
||||
(when need-explanation (add-FlowType-arrow! ftype nu-ftype))
|
||||
nu-ftype)]
|
||||
[else (mrspidey:internal-error 'link-parsed-ftype!
|
||||
"Bad ftype ~s, maybe old language" ftype)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
@ -0,0 +1,716 @@
|
||||
;; smart-checks.ss - identifies unsafe operations
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
|
||||
;;-------------------------------------------
|
||||
|
||||
(define-struct annotation (loc))
|
||||
(define-struct (check-annotation struct:annotation) (text num rest))
|
||||
(define-struct (uncheck-annotation struct:annotation) (text))
|
||||
(define-struct (type-annotation struct:annotation) (end-first finish FlowType))
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
(define check-annotations '()) ; store away checks for mred
|
||||
(define uncheck-annotations '()) ; store away unchecked prims
|
||||
|
||||
;;-------------------------------
|
||||
;; Counters
|
||||
|
||||
(define prim-count (void))
|
||||
(define lam-count (void))
|
||||
(define prim-apps (void))
|
||||
(define user-apps (void))
|
||||
(define ivar-count (void))
|
||||
(define type-assert-count (void))
|
||||
(define type-assert-failed-total (void))
|
||||
|
||||
(define prim-checks-def (void))
|
||||
(define lam-checks-def (void))
|
||||
(define ap-checks-def (void))
|
||||
(define ivar-checks-def (void))
|
||||
(define type-assert-failed-def (void))
|
||||
|
||||
(define total-checks (void))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define init-counts
|
||||
(lambda ()
|
||||
(set! prim-count (make-counter))
|
||||
(set! lam-count (make-counter))
|
||||
(set! prim-apps (make-counter))
|
||||
(set! user-apps (make-counter))
|
||||
(set! ivar-count (make-counter))
|
||||
(set! type-assert-count (make-counter))
|
||||
(set! type-assert-failed-total (make-counter))
|
||||
(set! total-checks (make-counter))
|
||||
(reset-counts)))
|
||||
|
||||
;; These three count per expression
|
||||
;; need to be reset with every definition traversed.
|
||||
|
||||
(define reset-counts
|
||||
(lambda ()
|
||||
(set! prim-checks-def (make-counter))
|
||||
(set! lam-checks-def (make-counter))
|
||||
(set! ap-checks-def (make-counter))
|
||||
(set! ivar-checks-def (make-counter))
|
||||
(set! type-assert-failed-def (make-counter))))
|
||||
|
||||
(define make-counter
|
||||
(lambda ()
|
||||
(let ([num 0])
|
||||
(lambda (n)
|
||||
(set! num (+ n num))
|
||||
num))))
|
||||
|
||||
;; ----------------------------------------
|
||||
|
||||
(define calc-checks
|
||||
(lambda (defs)
|
||||
(mrspidey:add-summary (format "CHECKS:"))
|
||||
(init-counts)
|
||||
(set! check-annotations '())
|
||||
(set! uncheck-annotations '())
|
||||
(for-each-with-n
|
||||
(lambda (def n)
|
||||
(mrspidey:zprogress "Checking" (zodiac:zodiac-start def))
|
||||
(match def
|
||||
[($ zodiac:define-values-form _ open _ _
|
||||
($ zodiac:list _ _ _ ($ zodiac:varref _ _ _ _ sym))
|
||||
_)
|
||||
(reset-counts)
|
||||
((zodiac:compat check-fn) def)
|
||||
;;(make-check-summary-line sym open)
|
||||
]
|
||||
[_
|
||||
(reset-counts)
|
||||
((zodiac:compat check-fn) def)
|
||||
'(make-check-summary-line
|
||||
(format "<expr> at line ~s"
|
||||
(zodiac:location-line
|
||||
(zodiac:zodiac-start def)))
|
||||
(zodiac:zodiac-start def))
|
||||
]))
|
||||
defs)
|
||||
(unless (null? defs)
|
||||
(mrspidey:zprogress "Checking" (zodiac:zodiac-finish (rac defs))))
|
||||
(make-check-summary "")
|
||||
(list check-annotations uncheck-annotations)))
|
||||
|
||||
;; ----------
|
||||
|
||||
(define check-fn
|
||||
(lambda (M unp)
|
||||
(pretty-debug-check `(check-fn ,(zodiac:stripper M)))
|
||||
(match M
|
||||
;; ivars
|
||||
[($ zodiac:app _ _ _ _
|
||||
($ zodiac:varref _ open _ _ (and ivar-sym (or '#%uq-ivar 'uq-ivar)))
|
||||
(obj-exp ivar-arg))
|
||||
(=> fail)
|
||||
(pretty-debug-check `(ivar ,ivar-sym))
|
||||
|
||||
;; Check the ivar is ok
|
||||
(let*-vals
|
||||
( [ftype (zodiac:parsed-ftype obj-exp)]
|
||||
[ftype (and ftype (extract-1st-value ftype))]
|
||||
[(tvars-ivarset-ok? set-tvar-ivarset-ok!)
|
||||
(alloc-Tvar-field)])
|
||||
(letrec
|
||||
([check-ivarset-ok?
|
||||
(lambda (tvar sym)
|
||||
(pretty-debug-check `(check-ivarset-ok? ,(Tvar-name tvar)))
|
||||
(set-tvar-ivarset-ok! tvar #t)
|
||||
(andmap
|
||||
(match-lambda
|
||||
[($ AV _ (? (lambda (t) (eq? t template-ivarset)))
|
||||
misc fields+)
|
||||
(assert (list? misc) 'ivar-check)
|
||||
(or
|
||||
(memq sym misc)
|
||||
(let ([parent (vector-ref fields+ 0)])
|
||||
(and (not (null? (get-Tvar-objs parent)))
|
||||
(check-ivarset-ok? parent sym)))
|
||||
(begin
|
||||
(pretty-debug-check
|
||||
`(ivar-failure ,sym ,misc ,(Tvar-name tvar)))
|
||||
#f)
|
||||
)]
|
||||
[_ #t])
|
||||
(get-Tvar-objs tvar)))])
|
||||
(if
|
||||
(match ivar-arg
|
||||
[($ zodiac:quote-form _ _ _ _ ($ zodiac:symbol _ _ _ sym))
|
||||
(and (Tvar? ftype) (check-ivarset-ok? ftype sym))]
|
||||
[_ #f])
|
||||
(begin
|
||||
(ivar-count 1)
|
||||
(add-uncheck! open (symbol->string ivar-sym)))
|
||||
(begin
|
||||
(ivar-count 1)
|
||||
(ivar-checks-def 1)
|
||||
(mrspidey:add-summary "ivar check" open 0)
|
||||
(add-check! open (symbol->string ivar-sym))))))
|
||||
|
||||
;; Check the primitive application - NOT!
|
||||
'(match ivar-arg
|
||||
[($ zodiac:quote-form _ _ _ _ ($ zodiac:symbol _ open _ sym))
|
||||
(let* ([ftype (zodiac:parsed-ftype M)])
|
||||
(when ftype
|
||||
(let ([ftype (extract-1st-value ftype)])
|
||||
(when (Tvar? ftype)
|
||||
(pretty-debug-check '(ivar-tvar))
|
||||
(match (get-Tvar-objs ftype)
|
||||
[(($ AV _ (? (lambda (t) (eq? t template-lam)))
|
||||
(and pi ($ atprim name type))))
|
||||
(pretty-debug-check '(ivar-lam-AV))
|
||||
(case (check-prim pi (zodiac:parsed-ftype M))
|
||||
[(#t)
|
||||
(prim-count 1)
|
||||
(add-uncheck! open (symbol->string sym))]
|
||||
[(#f)
|
||||
(prim-count 1)
|
||||
(mrspidey:add-summary "Method check" open 0)
|
||||
(prim-checks-def 1)
|
||||
(add-check! open (symbol->string sym) ftype)
|
||||
(pretty-debug `(CHECK-fo-prim ,(zodiac:stripper M)))
|
||||
(zodiac:set-parsed-check! ivar-arg #t)]
|
||||
[(not-function-type)
|
||||
(pretty-debug-check '(ivar-not-fn-type))]
|
||||
[(not-function-AV) (printf "ivar:not-function-AV~n")])]
|
||||
[_ (void)])))))]
|
||||
[_ (void)])
|
||||
(fail)]
|
||||
[($ zodiac:app _ _ _ _ fn args)
|
||||
(unless (atprim? (zodiac:parsed-atprim fn))
|
||||
(check-ap M))
|
||||
#f]
|
||||
[($ zodiac:case-lambda-form)
|
||||
(check-lambda M)
|
||||
#f]
|
||||
[($ zodiac:top-level-varref)
|
||||
(if (zodiac:parsed-atprim M)
|
||||
(check-ho-prim M)
|
||||
;; Otherwise should do bound? check, but don't
|
||||
(void))
|
||||
#f]
|
||||
[($ zodiac::-form)
|
||||
(check-type-assertion M)
|
||||
#f]
|
||||
[_ #f])))
|
||||
|
||||
;;-------------------------------------------
|
||||
|
||||
(define (parsed-Tvar x)
|
||||
;;(pretty-print `(parsed-Tvar ,(zodiac:stripper x)))
|
||||
(if (zodiac:parsed-ftype x)
|
||||
(let* ( [ftype (zodiac:parsed-ftype x)]
|
||||
[tvar (FlowType->Tvar ftype)])
|
||||
(pretty-debug-check
|
||||
`(parsed-Tvar ,(zodiac:stripper x) ,(FlowType-name ftype)
|
||||
,(Tvar-name tvar)))
|
||||
tvar)
|
||||
(mk-tvar-empty)))
|
||||
|
||||
(define check-ap
|
||||
(match-lambda
|
||||
[(and app ($ zodiac:app _ open _ _ fun args))
|
||||
(pretty-debug-check
|
||||
`(check-ap,(zodiac:stripper fun) ,(zodiac:parsed-ftype fun)))
|
||||
(let ([ftype-fn (zodiac:parsed-ftype fun)])
|
||||
(match (and (FlowType? ftype-fn) (FlowType->Atype ftype-fn))
|
||||
[($ atprim) (prim-apps 1)]
|
||||
[_ (user-apps 1)]))
|
||||
(let ([tvar (parsed-Tvar fun)])
|
||||
(unless
|
||||
(or
|
||||
(st:all-checks)
|
||||
(Tvar-in-type? tvar
|
||||
'(mvalues (cons (lambda _ _) (nil)))
|
||||
'()
|
||||
(lambda (a)
|
||||
(mrspidey:error 'check-ap
|
||||
"Reference to unbound type var ~s" a))))
|
||||
;; Check the application
|
||||
(ap-checks-def 1)
|
||||
(mrspidey:add-summary "Application check" open 0)
|
||||
(add-check! open "(" tvar)
|
||||
(pretty-debug `(CHECK-ap ,(zodiac:stripper app)))
|
||||
(zodiac:set-parsed-check! app #t)))]))
|
||||
|
||||
(define check-lambda
|
||||
(match-lambda
|
||||
[(and lam ($ zodiac:case-lambda-form _ open _ _ arglists bodies))
|
||||
(pretty-debug-check `(check-lam ,(zodiac:stripper lam)))
|
||||
;; put arity check on lambda
|
||||
(lam-count 1)
|
||||
(let* ( [tvar (parsed-Tvar lam)]
|
||||
[tvar (extract-1st-value tvar)])
|
||||
(match (get-Tvar-objs tvar)
|
||||
[(($ AV _ (? (lambda (t) (eq? t template-lam))) misc _ #(domain))
|
||||
. _)
|
||||
;; rest may be other AV-lam's for this case-lambda
|
||||
(let* ([arglist->ilist
|
||||
(match-lambda
|
||||
[($ zodiac:sym-arglist)
|
||||
'_]
|
||||
[($ zodiac:list-arglist vars)
|
||||
(map (lambda (_) '_) vars)]
|
||||
[($ zodiac:ilist-arglist vars)
|
||||
(recur loop ([vars vars])
|
||||
(match vars
|
||||
[(x) '_]
|
||||
[(a . b) `(_ . ,(loop b))]))])]
|
||||
[type
|
||||
(recur loop ([ilists (map arglist->ilist arglists)])
|
||||
(pretty-debug-check `(ilists ,ilists))
|
||||
(if (memq '_ ilists)
|
||||
'_
|
||||
(let ( [nils
|
||||
(filter null? ilists)]
|
||||
[non-nils
|
||||
(filter
|
||||
(lambda (x) (not (null? x)))
|
||||
ilists)])
|
||||
(cond
|
||||
[(null? non-nils)
|
||||
'nil]
|
||||
[(null? nils)
|
||||
`(cons _ ,(loop (map cdr non-nils)))]
|
||||
[else
|
||||
`(union
|
||||
nil
|
||||
(cons _ ,(loop (map cdr non-nils))))]))))])
|
||||
(pretty-debug-check `(type ,type))
|
||||
|
||||
(when
|
||||
(or
|
||||
(st:all-checks)
|
||||
(not (Tvar-in-type?
|
||||
domain (expand-input-type type) '()
|
||||
(lambda (a)
|
||||
(mrspidey:internal-error 'check-lambda
|
||||
"unbound tvar")))))
|
||||
;; Check it
|
||||
(lam-checks-def 1)
|
||||
(mrspidey:add-summary "Arity check" open 0)
|
||||
(add-check! open "lambda" domain)
|
||||
(zodiac:set-parsed-check! lam #t)))]
|
||||
[_;; never analyzed
|
||||
(void)]))]))
|
||||
|
||||
(define (check-ho-prim M)
|
||||
;; name : name-structure of prim
|
||||
;; open: source location for primitive
|
||||
;; returns correct primitive and either 1 or 0
|
||||
|
||||
(pretty-debug-check `(check-ho-prim ,(zodiac:stripper M)))
|
||||
|
||||
(match-let*
|
||||
( [($ zodiac:varref _ open _ _ sym) M]
|
||||
[(and atprim ($ atprim sym tschema _ _ _)) (zodiac:parsed-atprim M)])
|
||||
|
||||
(match (parsed-Tvar M)
|
||||
[(? Tvar? tvar)
|
||||
|
||||
(case (check-prim atprim tvar)
|
||||
[(#t)
|
||||
(prim-count 1)
|
||||
(add-uncheck! open (symbol->string sym))]
|
||||
[(#f)
|
||||
(prim-count 1)
|
||||
(mrspidey:add-summary (format "~s check" sym) open 0)
|
||||
(prim-checks-def 1)
|
||||
(add-check! open (symbol->string sym) tvar)
|
||||
(pretty-debug `(CHECK-fo-prim ,(zodiac:stripper M)))
|
||||
(zodiac:set-parsed-check! M #t)]
|
||||
[(not-function-type) (void)]
|
||||
[(not-function-AV)
|
||||
;(printf "check-hoo-prim: not-function-AV~n")
|
||||
(void)])])))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (check-prim atprim tvar)
|
||||
|
||||
(pretty-debug-check `(check-prim ,atprim ,(Tvar-name tvar) ))
|
||||
|
||||
(match (get-Tvar-objs (extract-1st-value tvar))
|
||||
[(($ AV _ template misc _ #(domain)))
|
||||
(check-prim-domain atprim domain)]
|
||||
[_ 'not-function-AV]))
|
||||
|
||||
(define (check-prim-domain atprim domain)
|
||||
(pretty-debug-check `(check-prim-domain ,atprim ,(Tvar-name domain) ))
|
||||
(match-let*
|
||||
( [($ atprim sym tschema _ _ _) atprim]
|
||||
[schemas (match tschema
|
||||
[('case-> . schemas) schemas]
|
||||
[schema (list schema)])])
|
||||
|
||||
(ormap
|
||||
(lambda (schema)
|
||||
|
||||
(let-values ([(forall type) (split-schema schema)])
|
||||
(match type
|
||||
[('lambda expected-domain _)
|
||||
(pretty-debug-check `(check-prim domain ,(Tvar-name domain)))
|
||||
(if (and
|
||||
(Tvar-in-type?
|
||||
domain expected-domain forall
|
||||
(lambda (a)
|
||||
(mrspidey:warning
|
||||
(format
|
||||
"Reference to unbound type var ~s in domain of ho primitive ~s"
|
||||
a sym))
|
||||
(lambda (AV) #f)))
|
||||
(not (st:all-checks)))
|
||||
#t
|
||||
(begin
|
||||
(pretty-debug-check
|
||||
`(check-prim-domain failed on ,sym
|
||||
,(FlowType-name domain)
|
||||
,expected-domain))
|
||||
#f))]
|
||||
[_
|
||||
;; Not a primitive function
|
||||
(pretty-debug-check `(Not a prim fn ,type))
|
||||
'not-function-type])))
|
||||
|
||||
schemas)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define check-type-assertion
|
||||
(match-lambda
|
||||
[(and M ($ zodiac::-form _ open _ _ exp type))
|
||||
(pretty-debug-check `(check-type-assertion ,(zodiac:stripper M)))
|
||||
(type-assert-count 1)
|
||||
(let* ([tvar (extract-1st-value (parsed-Tvar exp))]
|
||||
[in-type?
|
||||
(lambda (type)
|
||||
(Tvar-in-type?
|
||||
tvar (expand-input-type type) '()
|
||||
(lambda (a)
|
||||
(mrspidey:warning
|
||||
(format "Unbound type variable ~s" a)
|
||||
open 3)
|
||||
(lambda (AV) #f))))])
|
||||
(unless
|
||||
(match type
|
||||
[('exact type)
|
||||
;; Can't do exact yet - best is nonempty
|
||||
(and (not (null? (get-Tvar-objs tvar))) (in-type? type))]
|
||||
[_ (in-type? type)])
|
||||
;; Is bad
|
||||
(type-assert-failed-def 1)
|
||||
(type-assert-failed-total 1)
|
||||
(add-check! open "(")
|
||||
(mrspidey:warning
|
||||
(format "Type assertion ~s failed"
|
||||
(list ': '... ;;(zodiac:stripper exp)
|
||||
type))
|
||||
(zodiac:zodiac-start M)
|
||||
2)))]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define (Tvar-in-global-type? ftype type where)
|
||||
(Tvar-in-type?
|
||||
Tvar
|
||||
(expand-input-type type)
|
||||
(lambda (fv)
|
||||
(lookup-or-fail
|
||||
global-tdef-env fv
|
||||
(lambda ()
|
||||
(mrspidey:error
|
||||
(format
|
||||
"Reference to unbound type var ~s in ~a ~s"
|
||||
fv where type)))))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (add-check! open text . rest)
|
||||
(set! check-annotations
|
||||
(cons (make-check-annotation open text (total-checks 0) rest)
|
||||
check-annotations))
|
||||
(total-checks 1))
|
||||
|
||||
(define (add-uncheck! open text)
|
||||
(set! uncheck-annotations
|
||||
(cons (make-uncheck-annotation open text) uncheck-annotations)))
|
||||
|
||||
(define (show-checks)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ annotation ($ zodiac:location l c o f) text)
|
||||
(printf "File: ~s offset ~s text ~s~n"
|
||||
(file-name-from-path f) o text)])
|
||||
check-annotations))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (file-wrapper-start outport)
|
||||
;; Writes prefix to file
|
||||
;(fprintf outport ";; Generated by SBA Soft Scheme ~a~%" st:version)
|
||||
(fprintf outport ";; Control string ")
|
||||
(for-each (lambda (x) (fprintf outport" '~a" x)) (mrspidey:control-fn))
|
||||
(fprintf outport "~n~n"))
|
||||
|
||||
(define (file-wrapper-end outport)
|
||||
(newline outport)
|
||||
'(for-each (lambda (s) (fprintf outport ";; ~a" s))
|
||||
(reverse summary))
|
||||
(void)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define (write-soft-file outfile)
|
||||
;; Writes soft typed file - macro expanded with checks - executable
|
||||
(when (file-exists? outfile) (delete-file outfile))
|
||||
(let ([outport (open-output-file outfile)])
|
||||
|
||||
(file-wrapper-start outport)
|
||||
(for-each
|
||||
(lambda (def)
|
||||
(pretty-print
|
||||
((zodiac:unparse-dynamic-letd
|
||||
(lambda (exp cl-fn)
|
||||
(if (zodiac:parsed-check exp)
|
||||
(match exp
|
||||
[($ zodiac:app _ open close back fun args)
|
||||
`(CHECK-ap ,(cl-fn fun) ,@(map cl-fn args))]
|
||||
[($ zodiac:lambda-form _ open close back
|
||||
args body level)
|
||||
(let* ([args (map-ilist cl-fn args)])
|
||||
`(CHECK-lambda ,args ,(cl-fn body)))]
|
||||
[($ zodiac:lexical-varref
|
||||
_ open close _
|
||||
($ zodiac:bound _ _ _ _ sym)
|
||||
Tvar-box)
|
||||
(symbol-append 'CHECK- sym)])
|
||||
#f)))
|
||||
def)
|
||||
outport)
|
||||
(newline outport))
|
||||
defs-bind)
|
||||
(file-wrapper-end outport)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define (write-annotated-file outfile source-thunk)
|
||||
;; As source file, but with checks
|
||||
(when (file-exists? outfile) (delete-file outfile))
|
||||
(let* ([inport (source-thunk)]
|
||||
[outport (open-output-file outfile)]
|
||||
[checks (map
|
||||
(match-lambda
|
||||
[($ annotation loc)
|
||||
(cons (zodiac:location-offset loc) rest)])
|
||||
check-annotations)]
|
||||
[checks (sort
|
||||
(match-lambda*
|
||||
[((ofs1 . _) (ofs2 . _)) (< ofs1 ofs2)])
|
||||
checks)])
|
||||
|
||||
(file-wrapper-start outport)
|
||||
(recur loop ([pos 0][checks checks])
|
||||
(let ([c (read-char inport)])
|
||||
(unless (eof-object? c)
|
||||
(match checks
|
||||
[(( (? (lambda (p) (= p pos)))
|
||||
num name . _)
|
||||
. _)
|
||||
(let ([to-drop
|
||||
(match name
|
||||
["("
|
||||
;; Is an application check
|
||||
(assert (char=? c #\())
|
||||
(display (format "(CHECK-ap ~s " num)
|
||||
outport)
|
||||
""]
|
||||
["lambda"
|
||||
;; Is a lambda check
|
||||
(assert (char=? c #\())
|
||||
(display (format "(CHECK-lambda ~s " num)
|
||||
outport)
|
||||
"lambda"]
|
||||
[prim
|
||||
;; Is a primitive check
|
||||
(assert (char=? c (string-ref prim 0)))
|
||||
(display (format "(CHECK-~a ~s)" name num)
|
||||
outport)
|
||||
(substring prim 1 (string-length prim))])])
|
||||
(recur loop2 ([pos (add1 pos)]
|
||||
[s (string->list to-drop)])
|
||||
(cond
|
||||
[(null? s) (loop pos (cdr checks))]
|
||||
[(char=? (read-char inport) (car s))
|
||||
(loop2 (add1 pos) (cdr s))]
|
||||
[else
|
||||
(error 'write-annotated-file
|
||||
"File not as expected")])))]
|
||||
[_
|
||||
(write-char c outport)
|
||||
(loop (add1 pos) checks)]))))
|
||||
|
||||
(close-input-port inport)
|
||||
(file-wrapper-end outport)
|
||||
(close-output-port outport)))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define make-check-summary-line
|
||||
(lambda (name src)
|
||||
(let ([total (+ (prim-checks-def 0) (lam-checks-def 0)
|
||||
(ap-checks-def 0) (type-assert-failed-def 0))])
|
||||
(unless (= 0 total)
|
||||
(let* ((s (format "~a~a " (padr name 19) (padl total 3)))
|
||||
(s (if (< 0 (prim-checks-def 0))
|
||||
(format "~a (~a prim)" s (prim-checks-def 0))
|
||||
s))
|
||||
(s (if (< 0 (lam-checks-def 0))
|
||||
(format "~a (~a lambda)" s (lam-checks-def 0))
|
||||
s))
|
||||
(s (if (< 0 (ap-checks-def 0))
|
||||
(format "~a (~a ap)" s (ap-checks-def 0))
|
||||
s))
|
||||
(s (if (< 0 (type-assert-failed-def 0))
|
||||
(format "~a (~a type assertions)"
|
||||
s (type-assert-failed-def 0))
|
||||
s)))
|
||||
(mrspidey:add-summary s src 0))))))
|
||||
|
||||
;; --------------------
|
||||
|
||||
(define make-check-summary
|
||||
(lambda (hdr)
|
||||
(let* ([f (lambda (s) (mrspidey:add-summary s))]
|
||||
[total-possible
|
||||
(+ (user-apps 0) (prim-count 0) (lam-count 0)
|
||||
(type-assert-count 0))]
|
||||
[percentage
|
||||
(if (= 0 total-possible)
|
||||
0
|
||||
(string->number
|
||||
(chop-number
|
||||
(exact->inexact (* (/ (total-checks 0)
|
||||
total-possible) 100))
|
||||
4)))])
|
||||
|
||||
(f (format "~a~a~a~a"
|
||||
hdr
|
||||
(padr "TOTAL CHECKS:" 19)
|
||||
(padl (total-checks 0) 3)
|
||||
(format " (of ~s possible checks is ~s%)"
|
||||
total-possible percentage)))
|
||||
|
||||
(unless (zero? (type-assert-failed-total 0))
|
||||
(f (format "~a~a~a~a"
|
||||
hdr
|
||||
(padr "FAILED ASSERTIONS:" 19)
|
||||
(padl (type-assert-failed-total 0) 3)
|
||||
(format " (of ~s total type assertions)"
|
||||
(type-assert-count 0)))))
|
||||
|
||||
)))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
|
||||
(define (calc-type-annotations defs)
|
||||
(let* ( [type-annotations '()]
|
||||
[locs-done-table-size 2048]
|
||||
[locs-done-mask 2047]
|
||||
[loc->ndx (lambda (loc)
|
||||
(bitwise-and (zodiac:location-offset loc)
|
||||
locs-done-mask))]
|
||||
[locs-done-table (make-vector locs-done-table-size '())]
|
||||
[fn
|
||||
(lambda (exp cl-fn)
|
||||
(match exp
|
||||
[($ zodiac:parsed origin start finish)
|
||||
(let* ([ftype (zodiac:parsed-ftype exp)]
|
||||
[end-first (zodiac:determine-end-first-token exp)])
|
||||
|
||||
(pretty-debug
|
||||
`(ftype ,(and (FlowType? ftype) (FlowType-name ftype))
|
||||
start ,(zodiac:location-offset start)))
|
||||
|
||||
(when
|
||||
(and
|
||||
(FlowType? ftype)
|
||||
;;(memq (zodiac:origin-who origin) '(source reader))
|
||||
)
|
||||
|
||||
;; Don't add type-annotation if something else has this
|
||||
;; start location
|
||||
(let ([ndx (loc->ndx start)])
|
||||
(when (not (find
|
||||
(lambda (l)
|
||||
(= (zodiac:location-offset l)
|
||||
(zodiac:location-offset start)))
|
||||
(vector-ref locs-done-table ndx)))
|
||||
;; Check FlowType points to exp
|
||||
(assert (or (eq? (FlowType-expr ftype) exp)
|
||||
(eq? (FlowType-expr ftype) #t))
|
||||
'calc-type-annotation ftype
|
||||
(FlowType-expr ftype) exp)
|
||||
'(set-FlowType-expr! ftype exp)
|
||||
(set! type-annotations
|
||||
(cons
|
||||
(make-type-annotation
|
||||
start end-first finish ftype)
|
||||
type-annotations))
|
||||
(vector-set!
|
||||
locs-done-table ndx
|
||||
(cons start (vector-ref locs-done-table ndx)))))))
|
||||
#f]
|
||||
[_ #f]))])
|
||||
|
||||
(map-with-n
|
||||
(lambda (exp n)
|
||||
(begin
|
||||
(mrspidey:zprogress "Typing" (zodiac:zodiac-start exp))
|
||||
((zodiac:compat fn) exp)))
|
||||
defs)
|
||||
(unless (null? defs)
|
||||
(mrspidey:zprogress "Typing" (zodiac:zodiac-finish (rac defs))))
|
||||
|
||||
type-annotations))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,312 @@
|
||||
;; config.ss
|
||||
;; Lots of parameters for analysis
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define st:restricted
|
||||
(not (string? (current-load-relative-directory))))
|
||||
(define st:name "MrSpidey")
|
||||
(define st:version (lambda () "49s1"))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Front end parameters
|
||||
|
||||
(define st:fake-reader (make-parameter-boolean #f))
|
||||
(define st:system-expand (make-parameter-boolean #f))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Analysis parameters
|
||||
|
||||
(define st:constants (make-parameter-boolean #f))
|
||||
(define st:const-merge-size (make-parameter-integer 7))
|
||||
|
||||
(define st:if-split (make-parameter-boolean #t))
|
||||
; If #t, then knowledgeable about if's
|
||||
|
||||
(define st:flow-sensitive (make-parameter-boolean #t))
|
||||
; If #t, then in (begin (car x) (cdr x)), cdr is never checked
|
||||
|
||||
(define st:fo-units (make-parameter-boolean #t))
|
||||
;; If #t, then first-order units treated specially
|
||||
|
||||
(define st:lazy-fo-units (make-parameter-boolean #t))
|
||||
;; If #t, then first-order units treated specially
|
||||
|
||||
(define st:cache-units (make-parameter-boolean #t))
|
||||
;; If #t, then first-order units treated specially
|
||||
|
||||
(define st:whole-program (make-parameter-boolean #t))
|
||||
|
||||
(define st:special-fo-prims (make-parameter-boolean #t))
|
||||
(define st:see-void (make-parameter-boolean #t))
|
||||
(define st:cons-mutable (make-parameter-boolean #t))
|
||||
(define st:use-fo-ftype (make-parameter-boolean #t))
|
||||
|
||||
(define need-label-types #t)
|
||||
(define need-explanation #t)
|
||||
|
||||
(define st:zero-old-constraint-sets (make-parameter-boolean #t))
|
||||
(define st:zero-old-asts (make-parameter-boolean #t))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Simplification parameters
|
||||
|
||||
(define constraint-simplification-list
|
||||
(if st:restricted
|
||||
'(
|
||||
(none "No simplification")
|
||||
(nonempty "Remove empty constraints")
|
||||
(live "Remove empty and unreachable constraints")
|
||||
(live-few-e "As above, and also remove epsilon constraints")
|
||||
((live-few-e dfa-min-glb dfa-min-lub)
|
||||
"Live, few epsilon, DFA min")
|
||||
)
|
||||
'(
|
||||
(none "No simplification")
|
||||
(nonempty "Remove empty constraints")
|
||||
(nonempty-copy "Copy nonempty")
|
||||
(live "Remove empty and unreachable constraints")
|
||||
(live-few-e-L "Live, few lower epsilon")
|
||||
(live-few-e-U "Live, few upper epsilon")
|
||||
(live-few-e "Live, few epsilon")
|
||||
((live-few-e dfa-min-lub)
|
||||
"Live, few epsilon, DFA min LUB")
|
||||
((live-few-e dfa-min-glb)
|
||||
"Live, few epsilon, DFA min GLB")
|
||||
((live-few-e dfa-min-lub dfa-min-glb)
|
||||
"Live, few epsilon, DFA min")
|
||||
)))
|
||||
|
||||
(define make-constraint-simplification-para
|
||||
(case-lambda
|
||||
[() (make-constraint-simplification-para 'live-few-e)]
|
||||
[(default)
|
||||
(make-parameter-list
|
||||
default
|
||||
constraint-simplification-list
|
||||
(lambda (_) (void))
|
||||
;; also-ok?
|
||||
(lambda (x)
|
||||
(and (list? x)
|
||||
(andmap
|
||||
(lambda (y) (member y (map car constraint-simplification-list)))
|
||||
x))))]))
|
||||
|
||||
(define st:minimize-respect-assignable-part-of-fields
|
||||
(make-parameter-boolean #t))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Polymorphism parameters
|
||||
|
||||
(define st:constraint-simplification-poly (make-constraint-simplification-para))
|
||||
|
||||
(define st:polymorphism
|
||||
(make-parameter-list 'compress
|
||||
`((none "No polymorphism")
|
||||
(compress "Simplify constraints")
|
||||
;;(copy-con "")
|
||||
(reanalyze "Reanalyze")
|
||||
)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Unit parameters
|
||||
|
||||
(define st:unit-read-za (make-parameter-boolean #t))
|
||||
(define st:unit-write-za (make-parameter-boolean #t))
|
||||
(define st:unit-simplify
|
||||
(make-constraint-simplification-para 'live-few-e))
|
||||
(define st:unit-separate-S (make-parameter-boolean #t))
|
||||
(define st:save-za-in
|
||||
(make-parameter-list
|
||||
'source-directory
|
||||
`( (source-directory "Source file directory" "")
|
||||
(tmp-directory
|
||||
,(string-append
|
||||
(if (defined? 'wx:find-path)
|
||||
(wx:find-path 'temp-dir) " directory"))
|
||||
""))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Type Viewing parameters
|
||||
|
||||
;; --- copying
|
||||
|
||||
(define st:sdl-fo
|
||||
(make-parameter-list
|
||||
'basic-types
|
||||
'( (basic-types "Basic Types" "ie (1 -> 1)")
|
||||
(type-schemas "Type Schemas" "ie (X1 -> X1)"))))
|
||||
|
||||
(define st:sdl-fo-ivars (make-parameter-boolean #t))
|
||||
(define st:sdl-fo-struct-fields (make-parameter-boolean #t))
|
||||
(define st:sdl-fo-depth-limit? (make-parameter-boolean #t))
|
||||
(define st:sdl-fo-depth-limit (make-parameter-integer 50))
|
||||
(define st:sdl-fo-size-limit? (make-parameter-boolean #t))
|
||||
(define st:sdl-fo-size-limit (make-parameter-integer 50))
|
||||
|
||||
;; --- simplification
|
||||
|
||||
(define st:sdl-constraint-simplification
|
||||
(make-constraint-simplification-para 'live-few-e))
|
||||
|
||||
(define st:show-assignable-part-of-fields
|
||||
(make-parameter-boolean #f))
|
||||
|
||||
;; --- to SDL
|
||||
|
||||
(define st:listify-etc (make-parameter-boolean #t))
|
||||
|
||||
(define st:sdl-constructor/selector
|
||||
(make-parameter-list
|
||||
'constructor
|
||||
'((constructor "Show types as constructors" "")
|
||||
(selector "Show types as selectors" ""))))
|
||||
|
||||
(define st:naming-strategy
|
||||
(make-parameter-list
|
||||
'multiple
|
||||
(if st:restricted
|
||||
'((recursive "Recursive" "Name types on cycles")
|
||||
(multiple "Multiple" "Name types referenced more than once")
|
||||
(nontrivial "Non-Trivial" "Name non-trivial types")
|
||||
(all "All" "Name all types"))
|
||||
'((recursive "Recursive" "Name types on cycles")
|
||||
(multiple "Multiple" "Name types referenced more than once")
|
||||
(nontrivial "Non-Trivial" "Name non-trivial types")
|
||||
(all "All" "Name all types")))))
|
||||
|
||||
(define st:primitive-types
|
||||
(make-parameter-list
|
||||
'inferred
|
||||
'((prim "(prim ...)" "ie (prim car)")
|
||||
(given "Given types" "ie ((cons a b) -> a)")
|
||||
(inferred "Inferred types" "ie ((cons 'a-symbol 4) -> 'a-symbol)"))))
|
||||
|
||||
;; --- simplifying SDL
|
||||
|
||||
(define st:expand-output-type (make-parameter-boolean #t))
|
||||
(define st:sdl-tidy (make-parameter-boolean #t))
|
||||
|
||||
;; ---
|
||||
|
||||
(define st:pretty-type-width (make-parameter-integer 60))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define st:check-kernel (make-parameter-boolean #f))
|
||||
(define st:compare-min-algs (make-parameter-boolean #f))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Checking parameters
|
||||
|
||||
(define st:all-checks (make-parameter-boolean #f))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; control - interface to all parameters
|
||||
|
||||
(define mrspidey:control-fn
|
||||
(let ([paras
|
||||
(begin-elaboration-time
|
||||
(cons 'list
|
||||
(map
|
||||
(lambda (x) (list 'cons (list 'quote x) x))
|
||||
'(;; --- Analysis time
|
||||
st:constants
|
||||
st:const-merge-size
|
||||
st:fo-units
|
||||
st:if-split
|
||||
st:flow-sensitive
|
||||
st:special-fo-prims
|
||||
st:system-expand
|
||||
st:see-void
|
||||
st:unit-read-za
|
||||
st:unit-write-za
|
||||
st:save-za-in
|
||||
;; --- Polymorphism
|
||||
st:polymorphism
|
||||
st:constraint-simplification-poly
|
||||
;;st:library-prims
|
||||
;;st:topo-sort
|
||||
;; --- Seperate analysis
|
||||
st:unit-simplify
|
||||
;; --- Type viewing
|
||||
st:sdl-fo
|
||||
st:sdl-fo-ivars
|
||||
st:sdl-fo-struct-fields
|
||||
st:sdl-fo-depth-limit?
|
||||
st:sdl-fo-depth-limit
|
||||
st:sdl-fo-size-limit?
|
||||
st:sdl-fo-size-limit
|
||||
st:sdl-constraint-simplification
|
||||
st:show-assignable-part-of-fields
|
||||
st:listify-etc
|
||||
st:sdl-constructor/selector
|
||||
st:naming-strategy
|
||||
st:primitive-types
|
||||
st:expand-output-type
|
||||
st:sdl-tidy
|
||||
st:pretty-type-width
|
||||
|
||||
;; --- checking parameters
|
||||
st:all-checks
|
||||
))))])
|
||||
(match-lambda*
|
||||
[()
|
||||
;; Return list of all settings
|
||||
(map
|
||||
(match-lambda [(sym . para) (list sym (para))])
|
||||
paras)
|
||||
]
|
||||
[(para-name)
|
||||
;; Return one setting
|
||||
(match (assq para-name paras)
|
||||
[(_ . para) (para)]
|
||||
[#f (error 'mrspidey:control "Unknown parameter ~s" para-name)])]
|
||||
[(para-name nu-val)
|
||||
;; Return one setting
|
||||
(match (assq para-name paras)
|
||||
[(_ . para)
|
||||
(if (memq nu-val (map car (para '?)))
|
||||
(para nu-val)
|
||||
(error 'mrspidey:control "Value ~s invalid for parameter ~s"
|
||||
nu-val para-name))]
|
||||
[#f
|
||||
(error 'mrspidey:control "Unknown parameter ~s" para-name)])]
|
||||
[_ (error 'mrspidey:control "Bad # arguments")])))
|
||||
|
||||
;======================================================================
|
||||
|
||||
(when st:restricted
|
||||
;; . special configuration, if necy
|
||||
(void)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,155 @@
|
||||
;; contained.ss
|
||||
;;
|
||||
;; Check if one Tvar is contained in another
|
||||
;; Doesn't work for contravariant fields
|
||||
;; Not currently used
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; NOTE: Tvar2 must be tidy!!!
|
||||
|
||||
(define stack '())
|
||||
(define fail-stack '())
|
||||
|
||||
(define Tvar-containment?
|
||||
(lambda (tvar1 tvar2)
|
||||
(let*-vals
|
||||
( [calc-reached
|
||||
(lambda (tvar)
|
||||
(let*-vals
|
||||
([(reached? set-reached! get-reached)
|
||||
(field->set alloc-Tvar-field)])
|
||||
(recur traverse ([tvar tvar])
|
||||
(unless (reached? tvar)
|
||||
(set-reached! tvar)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _ ($ template _ _ _ ref) _ fields+ field-)
|
||||
(vector-for-each traverse fields+)])
|
||||
(get-Tvar-objs tvar))))
|
||||
(get-reached)))]
|
||||
[list-reached-1 (calc-reached tvar1)]
|
||||
[list-reached-2 (calc-reached tvar2)]
|
||||
[num-reached-1 (length list-reached-1)]
|
||||
[(get-num set-num!) (alloc-Tvar-field)]
|
||||
[(get-reached-vec set-reached-vec!) (alloc-Tvar-field)]
|
||||
)
|
||||
|
||||
(for-each-with-n (lambda (tvar n) (set-num! tvar n))
|
||||
list-reached-1)
|
||||
|
||||
(for-each
|
||||
(lambda (tvar) (set-reached-vec! tvar (make-vector num-reached-1 #f)))
|
||||
list-reached-2)
|
||||
|
||||
;; Tidyness check
|
||||
'(for-each
|
||||
(lambda (tvar)
|
||||
(let* ([objs (get-Tvar-objs tvar)]
|
||||
[templates (map AV-template objs)]
|
||||
[types (map template-type templates)]
|
||||
[types2 (list->set types)])
|
||||
(unless (= (length types) (length types2))
|
||||
(mrspidey:error
|
||||
(format "Upper bound of containment is not tidy, types are ~s"
|
||||
types)))))
|
||||
list-reached-2)
|
||||
|
||||
(begin0
|
||||
(let/cc
|
||||
fail
|
||||
|
||||
(recur ensure-contained ([tvar1 tvar1][tvar2 tvar2])
|
||||
(fluid-let ([stack (cons (cons tvar1 tvar2) stack)])
|
||||
(let ([n (get-num tvar1)]
|
||||
[reached (get-reached-vec tvar2)])
|
||||
(unless (vector-ref reached n)
|
||||
;; Need to search - record true to detect loops
|
||||
(vector-set! reached n #t)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _ (and template ($ template _ _ ref)) _ fields+)
|
||||
(or
|
||||
|
||||
;; More than one matching => not tidy => say contained.
|
||||
(> (count (match-lambda
|
||||
[($ AV _ template2)
|
||||
(eq? (template-type template)
|
||||
(template-type template2))])
|
||||
(get-Tvar-objs tvar2))
|
||||
1)
|
||||
|
||||
(ormap
|
||||
(match-lambda
|
||||
[($ AV _ template2 _ fields2+)
|
||||
(and ;(eq? template template2)
|
||||
(or
|
||||
(eq?
|
||||
(template-type template)
|
||||
(template-type template2))
|
||||
(memq
|
||||
template2
|
||||
(template-super-templates template)))
|
||||
(begin
|
||||
(for i 0
|
||||
(min
|
||||
(vector-length fields+)
|
||||
(vector-length fields2+))
|
||||
(ensure-contained
|
||||
(vector-ref fields+ i)
|
||||
(vector-ref fields2+ i)))
|
||||
#t))])
|
||||
(get-Tvar-objs tvar2))
|
||||
|
||||
;; No match
|
||||
(begin
|
||||
'(printf
|
||||
"~s ~s not in ~s ~s~n"
|
||||
(map (lambda (AV) (template-type (AV-template AV)))
|
||||
(get-Tvar-objs tvar1))
|
||||
(Tvar-name tvar1)
|
||||
(map (lambda (AV) (template-type (AV-template AV)))
|
||||
(get-Tvar-objs tvar2))
|
||||
(Tvar-name tvar2))
|
||||
(set! fail-stack stack)
|
||||
(fail #f)))])
|
||||
(get-Tvar-objs tvar1))))))
|
||||
|
||||
;; Did not fail => succeed
|
||||
#t)
|
||||
|
||||
))))
|
||||
|
||||
'(define (show-fail-stack-sdl)
|
||||
(map
|
||||
(match-lambda
|
||||
[(a . d)
|
||||
(list (Tvar->SDL a)
|
||||
(Tvar->SDL d))])
|
||||
fail-stack))
|
||||
|
||||
'(define (show-fail-stack)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(a . d)
|
||||
(printf "============~n")
|
||||
(show-Tvar a)
|
||||
(show-Tvar d)])
|
||||
fail-stack))
|
||||
|
||||
|
@ -0,0 +1,129 @@
|
||||
;; contained.ss
|
||||
;;
|
||||
;; Check if one Tvar is contained in another
|
||||
;; Doesn't work for contravariant fields
|
||||
;; ----------------------------------------------------------------------
|
||||
;; NOTE: Tvar2 must be tidy!!!
|
||||
|
||||
(define stack '())
|
||||
(define fail-stack '())
|
||||
|
||||
(define Tvar-containment?
|
||||
(lambda (tvar1 tvar2)
|
||||
(let*-vals
|
||||
( [calc-reached
|
||||
(lambda (tvar)
|
||||
(let*-vals
|
||||
([(reached? set-reached! get-reached)
|
||||
(field->set alloc-Tvar-field)])
|
||||
(recur traverse ([tvar tvar])
|
||||
(unless (reached? tvar)
|
||||
(set-reached! tvar)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _ ($ template _ _ ref) _ fields)
|
||||
(for i 0 (vector-length ref)
|
||||
(traverse
|
||||
(vector-ref fields (vector-ref ref i))))])
|
||||
(get-Tvar-objs tvar))))
|
||||
(get-reached)))]
|
||||
[list-reached-1 (calc-reached tvar1)]
|
||||
[list-reached-2 (calc-reached tvar2)]
|
||||
[num-reached-1 (length list-reached-1)]
|
||||
[(get-num set-num!) (alloc-Tvar-field)]
|
||||
[(get-reached-vec set-reached-vec!) (alloc-Tvar-field)]
|
||||
)
|
||||
|
||||
(for-each-with-n (lambda (tvar n) (set-num! tvar n))
|
||||
list-reached-1)
|
||||
|
||||
(for-each
|
||||
(lambda (tvar) (set-reached-vec! tvar (make-vector num-reached-1 #f)))
|
||||
list-reached-2)
|
||||
|
||||
;; Tidyness check
|
||||
'(for-each
|
||||
(lambda (tvar)
|
||||
(let* ([objs (get-Tvar-objs tvar)]
|
||||
[templates (map AV-template objs)]
|
||||
[types (map template-type templates)]
|
||||
[types2 (list->set types)])
|
||||
(unless (= (length types) (length types2))
|
||||
(mrspidey:error
|
||||
(format "Upper bound of containment is not tidy, types are ~s"
|
||||
types)))))
|
||||
list-reached-2)
|
||||
|
||||
(begin0
|
||||
(let/cc
|
||||
fail
|
||||
|
||||
(recur ensure-contained ([tvar1 tvar1][tvar2 tvar2])
|
||||
(fluid-let ([stack (cons (cons tvar1 tvar2) stack)])
|
||||
(let ([n (get-num tvar1)]
|
||||
[reached (get-reached-vec tvar2)])
|
||||
(unless (vector-ref reached n)
|
||||
;; Need to search - record true to detect loops
|
||||
(vector-set! reached n #t)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _ (and template ($ template _ _ ref)) _ fields)
|
||||
(or
|
||||
|
||||
;; More than one matching => not tidy => say contained.
|
||||
(> (count (match-lambda
|
||||
[($ AV _ template2 _ fields2)
|
||||
(eq? (template-type template)
|
||||
(template-type template2))])
|
||||
(get-Tvar-objs tvar2))
|
||||
1)
|
||||
|
||||
(ormap
|
||||
(match-lambda
|
||||
[($ AV _ template2 _ fields2)
|
||||
(and ;(eq? template template2)
|
||||
(eq? (template-type template)
|
||||
(template-type template2))
|
||||
(begin
|
||||
(for i 0 (vector-length ref)
|
||||
(let ([r (vector-ref ref i)])
|
||||
(ensure-contained
|
||||
(vector-ref fields r)
|
||||
(vector-ref fields2 r))))
|
||||
#t))])
|
||||
(get-Tvar-objs tvar2))
|
||||
;; No match
|
||||
(begin
|
||||
(printf
|
||||
"~s ~s not in ~s ~s~n"
|
||||
(map (lambda (AV) (template-type (AV-template AV)))
|
||||
(get-Tvar-objs tvar1))
|
||||
(Tvar-name tvar1)
|
||||
(map (lambda (AV) (template-type (AV-template AV)))
|
||||
(get-Tvar-objs tvar2))
|
||||
(Tvar-name tvar2))
|
||||
(set! fail-stack stack)
|
||||
(fail #f)))])
|
||||
(get-Tvar-objs tvar1))))))
|
||||
|
||||
;; Did not fail => succeed
|
||||
#t)
|
||||
|
||||
))))
|
||||
|
||||
'(define (show-fail-stack-sdl)
|
||||
(map
|
||||
(match-lambda
|
||||
[(a . d)
|
||||
(list (Tvar->SDL a)
|
||||
(Tvar->SDL d))])
|
||||
fail-stack))
|
||||
|
||||
'(define (show-fail-stack)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(a . d)
|
||||
(printf "============~n")
|
||||
(show-Tvar a)
|
||||
(show-Tvar d)])
|
||||
fail-stack))
|
@ -0,0 +1,37 @@
|
||||
;; debugging.ss
|
||||
|
||||
(define debugging #f)
|
||||
(define debugging-front #f)
|
||||
(define debugging-traverse #f)
|
||||
(define debugging-object #f)
|
||||
(define debugging-unit #f)
|
||||
(define debugging-check #f)
|
||||
(define debugging-atenv #f)
|
||||
(define debugging-atype #f)
|
||||
(define debugging-sdl #f)
|
||||
(define debugging-sdl2 #f)
|
||||
(define debugging-gui #t)
|
||||
|
||||
(define debugging-min #f)
|
||||
(define debugging-min2 #f)
|
||||
(define debugging-few #f)
|
||||
(define debugging-gram #f)
|
||||
(define debugging-dfa-min #f)
|
||||
(define debugging-min-table #f)
|
||||
|
||||
(define timing-min #f)
|
||||
|
||||
(define pretty-print-debug pretty-print)
|
||||
|
||||
(define (set-debug-flag which val)
|
||||
(case which
|
||||
[(general) (set! debugging val)]
|
||||
[(min) (set! debugging-min val)]
|
||||
[(front) (set! debugging-front val)]
|
||||
[(traverse) (set! debugging-traverse val)]))
|
||||
|
||||
;(set! debugging #t)
|
||||
;(set! debugging-min #t)
|
||||
;(set! debugging-gram #t)
|
||||
;(set! debugging-min-table #t)
|
||||
;(set! timing-min #t)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
;; driver.ss - driver file for text version
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define st:defconstructor add-default-constructor!)
|
||||
'(define st:defprim add-default-primitive!)
|
||||
'(define st:type-alias default-constructor-alias!)
|
||||
'(define (st:deftype name nutype)
|
||||
(install-input-type-expander!
|
||||
(lambda (type)
|
||||
(if (eq? type name) nutype type))))
|
||||
|
||||
(define st:set-debug set-debug-flag)
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define st:analyze
|
||||
(lambda (file)
|
||||
(analyze-program file)
|
||||
(void)))
|
||||
|
||||
(define st:
|
||||
(lambda (file)
|
||||
(let ([defs (analyze-program file)])
|
||||
(calc-checks defs)
|
||||
(void))))
|
||||
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (st:type-fn . args)
|
||||
;;(when (null? defs-bind)
|
||||
;; (error 'st:type "Checking not done yet, use st:"))
|
||||
(let* ([show
|
||||
(lambda (name)
|
||||
(list (zodiac:binding-var name)
|
||||
':
|
||||
(FlowType->SDL (atenv:lookup global-def-env name))))]
|
||||
[show*
|
||||
(lambda (b*)
|
||||
(map show b*)
|
||||
;;(for-each (lambda (b) (pretty-print (show b))) b*)
|
||||
)])
|
||||
|
||||
(if (null? args)
|
||||
;; Show all
|
||||
(show* (atenv:domain global-def-env))
|
||||
;; Show selectively
|
||||
(show*
|
||||
(filter
|
||||
(lambda (name) (memq (zodiac:binding-var name) args))
|
||||
(atenv:domain global-def-env))))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define st:help
|
||||
(lambda ()
|
||||
;(printf "Commands for SBA Soft Scheme Version ~a~%" st:version)
|
||||
(printf " (st:analyze file) analyze file~n")
|
||||
(printf " (st:check file) type check file~%")
|
||||
; (printf " (st:write file [output]) type check file and write it~%")
|
||||
(printf " (st:type [definition ...]) show type of top level defs~n")
|
||||
; (printf " (st:ltype var) show type of internal vars~n")
|
||||
; (printf " (st:why N) prints cause of check N~n")
|
||||
(printf " (st:control [param [value]]) show or change parameters~n")
|
||||
(printf " (st:help) prints this message~%")))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; (st:check file (output)) type check file
|
||||
; (st:bench file) execute type checked file fast
|
||||
; (st:run file) execute type checked file
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(st:language 'DrScheme)
|
||||
;(st:language 'MrEd)
|
||||
|
||||
;(printf "DrScheme selected~n")
|
@ -0,0 +1,105 @@
|
||||
(define-struct exn (message debug-info))
|
||||
(define-struct (exn:user struct:exn) ())
|
||||
(define-struct (exn:syntax struct:exn) (expr))
|
||||
(define-struct (exn:variable struct:exn) (id))
|
||||
(define-struct (exn:application struct:exn) (value))
|
||||
(define-struct (exn:application:non-procedure struct:exn:application) ())
|
||||
(define-struct (exn:application:arity struct:exn:application) (expected))
|
||||
(define-struct (exn:application:type struct:exn:application) (expected))
|
||||
(define-struct (exn:application:range struct:exn:application) ())
|
||||
(define-struct (exn:application:range:bounds struct:exn:application:range) (min max))
|
||||
(define-struct (exn:application:range:bounds:vector struct:exn:application:range:bounds) ())
|
||||
(define-struct (exn:application:range:bounds:string struct:exn:application:range:bounds) ())
|
||||
(define-struct (exn:application:range:bounds:struct struct:exn:application:range:bounds) ())
|
||||
(define-struct (exn:application:range:list struct:exn:application:range) ())
|
||||
(define-struct (exn:application:list-sizes struct:exn:application) ())
|
||||
(define-struct (exn:application:map-arity struct:exn:application) (provided))
|
||||
(define-struct (exn:application:integer struct:exn:application) ())
|
||||
(define-struct (exn:application:list struct:exn:application) ())
|
||||
(define-struct (exn:application:math struct:exn:application) ())
|
||||
(define-struct (exn:application:math:zero struct:exn:application:math) ())
|
||||
(define-struct (exn:application:math:infinity struct:exn:application:math) ())
|
||||
(define-struct (exn:application:math:negative struct:exn:application:math) ())
|
||||
(define-struct (exn:application:math:radix struct:exn:application:math) ())
|
||||
(define-struct (exn:application:mode-conflict struct:exn:application) (filename))
|
||||
(define-struct (exn:application:file-position struct:exn:application) ())
|
||||
(define-struct (exn:application:fprintf struct:exn:application) ())
|
||||
(define-struct (exn:application:fprintf:extra-arguments struct:exn:application:fprintf) (extras))
|
||||
(define-struct (exn:application:fprintf:no-argument struct:exn:application:fprintf) ())
|
||||
(define-struct (exn:application:fprintf:argument-type struct:exn:application:fprintf) (expected))
|
||||
(define-struct (exn:else struct:exn) ())
|
||||
(define-struct (exn:struct struct:exn) ())
|
||||
(define-struct (exn:struct:struct-type struct:exn:struct) (value))
|
||||
(define-struct (exn:object struct:exn) ())
|
||||
(define-struct (exn:object:class-type struct:exn:object) (value))
|
||||
(define-struct (exn:object:interface-type struct:exn:object) (value))
|
||||
(define-struct (exn:object:generic struct:exn:object) (object))
|
||||
(define-struct (exn:object:inherit struct:exn:object) (ivar))
|
||||
(define-struct (exn:object:implement struct:exn:object) (ivar))
|
||||
(define-struct (exn:object:class-ivar struct:exn:object) (class ivar))
|
||||
(define-struct (exn:object:interface-ivar struct:exn:object) (interface ivar))
|
||||
(define-struct (exn:object:ivar struct:exn:object) (object ivar))
|
||||
(define-struct (exn:object:private-class struct:exn:object) (class))
|
||||
(define-struct (exn:object:init struct:exn:object) (object class))
|
||||
(define-struct (exn:object:init:multiple struct:exn:object:init) ())
|
||||
(define-struct (exn:object:init:never struct:exn:object:init) ())
|
||||
(define-struct (exn:unit struct:exn) ())
|
||||
(define-struct (exn:unit:non-unit struct:exn:unit) (value))
|
||||
(define-struct (exn:unit:arity struct:exn:unit) (unit))
|
||||
(define-struct (exn:unit:import struct:exn:unit) (in-unit out-unit in-tag out-tag name))
|
||||
(define-struct (exn:unit:export struct:exn:unit) (unit tag name))
|
||||
(define-struct (exn:unit:invoke struct:exn:unit) ())
|
||||
(define-struct (exn:unit:invoke:variable struct:exn:unit:invoke) (name))
|
||||
(define-struct (exn:unit:signature struct:exn:unit) ())
|
||||
(define-struct (exn:unit:signature:non-signed-unit struct:exn:unit:signature) (value))
|
||||
(define-struct (exn:unit:signature:arity struct:exn:unit:signature) (unit))
|
||||
(define-struct (exn:unit:signature:match struct:exn:unit:signature) (dest-context src-context variable))
|
||||
(define-struct (exn:unit:signature:match:missing struct:exn:unit:signature:match) ())
|
||||
(define-struct (exn:unit:signature:match:extra struct:exn:unit:signature:match) ())
|
||||
(define-struct (exn:unit:signature:match:kind struct:exn:unit:signature:match) ())
|
||||
(define-struct (exn:read struct:exn) (port))
|
||||
(define-struct (exn:read:paren struct:exn:read) ())
|
||||
(define-struct (exn:read:number struct:exn:read) (input))
|
||||
(define-struct (exn:read:char struct:exn:read) (input))
|
||||
(define-struct (exn:read:eof struct:exn:read) (expected))
|
||||
(define-struct (exn:read:dot struct:exn:read) ())
|
||||
(define-struct (exn:read:unsupported struct:exn:read) (input))
|
||||
(define-struct (exn:read:vector-length struct:exn:read) (input))
|
||||
(define-struct (exn:read:compiled struct:exn:read) ())
|
||||
(define-struct (exn:read:graph struct:exn:read) ())
|
||||
(define-struct (exn:i/o struct:exn) ())
|
||||
(define-struct (exn:i/o:read struct:exn:i/o) (port))
|
||||
(define-struct (exn:i/o:write struct:exn:i/o) (port))
|
||||
(define-struct (exn:i/o:filesystem struct:exn:i/o) (pathname))
|
||||
(define-struct (exn:i/o:filesystem:path struct:exn:i/o:filesystem) ())
|
||||
(define-struct (exn:i/o:filesystem:path:username struct:exn:i/o:filesystem:path) ())
|
||||
(define-struct (exn:i/o:filesystem:file struct:exn:i/o:filesystem) ())
|
||||
(define-struct (exn:i/o:filesystem:directory struct:exn:i/o:filesystem) ())
|
||||
(define-struct (exn:i/o:filesystem:collection struct:exn:i/o:filesystem) ())
|
||||
(define-struct (exn:i/o:filesystem:file-exists struct:exn:i/o:filesystem) ())
|
||||
(define-struct (exn:i/o:port-closed struct:exn:i/o) (port))
|
||||
(define-struct (exn:i/o:user-port struct:exn:i/o) (port))
|
||||
(define-struct (exn:i/o:tcp struct:exn:i/o) ())
|
||||
(define-struct (exn:i/o:tcp:connect struct:exn:i/o:tcp) (address port-id))
|
||||
(define-struct (exn:i/o:tcp:listen struct:exn:i/o:tcp) (port-id))
|
||||
(define-struct (exn:i/o:tcp:accept struct:exn:i/o:tcp) (listener))
|
||||
(define-struct (exn:i/o:tcp:listener-closed struct:exn:i/o:tcp) (listener))
|
||||
(define-struct (exn:misc struct:exn) ())
|
||||
(define-struct (exn:misc:unsupported struct:exn:misc) ())
|
||||
(define-struct (exn:misc:user-break struct:exn:misc) ())
|
||||
(define-struct (exn:misc:out-of-memory struct:exn:misc) ())
|
||||
(define-struct (exn:misc:parameterization struct:exn:misc) (value))
|
||||
(define-struct (exn:misc:defmacro struct:exn:misc) (value))
|
||||
(define-struct (exn:misc:expansion-time struct:exn:misc) ())
|
||||
(define-struct (exn:misc:constant struct:exn:misc) (id))
|
||||
(define-struct (exn:misc:continuation struct:exn:misc) ())
|
||||
(define-struct (exn:misc:thread struct:exn:misc) ())
|
||||
(define-struct (exn:misc:thread:kill struct:exn:misc:thread) ())
|
||||
(define-struct (exn:misc:semaphore struct:exn:misc) ())
|
||||
(define-struct (exn:misc:hash-table struct:exn:misc) (key))
|
||||
(define-struct (exn:misc:regexp struct:exn:misc) ())
|
||||
(define-struct (exn:misc:process struct:exn:misc) ())
|
||||
(define-struct (exn:misc:dynamic-extension struct:exn:misc) (name))
|
||||
(define-struct (exn:misc:dynamic-extension:open struct:exn:misc:dynamic-extension) ())
|
||||
(define-struct (exn:misc:dynamic-extension:version struct:exn:misc:dynamic-extension) ())
|
||||
(define-struct (exn:misc:dynamic-extension:initialize struct:exn:misc:dynamic-extension) ())
|
@ -0,0 +1,105 @@
|
||||
;; expander-boot.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
(printf "Loading expander-boot.ss~n")
|
||||
|
||||
(define __keep-mrspidey-annotations #t)
|
||||
(load "~cormac/scheme/mzschemerc.ss")
|
||||
(match:set-error-control 'error)
|
||||
|
||||
(defmacro assert args '(void))
|
||||
(defmacro begin-test-case args `(begin ,@args))
|
||||
;(defmacro type: args `(type:-quote (quote ,args)))
|
||||
(defmacro primitive: args `(type: ,@args))
|
||||
|
||||
(defmacro include-exp (f)
|
||||
(let ([p (open-input-file f)])
|
||||
(begin0
|
||||
(read p)
|
||||
(close-input-port p))))
|
||||
|
||||
;; ---------- structures --------------------------------------------------
|
||||
;; field = (: sym type) | (! sym type) | sym
|
||||
;; field-name = sym
|
||||
|
||||
(define (struct-expander-fn struct: const?)
|
||||
(#%let ([make-exn make-exn:syntax]
|
||||
[debug debug-info-handler])
|
||||
(#%lambda body
|
||||
(#%let* ([syntax-error
|
||||
(#%lambda (s)
|
||||
(#%raise
|
||||
(make-exn
|
||||
(#%format "define-struct: ~a" s)
|
||||
((debug))
|
||||
(#%cons 'define-struct body))))]
|
||||
[field->field-name
|
||||
(match-lambda
|
||||
[((or ': '!) sym _) sym]
|
||||
[(? symbol? sym) sym]
|
||||
[x (syntax-error (format "Bad field ~s" x))])]
|
||||
[field-mutable?
|
||||
(match-lambda
|
||||
[('! sym _) #t]
|
||||
[_ (not const?)])]
|
||||
[build-struct-names
|
||||
(#%lambda (name fields)
|
||||
(#%let ([name (#%symbol->string name)]
|
||||
[+ #%string-append])
|
||||
(#%map #%string->symbol
|
||||
(#%append
|
||||
(#%list
|
||||
(+ "struct:" name)
|
||||
(+ "make-" name)
|
||||
(+ name "?"))
|
||||
(#%apply
|
||||
#%append
|
||||
(#%map
|
||||
(#%lambda (field)
|
||||
(let ([f
|
||||
(symbol->string
|
||||
(field->field-name field))])
|
||||
(cons
|
||||
(+ name "-" f)
|
||||
(if (field-mutable? field)
|
||||
(list (+ "set-" name "-" f "!"))
|
||||
'()))))
|
||||
fields))))))])
|
||||
(#%or (#%pair? body)
|
||||
(syntax-error "empty declaration"))
|
||||
(#%or (#%= 2 (#%length body))
|
||||
(syntax-error "wrong number of parts"))
|
||||
(#%or (#%symbol? (#%car body))
|
||||
(#%and (#%pair? (#%car body))
|
||||
(#%symbol? (#%caar body))
|
||||
(#%pair? (#%cdar body))
|
||||
(#%null? (#%cddar body)))
|
||||
(syntax-error "first part must be an identifier or identifier-expression pair"))
|
||||
(#%or (#%list? (#%cadr body))
|
||||
(syntax-error "improper field list"))
|
||||
(#%let* ([name (#%if (#%symbol? (#%car body))
|
||||
(#%car body)
|
||||
(#%caar body))]
|
||||
[fields (#%cadr body)])
|
||||
`(#%define-values ,(build-struct-names name fields)
|
||||
(,struct: ,@body)))))))
|
||||
|
||||
;(#%define-macro define-const-typed-structure (struct-expander-fn '#%const-typed-structure #t))
|
||||
(#%define-macro define-const-typed-structure (struct-expander-fn '#%typed-structure #f))
|
||||
(#%define-macro define-typed-structure (struct-expander-fn '#%typed-structure #f))
|
||||
|
||||
(printf "expander-boot.ss done~n")
|
@ -0,0 +1,322 @@
|
||||
;; gram.ss
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define debugging-gram #f)
|
||||
(defmacro pretty-debug-gram args `(when debugging-gram (pretty-print ,@args)))
|
||||
|
||||
; ======================================================================
|
||||
; VIEWING CONSTRAINTS AS GRAMMARS
|
||||
; ======================================================================
|
||||
; Non-Terminals
|
||||
|
||||
(define-structure (NT AVS type)
|
||||
([rhs* '()][prop #f][tag #f][sources #f][num #f][edgefrom '()]))
|
||||
|
||||
(define mk-AVS-NTs!
|
||||
(lambda (AVS)
|
||||
(set-AVS-L! AVS (make-NT AVS 'L ))
|
||||
(set-AVS-U! AVS (make-NT AVS 'U ))
|
||||
(set-AVS-LI! AVS (make-NT AVS 'LI))
|
||||
(set-AVS-UI! AVS (make-NT AVS 'UI))))
|
||||
|
||||
(define same-nt-type?
|
||||
(match-lambda*
|
||||
[(($ NT _ t1) ($ NT _ t2)) (eq? t1 t2)]))
|
||||
|
||||
(define nt-chg-AVS
|
||||
(match-lambda*
|
||||
[(f ($ NT x type)) (make-NT (f x) type)]))
|
||||
|
||||
(define drop-I
|
||||
(match-lambda
|
||||
[(and nt ($ NT AVS type _))
|
||||
(case type
|
||||
[(or 'L 'U) nt]
|
||||
[LI (AVS-L AVS)]
|
||||
[UI (AVS-U AVS)])]))
|
||||
|
||||
(define invert-nt
|
||||
(match-lambda
|
||||
[($ NT AVS 'L) (AVS-UI AVS)]
|
||||
[($ NT AVS 'LI) (AVS-U AVS)]
|
||||
[($ NT AVS 'U) (AVS-LI AVS)]
|
||||
[($ NT AVS 'UI) (AVS-L AVS)]))
|
||||
|
||||
; ======================================================================
|
||||
; Right hand side of a production
|
||||
|
||||
(define-structure (rhs* grsym misc nts))
|
||||
(define (make-rhs grsym nt) (make-rhs* grsym '() (list nt)))
|
||||
|
||||
(define-structure (grsym ineq fn sign template field-no))
|
||||
;; ineq is '<= or '>=
|
||||
;; fn is 'inj, 'inj-tst or 'ext
|
||||
;; sign is #t (monotonic) or #f (antimonotonic)
|
||||
;; field-no may be #f
|
||||
|
||||
(define (make-grsym->=inj+ t f) (make-grsym '>= 'inj #t t f))
|
||||
(define (make-grsym->=inj- t f) (make-grsym '>= 'inj #f t f))
|
||||
(define (make-grsym->=inj? t f) (make-grsym '>= 'inj '? t f))
|
||||
|
||||
(define (make-grsym-<=inj-tst+ t f) (make-grsym '<= 'inj-tst #t t f))
|
||||
(define (make-grsym-<=inj-tst- t f) (make-grsym '<= 'inj-tst #f t f))
|
||||
|
||||
(define (make-grsym-<=ext+ t f) (make-grsym '<= 'ext #t t f))
|
||||
(define (make-grsym->=ext- t f) (make-grsym '>= 'ext #f t f))
|
||||
|
||||
(define (make-grsym->=ext+ t f) (make-grsym '>= 'ext #t t f))
|
||||
(define (make-grsym-<=ext- t f) (make-grsym '<= 'ext #f t f))
|
||||
|
||||
;;(define (make-grsym-filter filter) (make-grsym '<= 'filter #t filter #f))
|
||||
(define (make-grsym-filter filter) (make-grsym '>= 'filter #t filter #f))
|
||||
(define grsym-crossover '>=crossover)
|
||||
|
||||
;; a grsym can also be '>=epsilon or '<=epsilon
|
||||
|
||||
(define grsym-eq?
|
||||
(match-lambda*
|
||||
[(($ grsym i1 f1 s1 t1 n1) ($ grsym i2 f2 s2 t2 n2))
|
||||
(and (eq? i1 i2) (eq? f1 f2) (eq? t1 t2) (eqv? n1 n2))]
|
||||
[(x y) (eq? x y)]))
|
||||
|
||||
(define invert-grsym
|
||||
(match-lambda
|
||||
[($ grsym '>= 'inj sign template field-no)
|
||||
(make-grsym '<= 'ext sign template field-no)]
|
||||
[($ grsym '<= 'inj-tst sign template field-no)
|
||||
(make-grsym '>= 'ext sign template field-no)]
|
||||
[($ grsym '>= 'filter #t filter #f)
|
||||
(make-grsym '<= 'unfilter #t filter #f)]
|
||||
['>=crossover '<=crossover]
|
||||
[(and g ($ grsym))
|
||||
(error 'invert-grsym "Bad grsym ~s" (grsym->rep g))]))
|
||||
|
||||
(define grsym-epsilon-or-filter?
|
||||
(match-lambda
|
||||
[(? symbol?) #t]
|
||||
[($ grsym _ 'filter) #t]
|
||||
[_ #f]))
|
||||
|
||||
; ======================================================================
|
||||
; Parameters for creating grammar
|
||||
|
||||
(define-structure
|
||||
(parameters-grammar
|
||||
interp-sign ; applied to sign of each field
|
||||
prims ; #t => treat prims as constants
|
||||
filters ; #t => filters are not epsilon edges
|
||||
assignable-fields ; #t => assignable fields in grammar
|
||||
structure-opaque ; #t => structures are constants
|
||||
))
|
||||
|
||||
; ======================================================================
|
||||
;; Prepare for creating grammar
|
||||
|
||||
(define (prep-gram!)
|
||||
(for-each mk-AVS-NTs! list-AVS))
|
||||
|
||||
; ======================================================================
|
||||
;; Initializing the NT fields of an AVS
|
||||
|
||||
(define (add-rhs! NT rhs)
|
||||
(pretty-debug-gram
|
||||
(match rhs
|
||||
[($ rhs* grsym _ nts)
|
||||
(assert (list? nts))
|
||||
(list `(add-rhs! ,(nt->sym NT) ,(grsym->rep grsym)
|
||||
,(map nt->sym nts)))]))
|
||||
(set-NT-rhs*! NT (cons rhs (NT-rhs* NT))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (for-each-calc-prods-L L paras fn)
|
||||
(match L
|
||||
[($ NT AVS 'L)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _ (and template ($ template _ signs _ _ _ _ structure?))
|
||||
misc fields)
|
||||
(if (or (zero? (vector-length fields))
|
||||
(and structure?
|
||||
(parameters-grammar-structure-opaque paras)))
|
||||
(fn (make-rhs* (make-grsym '>= 'inj #t template '?) misc '()))
|
||||
(for i 0 (vector-length fields)
|
||||
(let ([field (vector-ref fields i)]
|
||||
[interp-sign (parameters-grammar-interp-sign paras)]
|
||||
[sign (interp-sign (vector-ref signs i))])
|
||||
(fn (make-rhs*
|
||||
(make-grsym '>= 'inj (eq? sign '>=inj+) template i)
|
||||
misc
|
||||
(case sign
|
||||
[>=inj+ (list (AVS-L field))]
|
||||
[>=inj-
|
||||
(if (or #f ;; mk-assignable-part-fields?
|
||||
(eq? template template-lam))
|
||||
(map AVS-U (AVS-transitive-edgeto field))
|
||||
'())]))))))])
|
||||
(get-AVS-objs AVS))]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (for-each-calc-prods-U U paras fn)
|
||||
(match U
|
||||
[($ NT AVS 'U)
|
||||
(let ([interp-sign (parameters-grammar-interp-sign paras)])
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ (and template ($ template type signs)) field-no AVS2 misc)
|
||||
(case (interpret-sign (vector-ref signs field-no))
|
||||
[>=inj+
|
||||
(fn (make-rhs*
|
||||
(make-grsym-<=inj-tst+ template field-no)
|
||||
misc
|
||||
(list (AVS-U AVS2))))]
|
||||
[>=inj-
|
||||
(fn (make-rhs*
|
||||
(make-grsym-<=inj-tst- template field-no)
|
||||
misc
|
||||
(list (AVS-U AVS2))))])]
|
||||
[($ con-filter _ the-filter AVS2)
|
||||
(fn (make-rhs*
|
||||
(make-grsym-filter the-filter)
|
||||
'()
|
||||
(list (AVS-U AVS2))))])
|
||||
(AVS-constraints AVS)))
|
||||
(for-each
|
||||
(lambda (AVS2) (fn (make-rhs* '<=epsilon '() (list (AVS-U AVS2)))))
|
||||
(AVS-transitive-edgeto AVS))]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (for-each-calc-prods nt paras fn)
|
||||
(match nt
|
||||
[($ NT AVS 'L) (for-each-calc-prods-L nt paras fn)]
|
||||
[($ NT AVS 'U) (for-each-calc-prods-U nt paras fn)]))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(define (calc-productions!
|
||||
live-nts live-nt?
|
||||
mk-L? mk-U? mk-LI? mk-UI?
|
||||
L->LI
|
||||
mk-assignable-part-fields?
|
||||
treat-all-mono)
|
||||
|
||||
;; live-AVS, crossover-AVS, live-nt and live-nt?
|
||||
;; all come from calc-live-AVS-nt
|
||||
;; mk-... : bool -- controls which NTs to produce
|
||||
;; L->LI, ... : bool -- controls L->LI production rule
|
||||
|
||||
(let ([interpret-sign
|
||||
(if treat-all-mono
|
||||
(lambda (x) '>=inj+)
|
||||
(lambda (x) x))])
|
||||
|
||||
(for-each (lambda (nt) (set-NT-rhs*! nt '()))
|
||||
live-nts)
|
||||
|
||||
;; ------ Now fill NTs from AV, constraints and edges
|
||||
|
||||
(for-each
|
||||
(lambda (AVS)
|
||||
(pretty-debug-gram `(Prods for AVS ,(name-for-AVS AVS)))
|
||||
|
||||
;; ------ Invert AV
|
||||
(when (and mk-L? (live-nt? (AVS-L AVS)))
|
||||
(AVs->prods AVS interpret-sign live-nt?))
|
||||
|
||||
;; ------ Invert constraints
|
||||
(when (and mk-U? (live-nt? (AVS-U AVS)))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ (and template ($ template type signs)) field-no AVS2 misc)
|
||||
(case (interpret-sign (vector-ref signs field-no))
|
||||
[>=inj+
|
||||
(add-rhs! (AVS-U AVS)
|
||||
(make-rhs*
|
||||
(make-grsym-<=inj-tst+ template field-no)
|
||||
misc
|
||||
(filter live-nt?
|
||||
(map AVS-U (AVS-transitive-edgeto AVS2)))))]
|
||||
[>=inj-
|
||||
(add-rhs! (AVS-U AVS)
|
||||
(make-rhs*
|
||||
(make-grsym-<=inj-tst- template field-no)
|
||||
misc
|
||||
(filter live-nt? (list (AVS-L AVS2)))))])]
|
||||
[($ con-filter _ the-filter AVS2)
|
||||
(add-rhs! (AVS-U AVS)
|
||||
(make-rhs*
|
||||
(make-grsym-filter the-filter)
|
||||
'()
|
||||
(filter live-nt?
|
||||
(map AVS-U (AVS-transitive-edgeto AVS2)))))
|
||||
'(for-each
|
||||
(lambda (to)
|
||||
(when (live-nt? (AVS-L to))
|
||||
(add-rhs! (AVS-L to)
|
||||
(make-rhs*
|
||||
(make-grsym-filter the-filter)
|
||||
'()
|
||||
(list (AVS-L AVS))))))
|
||||
(AVS-transitive-edgeto AVS2))
|
||||
])
|
||||
(AVS-constraints AVS)))
|
||||
)
|
||||
live-AVS)
|
||||
|
||||
;; ------ Add L->LI productions
|
||||
(when L->LI
|
||||
(for-each
|
||||
(lambda (AVS)
|
||||
(for-each
|
||||
(lambda (to)
|
||||
(when (and (NT? (AVS-L to)) (live-nt? (AVS-L to)))
|
||||
(add-rhs! (AVS-L to)
|
||||
(make-rhs* grsym-crossover '() (list (AVS-LI AVS))))))
|
||||
(AVS-transitive-edgeto AVS)))
|
||||
crossover-AVS))
|
||||
|
||||
;; ------ convert L, U productions into LI, UI productions
|
||||
(pretty-debug '(inverting productions))
|
||||
|
||||
(for-each
|
||||
(lambda (nt)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ rhs* grsym misc to-nts)
|
||||
(unless (eq? grsym '<=crossover)
|
||||
(let* ([inv-grsym (invert-grsym grsym)]
|
||||
[inv-nt (invert-nt nt)]
|
||||
[inv-rhs (make-rhs* inv-grsym misc (list inv-nt))])
|
||||
(for-each (lambda (to) (add-rhs! (invert-nt to) inv-rhs))
|
||||
to-nts)))])
|
||||
(NT-rhs* nt)))
|
||||
live-nts)
|
||||
|
||||
(let ([live-nts
|
||||
(apply append
|
||||
(map
|
||||
(match-lambda
|
||||
[($ NT AVS 'L) (list (AVS-L AVS) (AVS-UI AVS))]
|
||||
[($ NT AVS 'U) (list (AVS-U AVS) (AVS-LI AVS))])
|
||||
live-nts))])
|
||||
|
||||
;; Now group together all productions for given NT with given grsym
|
||||
(for-each
|
||||
(lambda (nt)
|
||||
(let ([rhs* (NT-rhs* nt)])
|
||||
(set-NT-rhs*! nt '())
|
||||
(for-each (lambda (rhs)
|
||||
(assert (list? (rhs*-nts rhs)))
|
||||
(add-rhs! nt rhs))
|
||||
(group-rhs* rhs*))))
|
||||
live-nts)
|
||||
|
||||
(list live-nts))))
|
@ -0,0 +1,147 @@
|
||||
;; hash.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-struct hash-table-state
|
||||
(hash-table-size entries-in-table
|
||||
resize-table-size entry->hash-fn
|
||||
hash-table))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
|
||||
(define prime1 83)
|
||||
(define prime2 1789)
|
||||
(define default-hash-table-size (* 32 1024))
|
||||
(define resize-table-fraction 0.6)
|
||||
|
||||
;;------------------------------------------------------------
|
||||
|
||||
(define hash-table-size 0)
|
||||
(define entries-in-table 0)
|
||||
(define resize-table-size 0)
|
||||
(define entry->hash-fn (void))
|
||||
(define hash-table (void))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
|
||||
(define (init-hash-table entry->hash size)
|
||||
(set! hash-table-size (if (zero? size) default-hash-table-size size))
|
||||
(set! entries-in-table 0)
|
||||
(set! resize-table-size
|
||||
(inexact->exact
|
||||
(round (* hash-table-size resize-table-fraction))))
|
||||
(set! entry->hash-fn entry->hash)
|
||||
(set! hash-table (make-vector hash-table-size '())))
|
||||
|
||||
(define (capture-hash-table-state)
|
||||
(make-hash-table-state hash-table-size entries-in-table
|
||||
resize-table-size entry->hash-fn
|
||||
hash-table))
|
||||
|
||||
(define restore-hash-table-state!
|
||||
(match-lambda
|
||||
[($ hash-table-state t1 t2 t3 t4 t5)
|
||||
(set! hash-table-size t1)
|
||||
(set! entries-in-table t2)
|
||||
(set! resize-table-size t3)
|
||||
(set! entry->hash-fn t4)
|
||||
(set! hash-table t5)]))
|
||||
|
||||
(define free-hash-table-state!
|
||||
(match-lambda
|
||||
[($ hash-table-state t1 t2 t3 t4 t5)
|
||||
(assert (not (eq? t5 hash-table)))
|
||||
(vector-zero! t5)]))
|
||||
|
||||
(define (prompt-hash-table-state)
|
||||
(list (capture-hash-table-state)
|
||||
(vector-length hash-table)
|
||||
(recur loop ([i (sub1 (vector-length hash-table))])
|
||||
(if (< i 0)
|
||||
'()
|
||||
(if (null? (vector-ref hash-table i))
|
||||
(loop (sub1 i))
|
||||
(cons (cons i (vector-ref hash-table i)) (loop (sub1 i))))))))
|
||||
|
||||
(define unprompt-hash-table-state!
|
||||
(match-lambda
|
||||
[(state vec-size vec-entries)
|
||||
(restore-hash-table-state! state)
|
||||
(for i 0 (vector-length hash-table) (vector-set! hash-table i '()))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(i . elem) (vector-set! hash-table i elem)])
|
||||
vec-entries)]))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
|
||||
|
||||
;; (define (hash-fn n1 n2)
|
||||
;; (fxlogand (+ (* n1 prime1) (* n2 prime2)) (sub1 hash-table-size)))
|
||||
|
||||
(define (hash-fn n1 n2)
|
||||
(modulo (+ (* n1 prime1) (* n2 prime2)) hash-table-size))
|
||||
|
||||
(define (hash-fn* n*) (foldl hash-fn 0 n*))
|
||||
|
||||
(define (add-entry h entry)
|
||||
(vector-set! hash-table h (cons entry (vector-ref hash-table h)))
|
||||
(set! entries-in-table (add1 entries-in-table))
|
||||
'(if (zero? (mod entries-in-table 10000))
|
||||
(printf "Entries ~s~n" entries-in-table))
|
||||
(when (>= entries-in-table resize-table-size)
|
||||
(resize-hash-table)))
|
||||
|
||||
(define (resize-hash-table)
|
||||
(set! hash-table-size (* 2 hash-table-size))
|
||||
(let ( [old hash-table]
|
||||
[s (format "Resizing hash table to ~s" hash-table-size)])
|
||||
(mrspidey:progress s '...)
|
||||
(flush-output)
|
||||
(set! hash-table (make-vector hash-table-size '()))
|
||||
(set! resize-table-size
|
||||
(inexact->exact
|
||||
(round (* hash-table-size resize-table-fraction))))
|
||||
(for i 0 (vector-length old)
|
||||
(map
|
||||
(lambda (entry)
|
||||
(let ([h (entry->hash-fn entry)])
|
||||
(vector-set! hash-table h
|
||||
(cons entry (vector-ref hash-table h)))))
|
||||
(vector-ref old i)))
|
||||
(mrspidey:progress s 'done)
|
||||
;;(show-stat-small)
|
||||
))
|
||||
|
||||
(define (hash-table-list h) (vector-ref hash-table h))
|
||||
|
||||
(define (hash-find h ok?)
|
||||
(recur loop ([l (vector-ref hash-table h)])
|
||||
(cond [(null? l) #f]
|
||||
[(ok? (car l)) (car l)]
|
||||
[else (loop (cdr l))])))
|
||||
|
||||
(define (hash-table-info)
|
||||
(list hash-table-size entries-in-table
|
||||
(recur loop ([i 0][c 0])
|
||||
(if (= i hash-table-size) c
|
||||
(let ([l (length (vector-ref hash-table i))])
|
||||
(loop (add1 i)
|
||||
(+ c (max 0 (- l 1)))))))))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
|
@ -0,0 +1,601 @@
|
||||
; hyper.ss - interface to GUI
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;;----------------------------------------------------------------------
|
||||
|
||||
(define (st:analyze-and-make-annotations filename)
|
||||
(analysis-set-arrow-filter! #f)
|
||||
(record-analyzed-file
|
||||
filename
|
||||
(lambda () (open-code-file filename))
|
||||
(lambda () (analyze-program filename))))
|
||||
|
||||
(define (calc-annotations defs)
|
||||
(match-let*
|
||||
([type-annotations (calc-type-annotations defs)]
|
||||
[(check-annotations uncheck-annotations) (calc-checks defs)]
|
||||
[all-annotations
|
||||
(vector type-annotations check-annotations uncheck-annotations)])
|
||||
;;(pretty-debug `(links ,all-annotations))
|
||||
all-annotations))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
|
||||
(define arrow-filter #f) ; if not #f, then a list of templates
|
||||
; only show pred with matching AV
|
||||
|
||||
(define (analysis-set-arrow-filter! C)
|
||||
(set! arrow-filter
|
||||
(if C
|
||||
(map lookup-template (list C))
|
||||
#f)))
|
||||
|
||||
(define (analysis-filter-on?)
|
||||
(and arrow-filter (symbol->string (template-type (car arrow-filter)))))
|
||||
|
||||
(define (analysis-get-filters)
|
||||
(cons
|
||||
(cons "No filter" #f)
|
||||
(map
|
||||
(lambda (C) (cons (symbol->string C) C))
|
||||
(append
|
||||
`( nil num sym str void undefined true false
|
||||
box cons vec eof iport oport
|
||||
promise unit thread hash-table regexp parameterization semaphore)
|
||||
(filter
|
||||
(lambda (x) x)
|
||||
(hash-table-map
|
||||
constructor-env
|
||||
(lambda (c template)
|
||||
(and
|
||||
(memq template-structure (template-super-templates template))
|
||||
c))))))))
|
||||
|
||||
;; ------------------------------
|
||||
|
||||
(define (objs-contain-filter? objs)
|
||||
(or
|
||||
(and
|
||||
(eq? arrow-filter #f)
|
||||
(not (null? objs)))
|
||||
(ormap
|
||||
(lambda (AV)
|
||||
(memq (AV-template AV) arrow-filter))
|
||||
objs)))
|
||||
|
||||
(define (tvar-contain-filter-mvalues? get-Tvar-objs tvar)
|
||||
(or
|
||||
(objs-contain-filter? (get-Tvar-objs tvar))
|
||||
(ormap
|
||||
(match-lambda
|
||||
[($ AV _ (? (eqc? template-mvalues)) _ #(tvar-mvlist))
|
||||
;;(pretty-debug `(tvar-mvlist ,(Tvar-name tvar-mvlist)))
|
||||
(ormap
|
||||
(match-lambda
|
||||
[($ AV _ (? (eqc? template-cons)) _ #(tvar-car-mvlist _))
|
||||
(objs-contain-filter? (get-Tvar-objs tvar-car-mvlist))]
|
||||
[_ #f])
|
||||
(get-Tvar-objs tvar-mvlist))]
|
||||
[_ #f])
|
||||
(get-Tvar-objs tvar))))
|
||||
|
||||
(define (FlowType-contains-filter? ftype)
|
||||
;(pretty-debug `(FlowType-contains-filter? ,(FlowType-name ftype)))
|
||||
(or
|
||||
(not arrow-filter)
|
||||
(match (FlowType->Atype ftype)
|
||||
[(or (? atconst?) (? atprim?) (? Tvar?))
|
||||
(tvar-contain-filter-mvalues? Tvar-objs (FlowType->Tvar ftype))]
|
||||
[($ atvalues (val1 . _))
|
||||
(FlowType-contains-filter? val1)]
|
||||
;; other atypes are atschema atthunk, atstruct, atunit, atlunit
|
||||
;; all are too expensive to convert.
|
||||
[x
|
||||
(pretty-debug `(FlowType-contains-filter? unhandled-atype x))
|
||||
#f])))
|
||||
|
||||
(define (FlowType-orig-objs-contains-filter? ftype)
|
||||
;;(pretty-debug `(FlowType-orig-contains-filter? ,(FlowType-name ftype)))
|
||||
(match (FlowType->Atype ftype)
|
||||
[(or (? Tvar?))
|
||||
(tvar-contain-filter-mvalues? Tvar-orig-objs (FlowType->Tvar ftype))]
|
||||
[($ atvalues (val1 . _))
|
||||
(FlowType-orig-objs-contains-filter? val1)]
|
||||
;; other atypes are atschema atthunk, atstruct, atunit, atlunit
|
||||
;; all are too expensive to convert.
|
||||
[x
|
||||
(pretty-debug `(FlowType-orig-objs-contains-filter? unhandled-atype x))
|
||||
#f]))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; Abstracts over parents and children
|
||||
|
||||
(define analysis-walk1
|
||||
(lambda (start in-get-edges file-visable?)
|
||||
(assert (FlowType? start))
|
||||
(pretty-debug `(analysis-walk1 ,(FlowType-name start)))
|
||||
(if (string? (FlowType-type-annotation start))
|
||||
;; start from .za file, show no edges
|
||||
'()
|
||||
(letrec*
|
||||
( [traversed '()] ; list of FlowType's
|
||||
[preds '()] ; visable FlowType's
|
||||
[get-edges
|
||||
(lambda (ftype)
|
||||
(let ([r (in-get-edges ftype)])
|
||||
(pretty-debug `(get-edges ,(map FlowType-name (cons ftype r))))
|
||||
r))]
|
||||
[traverse
|
||||
(lambda (ftype)
|
||||
(pretty-debug `(traverse ,(FlowType-name ftype)))
|
||||
(when
|
||||
(and
|
||||
(FlowType-contains-filter? ftype)
|
||||
(not (memq ftype traversed)))
|
||||
(set! traversed (cons ftype traversed))
|
||||
(let*
|
||||
( [ftype-w/-ta (get-ftype-w/-ta ftype)]
|
||||
[ta (and ftype-w/-ta
|
||||
(FlowType-type-annotation ftype-w/-ta))])
|
||||
(pretty-debug
|
||||
`(traverse-ftype-w/-ta
|
||||
,(and ftype-w/-ta (FlowType-name ftype-w/-ta))))
|
||||
|
||||
(cond
|
||||
[(not ta)
|
||||
;; invisable
|
||||
;; Go back to parents
|
||||
(for-each traverse (get-edges ftype))]
|
||||
|
||||
[(string? ta)
|
||||
(if (file-visable? ta)
|
||||
|
||||
;; ftype from .za file, source file is loaded
|
||||
;; can follow this edge unless dest is from same file
|
||||
(for-each
|
||||
(lambda (ftype2)
|
||||
(let ([ta2 (FlowType-type-annotation ftype2)])
|
||||
(unless (and (string? ta2) (string=? ta ta2))
|
||||
(traverse ftype2))))
|
||||
(get-edges ftype))
|
||||
|
||||
;; .za file, source file not loaded
|
||||
(set! preds (cons ftype-w/-ta preds)))]
|
||||
|
||||
[(and
|
||||
(not (string? ta))
|
||||
(not (eq? ftype-w/-ta start)))
|
||||
|
||||
;; visable
|
||||
;; add to preds unless src and dest are single value
|
||||
(set! preds (cons ftype-w/-ta preds))]
|
||||
|
||||
[else
|
||||
;; Invisable
|
||||
;; Go back to parents
|
||||
(for-each traverse (get-edges ftype))]))))])
|
||||
|
||||
(for-each traverse (get-edges start))
|
||||
|
||||
(pretty-debug `(traversed ,(map FlowType-name traversed)))
|
||||
(pretty-debug
|
||||
`(preds ,(map
|
||||
(lambda (i) (and (FlowType? i) (FlowType-name i)))
|
||||
preds)))
|
||||
|
||||
(remq start preds)))))
|
||||
|
||||
(define (get-ftype-w/-ta ftype)
|
||||
(if (FlowType-type-annotation ftype)
|
||||
ftype
|
||||
(and (FlowType-values-ftype ftype)
|
||||
(get-ftype-w/-ta (FlowType-values-ftype ftype)))))
|
||||
|
||||
(define (single-value-ftype ftype)
|
||||
(let ([r
|
||||
(match (FlowType->Atype ftype)
|
||||
[(? Tvar? tvar)
|
||||
(ormap
|
||||
(lambda (AV) (not (eq? (AV-template AV) template-mvalues)))
|
||||
(get-Tvar-objs tvar))]
|
||||
[($ atvalues) #f]
|
||||
[_ #t])])
|
||||
(pretty-debug `(single-value-ftype ,(FlowType-name ftype) ,r))
|
||||
r))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; Returns the preds in the Tvar graph of a given ftype
|
||||
;; format is a list of Tvars of predecessors that are visable
|
||||
|
||||
(define analysis-parents
|
||||
(lambda (ftype file-visable?)
|
||||
(pretty-debug `(analysis-parents ,(FlowType-name ftype) ,(print-struct)))
|
||||
(let ([r (analysis-walk1 ftype get-arrowfrom file-visable?)])
|
||||
(pretty-debug `(analysis-parents-returns ,(map FlowType-name r)))
|
||||
r)))
|
||||
|
||||
(define (get-arrowfrom to)
|
||||
(append
|
||||
(if (Tvar? to)
|
||||
(append
|
||||
(get-mvalue-components to)
|
||||
(Tvar-edgefrom to))
|
||||
'())
|
||||
(match (FlowType->Atype to)
|
||||
[($ atvalues ftypes)
|
||||
ftypes]
|
||||
[_ '()])
|
||||
(FlowType-arrowfrom to)))
|
||||
|
||||
(define (get-mvalue-components tvar)
|
||||
'(pretty-debug `(get-mvalue-components ,(Tvar-name tvar)))
|
||||
(filter-map
|
||||
(lambda (AV)
|
||||
(if (eq? (AV-template AV) template-mvalues)
|
||||
;; get-nth
|
||||
(let ( [p (mk-Tvar 'p)]
|
||||
[l (mk-Tvar 'l)])
|
||||
(new-edge! (vector-ref (AV-fields+ AV) 0) p)
|
||||
(new-con! p (make-con-cdr p))
|
||||
(new-con! p (make-con-car l))
|
||||
'(pretty-debug
|
||||
`(get-mvalue-components
|
||||
,(Tvar-name tvar) ,(Tvar-name p) ,(Tvar-name l)))
|
||||
l)
|
||||
#f))
|
||||
(get-Tvar-objs tvar)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define analysis-children
|
||||
(lambda (ftype file-visable?)
|
||||
(analysis-walk1
|
||||
ftype
|
||||
FlowType-alledgeto
|
||||
file-visable?)))
|
||||
|
||||
(define FlowType-alledgeto
|
||||
(lambda (ftype)
|
||||
(append
|
||||
;; Direct successors
|
||||
(FlowType-arrowto ftype)
|
||||
(if (FlowType-values-ftype ftype)
|
||||
(list (FlowType-values-ftype ftype))
|
||||
'())
|
||||
;; For filter successors, make sure some same values
|
||||
(if (Tvar? ftype)
|
||||
(append
|
||||
(Tvar-edgeto ftype)
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[($ con-filter _ _ tvar) tvar]
|
||||
[_ #f])
|
||||
(Tvar-constraints ftype)))
|
||||
'()))))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; Returns all ancestor/descendant arrows of a given ftype
|
||||
;; as (listof (list from to))
|
||||
|
||||
(define analysis-walkn
|
||||
(lambda (ftype get-edges file-visable?)
|
||||
(assert (FlowType? ftype))
|
||||
(pretty-debug `(analysis-walkn ,(FlowType-name ftype)))
|
||||
;;(error)
|
||||
(let ( [done '()] ; list of FlowType's
|
||||
[arrows '()]) ; visable arrows
|
||||
(recur traverse ([ftype ftype])
|
||||
(unless (memq ftype done)
|
||||
(set! done (cons ftype done))
|
||||
(let ([parents (analysis-walk1 ftype get-edges file-visable?)])
|
||||
(for-each
|
||||
(lambda (p)
|
||||
(set! arrows (cons (list p ftype) arrows))
|
||||
(traverse p))
|
||||
parents))))
|
||||
|
||||
arrows)))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; Returns all ancestor arrows of a given ftype
|
||||
;; as (listof (list from to))
|
||||
|
||||
(define analysis-ancestors
|
||||
(lambda (ftype file-visable?)
|
||||
(analysis-walkn ftype get-arrowfrom file-visable?)))
|
||||
|
||||
(define analysis-descendants
|
||||
(lambda (ftype file-visable?)
|
||||
(map reverse
|
||||
(analysis-walkn ftype FlowType-alledgeto file-visable?))))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; Calcs the shortest path to a source FlowType with
|
||||
;; orig-objs matching filter via breadth-first search
|
||||
;; Returns a list of FlowTypes
|
||||
;; or nil if no path to visable source
|
||||
;; or #f if ftype does not contain filter
|
||||
|
||||
(define analysis-shortest-path
|
||||
(lambda (ftype file-visable?)
|
||||
(assert (FlowType? ftype))
|
||||
(if (FlowType-contains-filter? ftype)
|
||||
(let ([visited (list ftype)])
|
||||
(letrec
|
||||
([traverse
|
||||
(lambda (list-paths)
|
||||
(pretty-debug
|
||||
`(list-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) list-paths)
|
||||
,(map FlowType-name visited)))
|
||||
(match list-paths
|
||||
[()
|
||||
;; No paths -> return the empty path
|
||||
'()]
|
||||
[((and path (ftype . rest-path)) . rest-paths)
|
||||
(pretty-debug
|
||||
`(path ,(map FlowType-name path)
|
||||
rest-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) rest-paths)))
|
||||
(let* ( [parents1 (analysis-parents ftype file-visable?)]
|
||||
[parents2
|
||||
(filter
|
||||
(lambda (p)
|
||||
(if (memq p visited)
|
||||
#f
|
||||
(begin
|
||||
(set! visited (cons p visited))
|
||||
#t)))
|
||||
parents1)])
|
||||
(set! visited (cons ftype visited))
|
||||
(if (and (null? parents2)
|
||||
(or (null? parents1)
|
||||
(null? rest-paths)))
|
||||
;; either this path has terminated,
|
||||
;; or went to cycle and is only one left.
|
||||
;; either way, return it
|
||||
(reverse path)
|
||||
(traverse
|
||||
(append rest-paths
|
||||
(filter-map
|
||||
(lambda (parent) (cons parent path))
|
||||
parents2)))))]))])
|
||||
|
||||
(let ([path (traverse
|
||||
(map list (analysis-parents ftype file-visable?)))])
|
||||
|
||||
(pretty-debug `(traverse-path ,(map FlowType-name path)))
|
||||
|
||||
path)))
|
||||
#f)))
|
||||
|
||||
'(define analysis-shortest-path
|
||||
(lambda (ftype file-visable?)
|
||||
(assert (FlowType? ftype))
|
||||
(if (FlowType-contains-filter? ftype)
|
||||
(let ([visited '()])
|
||||
(letrec
|
||||
([traverse
|
||||
(lambda (list-paths)
|
||||
(pretty-debug
|
||||
`(list-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) list-paths)
|
||||
,(map FlowType-name visited)))
|
||||
(match list-paths
|
||||
[()
|
||||
;; No paths -> return the empty path
|
||||
'()]
|
||||
[((and path (ftype . rest-path)) . rest-paths)
|
||||
(pretty-debug
|
||||
`(path ,(map FlowType-name path)
|
||||
rest-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) rest-paths)))
|
||||
(if (memq ftype visited)
|
||||
;; going around a loop
|
||||
(traverse rest-paths)
|
||||
(let* ( [parents (analysis-parents ftype file-visable?)])
|
||||
(set! visited (cons ftype visited))
|
||||
(if (and (null? parents) (null? rest-paths))
|
||||
;; this path has terminated, and is the only one left,
|
||||
;; and hence the longest, so return it
|
||||
(reverse path)
|
||||
(traverse
|
||||
(append rest-paths
|
||||
(filter-map
|
||||
(lambda (parent) (cons parent path))
|
||||
parents))))))]))])
|
||||
|
||||
(let ([path (traverse
|
||||
(map list (analysis-parents ftype file-visable?)))])
|
||||
|
||||
(pretty-debug `(traverse-path ,(map FlowType-name path)))
|
||||
|
||||
path)))
|
||||
#f)))
|
||||
|
||||
|
||||
|
||||
'(define analysis-shortest-path
|
||||
(lambda (ftype file-visable?)
|
||||
(assert (FlowType? ftype))
|
||||
(let ([visited '()])
|
||||
(letrec
|
||||
([traverse
|
||||
(lambda (list-paths)
|
||||
(pretty-debug
|
||||
`(list-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) list-paths)
|
||||
,(map FlowType-name visited)))
|
||||
(match list-paths
|
||||
[()
|
||||
;; No paths -> return the empty path
|
||||
'()]
|
||||
[((and path (ftype . rest-path)) . rest-paths)
|
||||
(if (memq ftype visited)
|
||||
|
||||
;; Visited on a shorter path
|
||||
(traverse rest-paths)
|
||||
|
||||
(begin
|
||||
(pretty-print
|
||||
`(path ,(map FlowType-name path)
|
||||
rest-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) rest-paths)))
|
||||
(set! visited (cons ftype visited))
|
||||
(cond
|
||||
[(FlowType-orig-objs-contains-filter? ftype)
|
||||
;; Has orig-objs that match the filter
|
||||
;; => return this path
|
||||
(reverse path)]
|
||||
[(FlowType-contains-filter? ftype)
|
||||
;; Has propogated objs that match the filter
|
||||
;; => go back to parent
|
||||
(let* ([new-paths
|
||||
(map
|
||||
(lambda (parent) (cons parent path))
|
||||
(get-arrowfrom ftype))])
|
||||
(pretty-print
|
||||
`(rest-paths ,(map (lambda (p) (map FlowType-name p)) rest-paths)
|
||||
new-paths
|
||||
,(map (lambda (p) (map FlowType-name p)) new-paths)))
|
||||
(traverse (append rest-paths new-paths)))]
|
||||
[else
|
||||
;; This FlowType no good
|
||||
(traverse rest-paths)])))]))])
|
||||
(let ([path (traverse (list (list ftype)))])
|
||||
|
||||
(pretty-print `(traverse-path ,(map FlowType-name path)))
|
||||
;; Drop first FlowType - it is us
|
||||
;; Remove invisable FlowType's
|
||||
;; NO LONGER Add '() as last tag if last FlowType invisable
|
||||
(assert (or (null? path) (eq? (car path) ftype)))
|
||||
(if (null? path)
|
||||
'()
|
||||
(recur loop ([path (cdr path)])
|
||||
(match path
|
||||
[(ftype . rest)
|
||||
(cond
|
||||
[(FlowType-type-annotation ftype) (cons ftype (loop rest))]
|
||||
[(null? rest) '()]
|
||||
[else (loop rest)])]
|
||||
[()
|
||||
;; No path
|
||||
'()]))))))))
|
||||
|
||||
;; ======================================================================
|
||||
;; Returns a string representation of the the type
|
||||
|
||||
(define (FlowType->SDL-text ftype)
|
||||
(let ([type-port (open-output-string)])
|
||||
(dynamic-let
|
||||
([pretty-print-columns (st:pretty-type-width)])
|
||||
(pretty-print (FlowType->SDL ftype) type-port))
|
||||
(begin0
|
||||
(get-output-string type-port)
|
||||
(close-output-port type-port))))
|
||||
|
||||
(define analysis-callback
|
||||
(lambda (ftype)
|
||||
(assert (FlowType? ftype) 'analysis-callback ftype)
|
||||
(pretty-debug `(analysis-callback ,(FlowType->pretty ftype)))
|
||||
(FlowType->SDL-text ftype)))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
|
||||
'(define test-hyper
|
||||
(lambda (files)
|
||||
(initialize-analysis!)
|
||||
(match-let*
|
||||
([(defs in out)
|
||||
(sba-analyze-file (files->file-thunk* files))])
|
||||
(set! global-in-env in-env)
|
||||
(set! global-out-env out-env)
|
||||
(report-unbound-vars)
|
||||
(hyper defs)
|
||||
(printf "Testing parents~n")
|
||||
(pretty-print (mapLR analysis-parents list-ftype))
|
||||
(printf "Testing analysis-shortest-path~n")
|
||||
(pretty-print (mapLR analysis-shortest-path list-ftype))
|
||||
(printf "Testing children~n")
|
||||
(pretty-print (mapLR analysis-children list-ftype list-ftype))
|
||||
(void))))
|
||||
|
||||
;; (trace analysis-parents analysis-shortest-path analysis-children)
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; zodiac-based source-correlating pretty-printer
|
||||
|
||||
'(define (correlate-pretty-print sexp)
|
||||
(let* ([p (open-output-string)]
|
||||
[_ (pretty-print sexp p)]
|
||||
[s (get-output-string p)]
|
||||
[_ (close-output-port p)]
|
||||
[p (open-input-string p)]
|
||||
[r (zodiac:read p)]
|
||||
[zexp (r)])
|
||||
(values s
|
||||
(recur loop ([sexp sexp][zexp zexp])
|
||||
(match (list sexp zexp)
|
||||
[((? list? sl) ($ zodiac:list _ s f (? list? zl)))
|
||||
(list
|
||||
(zodiac:location-offset s)
|
||||
(zodiac:location-offset f)
|
||||
(map loop sl zl))]
|
||||
[(sexp ($ zodiac:zodiac _ s f))
|
||||
(list
|
||||
(zodiac:location-offset s)
|
||||
(zodiac:location-offset f)
|
||||
sexp)])))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define analysis-get-pred-filter-list
|
||||
(lambda ()
|
||||
(cons (cons "All sources" #f)
|
||||
(reverse
|
||||
(map
|
||||
(match-lambda
|
||||
[(con . constructor) (cons (symbol->string con) (list con))])
|
||||
(append constructor-env default-constructor-env))))))
|
||||
|
||||
(define analysis-get-param
|
||||
(lambda (param)
|
||||
((eval param))))
|
||||
|
||||
(define analysis-set-param!
|
||||
(lambda (param val)
|
||||
((eval param) val)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
;; ----------
|
||||
|
||||
'(define (contains-some-same-vals? ftype value-from-ftypes)
|
||||
;; Returns #t if ftype contains at least some values from
|
||||
;; each of value-from-ftypes
|
||||
(andmap
|
||||
(lambda (value-from-ftype)
|
||||
(match (list
|
||||
(FlowType->Atype ftype)
|
||||
(FlowType->Atype value-from-ftype))
|
||||
[((? fo-Atype? x) (? fo-Atype? y)) (eq? x y)]
|
||||
[((? Tvar? x) (? Tvar? y))
|
||||
(ormap
|
||||
(lambda (AV) (memq AV (get-Tvar-objs y)))
|
||||
(get-Tvar-objs x))]
|
||||
[_ #t]))
|
||||
value-from-ftypes))
|
@ -0,0 +1,378 @@
|
||||
;; kernel-aux.ss
|
||||
;; Helper functions for building constraints
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
;;
|
||||
(define (make-constructed-AV-template template . args)
|
||||
(match-let* ( [($ template type num+ num- ref assign) template]
|
||||
[fields+ (make-vector num+)]
|
||||
[fields- (make-vector num-)])
|
||||
(for-each-with-n
|
||||
(lambda (arg n)
|
||||
(if (vector-ref assign n)
|
||||
;; Mutable - fill next two fields
|
||||
(let ([tvar (mk-Tvar 'mut-field)])
|
||||
(new-edge! arg tvar)
|
||||
(vector-set! fields- (vector-ref assign n) tvar)
|
||||
(when (vector-ref ref n)
|
||||
(vector-set! fields+ (vector-ref ref n) tvar)))
|
||||
;; Immutable - fill one field
|
||||
(when (vector-ref ref n)
|
||||
(vector-set! fields+ (vector-ref ref n) arg))))
|
||||
args)
|
||||
(create-AV template '() fields+ fields-)))
|
||||
|
||||
(define (make-constructed-AV C . args)
|
||||
(apply make-constructed-AV-template (lookup-template C) args))
|
||||
|
||||
(define (make-constructed-Tvar C . args)
|
||||
(let ([tvar (mk-Tvar 'constructed-Tvar)]
|
||||
[AV (apply make-constructed-AV C args)])
|
||||
(new-AV! tvar AV)
|
||||
tvar))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (make-AV-cons a d)
|
||||
(if (st:cons-mutable)
|
||||
(let* ( [fields+ (make-vector 2)]
|
||||
[fields- (make-vector 2)])
|
||||
(let ([tvar (mk-Tvar 'mut-field)])
|
||||
(new-edge! a tvar)
|
||||
(vector-set! fields+ 0 tvar)
|
||||
(vector-set! fields- 0 tvar))
|
||||
(let ([tvar (mk-Tvar 'mut-field)])
|
||||
(new-edge! d tvar)
|
||||
(vector-set! fields+ 1 tvar)
|
||||
(vector-set! fields- 1 tvar))
|
||||
(create-AV template-cons '() fields+ fields-))
|
||||
(create-AV template-cons '() (vector a d) (vector))))
|
||||
|
||||
|
||||
(define (make-con-car tvar) (create-con template-cons 0 tvar #t))
|
||||
(define (make-con-cdr tvar) (create-con template-cons 1 tvar #t))
|
||||
(define (make-con-dom tvar) (create-con template-lam 0 tvar #f))
|
||||
(define (make-con-rng tvar) (create-con template-lam 0 tvar #t))
|
||||
|
||||
(define (make-AV-vec a)
|
||||
(cond
|
||||
[(lookup-template 'vect)
|
||||
=>
|
||||
(lambda (template-vect)
|
||||
(make-constructed-AV-template template-vect a AV-numb))]
|
||||
[(lookup-template 'vec)
|
||||
=>
|
||||
(lambda (template-vec)
|
||||
(make-constructed-AV-template template-vec a))]))
|
||||
|
||||
(define (make-AV-lam dom rng nargs restarg)
|
||||
(create-AV
|
||||
template-lam
|
||||
(list 'lam-info nargs restarg)
|
||||
(vector rng)
|
||||
(vector dom)))
|
||||
|
||||
(define AV-nil (void))
|
||||
(define AV-numb (void))
|
||||
(define AV-sym (void))
|
||||
(define AV-str (void))
|
||||
(define AV-char (void))
|
||||
(define AV-true (void))
|
||||
(define AV-false (void))
|
||||
(define AV-void (void))
|
||||
(define AV-undefined (void))
|
||||
(define AV-top-s (void))
|
||||
|
||||
(define (mk-tvar-nil) (mk-Tvar-init-AV 'nil AV-nil))
|
||||
(define (mk-tvar-numb) (mk-Tvar-init-AV 'num AV-numb))
|
||||
(define (mk-tvar-sym) (mk-Tvar-init-AV 'sym AV-sym))
|
||||
(define (mk-tvar-str) (mk-Tvar-init-AV 'str AV-str))
|
||||
(define (mk-tvar-char) (mk-Tvar-init-AV 'char AV-char))
|
||||
(define (mk-tvar-true) (mk-Tvar-init-AV 'true AV-true))
|
||||
(define (mk-tvar-false) (mk-Tvar-init-AV 'false AV-false))
|
||||
(define (mk-tvar-empty) (mk-Tvar 'empty))
|
||||
(define (mk-tvar-void)
|
||||
(if (st:see-void)
|
||||
(mk-Tvar-init-AV 'void AV-void)
|
||||
(mk-Tvar 'void)))
|
||||
(define (mk-tvar-undefined) (mk-Tvar-init-AV 'undefined AV-undefined))
|
||||
|
||||
(define (init-common-AV!)
|
||||
(unless (template? template-nil)
|
||||
(mrspidey:internal-error
|
||||
"template-nil not a template, language probably not specified"))
|
||||
(set! AV-nil (make-constructed-AV-template template-nil))
|
||||
(set! AV-numb (make-constructed-AV-template template-num))
|
||||
(set! AV-sym (make-constructed-AV-template template-sym))
|
||||
(set! AV-str (make-constructed-AV-template template-str))
|
||||
(set! AV-char (make-constructed-AV-template template-char))
|
||||
(set! AV-true (make-constructed-AV-template template-true))
|
||||
(set! AV-false (make-constructed-AV-template template-false))
|
||||
(set! AV-void (make-constructed-AV-template template-void))
|
||||
(set! AV-undefined (make-constructed-AV-template template-undefined))
|
||||
(set! AV-top-s (make-constructed-AV-template template-top-s))
|
||||
)
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define traverse-simple-const
|
||||
;; Returns an AV, or #f
|
||||
(match-lambda
|
||||
[(or ($ zodiac:char _ _ _ c) (? char? c))
|
||||
(if (st:constants)
|
||||
(create-AV template-char c (vector) (vector))
|
||||
AV-char)]
|
||||
[(or ($ zodiac:symbol _ _ _ sym) (? symbol? sym))
|
||||
(if (st:constants)
|
||||
(create-AV template-sym sym (vector) (vector))
|
||||
AV-sym)]
|
||||
[(or ($ zodiac:number _ _ _ num) (? number? num))
|
||||
(if (st:constants)
|
||||
(create-AV template-num num (vector) (vector))
|
||||
AV-numb)]
|
||||
[(or ($ zodiac:string _ _ _ str) (? string? str)) AV-str]
|
||||
[(or ($ zodiac:boolean _ _ _ #t) #t) AV-true]
|
||||
[(or ($ zodiac:boolean _ _ _ #f) #f) AV-false]
|
||||
[(or ($ zodiac:list _ _ _ ()) ()) AV-nil]
|
||||
[_ #f]))
|
||||
|
||||
(define traverse-const-exact
|
||||
;; Returns an AV
|
||||
(lambda (V)
|
||||
(or (traverse-simple-const V)
|
||||
(match V
|
||||
[(or ($ zodiac:list _ _ _ l)
|
||||
(? pair? l)
|
||||
(? null? l))
|
||||
(recur loop ([l l])
|
||||
(match l
|
||||
[(a . d)
|
||||
(let ([tvar-a (mk-Tvar 'car)]
|
||||
[tvar-d (mk-Tvar 'cdr)])
|
||||
(new-AV! tvar-a (traverse-const-exact a))
|
||||
(new-AV! tvar-d (loop d))
|
||||
(make-AV-cons tvar-a tvar-d))]
|
||||
[() AV-nil]
|
||||
[x (traverse-const-exact x)]))]
|
||||
[($ zodiac:improper-list _ _ _ l)
|
||||
(recur loop ([l l])
|
||||
(match l
|
||||
[(x) (traverse-const-exact x)]
|
||||
[(a . d)
|
||||
(let ([tvar-a (mk-Tvar 'car)]
|
||||
[tvar-d (mk-Tvar 'cdr)])
|
||||
(new-AV! tvar-a (traverse-const-exact a))
|
||||
(new-AV! tvar-d (loop d))
|
||||
(make-AV-cons tvar-a tvar-d))]))]
|
||||
[($ zodiac:vector _ _ _ v)
|
||||
(let ([tvar-e (mk-Tvar 'vec-field)])
|
||||
(for-each
|
||||
(lambda (e) (new-AV! tvar-e (traverse-const-exact e)))
|
||||
v)
|
||||
(make-AV-vec tvar-e))]
|
||||
[(? vector? v)
|
||||
(let ([tvar-e (mk-Tvar 'vec-field)])
|
||||
(for-each
|
||||
(lambda (e) (new-AV! tvar-e (traverse-const-exact e)))
|
||||
(vector->list v))
|
||||
(make-AV-vec tvar-e))]
|
||||
[($ zodiac:box _ _ _ b)
|
||||
(let ([tvar-e (mk-Tvar 'box-field)])
|
||||
(new-AV! tvar-e (traverse-const-exact b))
|
||||
(make-constructed-AV 'box tvar-e))]
|
||||
[(? box? b)
|
||||
(let ([tvar-e (mk-Tvar 'box-field)])
|
||||
(new-AV! tvar-e (traverse-const-exact (unbox b)))
|
||||
(make-constructed-AV 'box tvar-e)) ]
|
||||
[(? void?)
|
||||
(make-constructed-AV 'void)]
|
||||
[obj (error 'traverse-const-exact "Bad const ~s" obj)]))))
|
||||
|
||||
;; ======================================================================
|
||||
;; Transitive closure of edgeto
|
||||
;; Could use faster algorithm here
|
||||
|
||||
(define (Tvar-transitive-edgeto Tvar)
|
||||
(let*-vals ( [(reached? set-reached!) (alloc-Tvar-field)]
|
||||
[edgeto '()])
|
||||
(recur loop ([Tvar Tvar])
|
||||
(unless (reached? Tvar)
|
||||
(set-reached! Tvar #t)
|
||||
(set! edgeto (cons Tvar edgeto))
|
||||
(for-each loop (Tvar-edgeto Tvar))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con-filter _ _ to) (loop to)]
|
||||
[_ (void)])
|
||||
(Tvar-constraints Tvar))))
|
||||
(pretty-debug
|
||||
`(Tvar-trans-edgeto ,(Tvar-name Tvar) ,(map Tvar-name edgeto)))
|
||||
edgeto))
|
||||
|
||||
(define (Tvar-transitive-edgefrom Tvar)
|
||||
(let*-vals ( [(reached? set-reached!) (alloc-Tvar-field)]
|
||||
[edgefrom '()])
|
||||
(recur loop ([Tvar Tvar])
|
||||
(unless (reached? Tvar)
|
||||
(set-reached! Tvar #t)
|
||||
(set! edgefrom (cons Tvar edgefrom))
|
||||
(for-each loop (Tvar-edgefrom Tvar))))
|
||||
(pretty-debug
|
||||
`(Tvar-trans-edgefrom ,(Tvar-name Tvar) ,(map Tvar-name edgefrom)))
|
||||
edgefrom))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (copy-constraint-set tvar tvar* edges)
|
||||
;; copies all Tvars in list tvar*
|
||||
;; edges: (listof (cons Tvar Tvar))
|
||||
|
||||
(pretty-debug
|
||||
`(copy-constraint-set ,(Tvar-name (car tvar*)) ,(Tvar-name (rac tvar*))))
|
||||
|
||||
(let*-vals
|
||||
( [(tvar-nutvar set-tvar-nutvar!) (alloc-Tvar-field)]
|
||||
[(AV-nuAV set-AV-nuAV!) (alloc-AV-field)]
|
||||
[Tvar->nuTvar (lambda (tvar) (or (tvar-nutvar tvar) tvar))]
|
||||
[copy-AV
|
||||
(lambda (AV)
|
||||
(or
|
||||
(AV-nuAV AV)
|
||||
(match AV
|
||||
[(and AV ($ AV _ template misc fields+ fields-))
|
||||
(if (or
|
||||
(vector-ormap tvar-nutvar fields+)
|
||||
(vector-ormap tvar-nutvar fields-))
|
||||
(let* ( [nu-AV (create-AV
|
||||
template misc
|
||||
(vector-map Tvar->nuTvar fields+)
|
||||
(vector-map Tvar->nuTvar fields-))])
|
||||
(set-AV-nuAV! AV nu-AV)
|
||||
nu-AV)
|
||||
(begin
|
||||
(set-AV-nuAV! AV AV)
|
||||
AV))])))])
|
||||
|
||||
(for-each
|
||||
(lambda (Tvar) (set-tvar-nutvar! Tvar (mk-Tvar 'copy-constraint-set)))
|
||||
tvar*)
|
||||
|
||||
(for-each
|
||||
(lambda (source)
|
||||
(let ([dest (Tvar->nuTvar source)])
|
||||
;; --- AV
|
||||
(for-each
|
||||
(lambda (AV) (new-AV! dest (copy-AV AV)))
|
||||
(Tvar-objs source))
|
||||
;; --- Constraints
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ template field-no Tvar sign)
|
||||
(new-con! dest
|
||||
(create-con template field-no (Tvar->nuTvar Tvar) sign))]
|
||||
[($ con-filter _ filter Tvar)
|
||||
(new-con! dest
|
||||
(create-con-filter filter (Tvar->nuTvar Tvar)))])
|
||||
(Tvar-constraints source))
|
||||
;; --- Edges
|
||||
(for-each
|
||||
(lambda (Tvar2) (new-edge! dest (Tvar->nuTvar Tvar2)))
|
||||
(Tvar-edgeto source))))
|
||||
tvar*)
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(from . to)
|
||||
(new-edge! (Tvar->nuTvar from) (Tvar->nuTvar to))])
|
||||
edges)
|
||||
|
||||
(Tvar->nuTvar tvar)))
|
||||
|
||||
; ======================================================================
|
||||
; Non-Terminals
|
||||
|
||||
(define-typed-structure NT (tvar type rhs*))
|
||||
|
||||
(define mk-Tvar-NTs!
|
||||
(lambda (Tvar)
|
||||
(set-Tvar-L! Tvar (make-NT Tvar 'L '()))
|
||||
(set-Tvar-U! Tvar (make-NT Tvar 'U '()))
|
||||
))
|
||||
|
||||
(define mk-AV-NTs!
|
||||
(lambda (AV)
|
||||
(set-AV-U! AV (make-NT AV 'U '()))
|
||||
))
|
||||
|
||||
(define (chk-Tvar-L tvar)
|
||||
(or (Tvar-L tvar)
|
||||
(begin
|
||||
(mk-Tvar-NTs! tvar)
|
||||
(Tvar-L tvar))))
|
||||
|
||||
(define (chk-Tvar-U tvar)
|
||||
(or (Tvar-U tvar)
|
||||
(begin
|
||||
(mk-Tvar-NTs! tvar)
|
||||
(Tvar-U tvar))))
|
||||
|
||||
(define (chk-AV-U AV)
|
||||
(or (AV-U AV)
|
||||
(begin
|
||||
(mk-AV-NTs! AV)
|
||||
(AV-U AV))))
|
||||
|
||||
(define (alloc-NT-field)
|
||||
(let* ( [table (make-hash-table)]
|
||||
[get-info
|
||||
(lambda (nt)
|
||||
(hash-table-get table nt (lambda () #f)))]
|
||||
[set-info!
|
||||
(lambda (nt v)
|
||||
(hash-table-put! table nt v))])
|
||||
(values get-info set-info!)))
|
||||
|
||||
(define nt->sym
|
||||
(match-lambda
|
||||
[($ NT x type)
|
||||
(symbol-append type ':
|
||||
(if (Tvar? x) (Tvar-name x)
|
||||
(symbol-append 'AV ': (AV-num x))))]
|
||||
[x `(BAD-NT!!!! ,x)]))
|
||||
|
||||
(define (AV->rep AV) (symbol-append 'AV ': (AV-num AV)))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define select-L
|
||||
(lambda (nt*)
|
||||
(filter-map (match-lambda [($ NT x 'L) x][_ #f]) nt*)))
|
||||
|
||||
'(define select-LI
|
||||
(lambda (nt*)
|
||||
(filter-map (match-lambda [($ NT x 'LI) x][_ #f]) nt*)))
|
||||
|
||||
(define select-U
|
||||
(lambda (nt*)
|
||||
(filter-map (match-lambda [($ NT x 'U) x][_ #f]) nt*)))
|
||||
|
||||
'(define select-UI
|
||||
(lambda (nt*)
|
||||
(filter-map (match-lambda [($ NT x 'UI) x][_ #f]) nt*)))
|
||||
|
||||
;; ======================================================================
|
@ -0,0 +1,785 @@
|
||||
;; kernel.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------=
|
||||
;; FlowType == value flow graph node
|
||||
|
||||
(define-const-typed-structure
|
||||
FlowType
|
||||
( (: num num)
|
||||
(! expr (union zodiac:parsed string false symbol))
|
||||
(! arrowto (listof FlowType))
|
||||
(! arrowfrom (listof FlowType))
|
||||
(! type-annotation any) ;; type-annotation% or file.ss (if from .za file)
|
||||
(! proplist (listof (cons sym any)))
|
||||
(! values-ftype (union false FlowType))
|
||||
))
|
||||
|
||||
(define num-ftype 0)
|
||||
(define list-ftype '())
|
||||
(define num-edge 0)
|
||||
|
||||
(define (init-FlowType!)
|
||||
(set! num-ftype 0)
|
||||
(set! list-ftype '())
|
||||
(set! num-edge 0))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
;; Extension functions
|
||||
|
||||
(define (add-FlowType-arrow! from to)
|
||||
(set-FlowType-arrowto! from (cons to (FlowType-arrowto from)))
|
||||
(set-FlowType-arrowfrom! to (cons from (FlowType-arrowfrom to))))
|
||||
|
||||
(define (add-FlowType! ftype)
|
||||
(set! num-ftype (add1 num-ftype))
|
||||
(set! list-ftype (cons ftype list-ftype))
|
||||
ftype)
|
||||
|
||||
;;------------------------------------------------------------
|
||||
;; Property list stuff
|
||||
|
||||
(define (add-FlowType-prop! ftype prop val)
|
||||
(set-FlowType-proplist! ftype
|
||||
(cons (cons prop val) (FlowType-proplist ftype))))
|
||||
|
||||
(define (get-FlowType-prop ftype prop default)
|
||||
(recur loop ([l (FlowType-proplist ftype)])
|
||||
(match l
|
||||
[() default]
|
||||
[((a . d) . rest)
|
||||
(if (eq? a prop)
|
||||
d
|
||||
(loop rest))]
|
||||
[_ default])))
|
||||
|
||||
(define (FlowType-name ftype)
|
||||
(symbol-append (get-FlowType-prop ftype 'symbol 'anon)
|
||||
':
|
||||
(FlowType-num ftype)))
|
||||
|
||||
;; ======================================================================
|
||||
;; ======================================================================
|
||||
|
||||
(define-typed-structure (Tvar struct:FlowType)
|
||||
( (: objs (listof AV))
|
||||
(: orig-objs (listof AV))
|
||||
(: constraints (listof (union con con-filter)))
|
||||
(: leq-top-s bool)
|
||||
(: edgeto (listof Tvar))
|
||||
(: edgefrom (listof Tvar))
|
||||
(: L NT)
|
||||
(: U NT)
|
||||
(: PL NT)
|
||||
(: PU NT)
|
||||
))
|
||||
|
||||
(define-const-typed-structure AV
|
||||
((: num num)
|
||||
(: template template)
|
||||
misc
|
||||
(: fields+ (vec Tvar))
|
||||
(: fields- (vec Tvar))
|
||||
(! U NT)
|
||||
(! PU any)
|
||||
wb
|
||||
))
|
||||
|
||||
(define-const-typed-structure template
|
||||
( (: type sym)
|
||||
(: num+ int)
|
||||
(: num- int)
|
||||
(: ref (vec num))
|
||||
(: assign (vec num))
|
||||
(! super-templates (listof template))
|
||||
(: misc-eq? (any -> any))))
|
||||
|
||||
;; ref and assign are for constructors
|
||||
;; ref maps a constructor-field to the AV-field+ to get value from
|
||||
;; assign maps a constructor-field to the AV-field- to add value to,
|
||||
;; or #f if immutable
|
||||
;; super-templates field records that eg num is a supertype of apply+
|
||||
;; misc-eq? is an equality function on the misc field of AVs
|
||||
;; sym-ndx maps symbols to the index for that symbol
|
||||
;; eg. map ivar names
|
||||
|
||||
|
||||
;; Each elem of AV-fields is an Tvar
|
||||
|
||||
(define-const-typed-structure con
|
||||
( (: num num)
|
||||
(: template template)
|
||||
(: field-no num)
|
||||
(: tvar Tvar)
|
||||
(: sign bool)
|
||||
misc))
|
||||
|
||||
(define-const-typed-structure con-filter
|
||||
((: num num)
|
||||
(: filter filter)
|
||||
(: tvar Tvar)))
|
||||
|
||||
(define-const-typed-structure filter
|
||||
((: sign bool)
|
||||
(: templates (listof template))))
|
||||
|
||||
(define (create-filter sign templates)
|
||||
(assert (and (boolean? sign)
|
||||
(list? templates)
|
||||
(andmap template? templates))
|
||||
'create-filter sign templates)
|
||||
(make-filter sign templates))
|
||||
|
||||
;; Says whether to include or exclude certain templates
|
||||
|
||||
(define-const-typed-structure con-top-s
|
||||
())
|
||||
|
||||
(define con-top-s (make-con-top-s))
|
||||
|
||||
(define mt-vector (vector))
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
(define num-con 0)
|
||||
(define num-AV 0)
|
||||
(define num-AV-in-Tvar 0)
|
||||
(define max-constraint-system-size 0)
|
||||
(define (constraint-system-size) (+ num-edge num-con num-AV-in-Tvar))
|
||||
|
||||
(define (SBA-entry->hash entry)
|
||||
(hash-fn (FlowType-num (car entry))
|
||||
(let ([d (cdr entry)])
|
||||
(if (Tvar? d)
|
||||
(FlowType-num d)
|
||||
(AV-num d)))))
|
||||
|
||||
(define (init-kernel!)
|
||||
(init-FlowType!)
|
||||
(set! num-con 0)
|
||||
(set! num-AV 0)
|
||||
(set! num-AV-in-Tvar 0)
|
||||
(set! max-constraint-system-size 0)
|
||||
(init-hash-table SBA-entry->hash 0)
|
||||
)
|
||||
|
||||
;;------------------------------------------------------------
|
||||
;; Creation functions
|
||||
|
||||
(define (create-AV template misc fields+ fields-)
|
||||
(assert (and
|
||||
(template? template)
|
||||
(vector? fields+)
|
||||
(vector? fields-)
|
||||
(vector-andmap Tvar? fields+)
|
||||
(vector-andmap Tvar? fields-))
|
||||
`(create-AV ,template ,misc ,fields+ ,fields-))
|
||||
(let ([AV (make-AV num-AV template misc fields+ fields- #f #f (make-weak-box 1))])
|
||||
(set! num-AV (add1 num-AV))
|
||||
AV))
|
||||
|
||||
(define mk-Tvar-nolist
|
||||
(lambda (sym)
|
||||
(let ([tvar (make-Tvar
|
||||
;; FlowType fields
|
||||
num-ftype #f '() '() #f `((symbol . ,sym)) #f
|
||||
;; Tvar fields
|
||||
'() '() '() #f '() '()
|
||||
#f #f #f #f
|
||||
)])
|
||||
(set! num-ftype (add1 num-ftype))
|
||||
tvar)))
|
||||
|
||||
(define mk-Tvar
|
||||
(lambda (sym)
|
||||
(let ([tvar (mk-Tvar-nolist sym)])
|
||||
(set! list-ftype (cons tvar list-ftype))
|
||||
tvar)))
|
||||
|
||||
(define (create-con template field-no tvar sign)
|
||||
(create-con-misc template field-no tvar sign '()))
|
||||
|
||||
(define (create-con-misc template field-no tvar sign misc)
|
||||
(make-con num-con template field-no tvar sign misc))
|
||||
|
||||
(define (create-con-filter filter tvar)
|
||||
(assert (filter? filter))
|
||||
(make-con-filter num-con filter tvar))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Functions for extending graph
|
||||
;; the add-* functions extend the data structures, but don't propogate
|
||||
;; the check-add-* only adds if item not in data structure, but don't propogate
|
||||
;; the extend-* functions also propogate values & constraints appropriately
|
||||
;; the new-* functions are normally bound to extend-*, but sometines add-*
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define add-edge!
|
||||
(lambda (from to)
|
||||
(assert (and (Tvar? from) (Tvar? to)) 'add-edge! from to)
|
||||
(set-Tvar-edgeto! from (cons to (Tvar-edgeto from)))
|
||||
(set-Tvar-edgefrom! to (cons from (Tvar-edgefrom to)))
|
||||
(set! num-edge (add1 num-edge))
|
||||
(add-entry (hash-fn (FlowType-num from) (FlowType-num to))
|
||||
(cons from to))))
|
||||
|
||||
(define add-AV!
|
||||
(lambda (tvar AV)
|
||||
(set! num-AV-in-Tvar (add1 num-AV-in-Tvar))
|
||||
(set-Tvar-objs! tvar (cons AV (Tvar-objs tvar)))
|
||||
(add-entry (hash-fn (FlowType-num tvar) (AV-num AV))
|
||||
(cons tvar AV))))
|
||||
|
||||
(define add-con!
|
||||
(lambda (tvar con)
|
||||
(set! num-con (add1 num-con))
|
||||
(set-Tvar-constraints! tvar (cons con (Tvar-constraints tvar)))))
|
||||
|
||||
'(define add-nohash-con! add-con!)
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; the check-add-* functions check if a constraint is present,
|
||||
;; and if not, add it, but do not propogate
|
||||
|
||||
(define check-add-edge!
|
||||
(lambda (from to)
|
||||
(assert (and (Tvar? from) (Tvar? to)) 'extend-edge! from to)
|
||||
(unless
|
||||
(or (Tvar-edge? from to) (eq? from to))
|
||||
(add-edge! from to))))
|
||||
|
||||
(define check-add-AV!
|
||||
(lambda (tvar AV)
|
||||
(assert (AV? AV) `(extend-AV! ,tvar ,AV))
|
||||
(set-Tvar-orig-objs! tvar (cons AV (Tvar-orig-objs tvar)))))
|
||||
|
||||
(define check-add-con!
|
||||
(lambda (tvar con)
|
||||
(set! num-con (add1 num-con))
|
||||
(set-Tvar-constraints! tvar (cons con (Tvar-constraints tvar)))
|
||||
(match con
|
||||
[($ con-filter _ _ dest)
|
||||
(set-Tvar-edgefrom! dest (cons tvar (Tvar-edgefrom dest)))]
|
||||
[_ (void)])))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; the extend-* functions also propogate values & constraints appropriately
|
||||
|
||||
(define extend-edge!
|
||||
(lambda (from to)
|
||||
(assert (and (Tvar? from) (Tvar? to)) 'extend-edge! from to)
|
||||
(unless
|
||||
(or (Tvar-edge? from to) (eq? from to))
|
||||
(add-edge! from to)
|
||||
;; Propogate all AV's
|
||||
(for-each (lambda (AV) (prop-AV! to AV))
|
||||
(Tvar-objs from)))))
|
||||
|
||||
(define extend-AV!
|
||||
(lambda (tvar AV)
|
||||
(assert (AV? AV) `(extend-AV! ,tvar ,AV))
|
||||
(set-Tvar-orig-objs! tvar (cons AV (Tvar-orig-objs tvar)))
|
||||
(prop-AV! tvar AV)))
|
||||
|
||||
(define prop-AV!
|
||||
(lambda (tvar AV)
|
||||
(assert (and (Tvar? tvar) (AV? AV)) `(prop-AV! ,tvar ,AV))
|
||||
(unless (Tvar-AV-mem? tvar AV)
|
||||
(add-AV! tvar AV)
|
||||
;; Apply all constraints
|
||||
(for-each
|
||||
(lambda (con) (SBA-constraint tvar con AV))
|
||||
(Tvar-constraints tvar))
|
||||
;; Propogate
|
||||
(for-each
|
||||
(lambda (to) (prop-AV! to AV))
|
||||
(Tvar-edgeto tvar)))))
|
||||
|
||||
(define extend-con!
|
||||
(lambda (tvar con)
|
||||
(set! num-con (add1 num-con))
|
||||
(set-Tvar-constraints! tvar (cons con (Tvar-constraints tvar)))
|
||||
(match con
|
||||
[($ con-filter _ _ dest)
|
||||
(set-Tvar-edgefrom! dest (cons tvar (Tvar-edgefrom dest)))]
|
||||
[_ (void)])
|
||||
;; Apply to all AV's
|
||||
(for-each (lambda (AV) (SBA-constraint tvar con AV))
|
||||
(get-Tvar-objs tvar))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; the new-* functions are normally equiv to extend-*,
|
||||
;; but can be set to add-* via a parameter
|
||||
|
||||
(define new-edge! extend-edge!)
|
||||
(define new-AV! extend-AV!)
|
||||
(define new-con! extend-con!)
|
||||
|
||||
(define (new-leq-top-s! tvar)
|
||||
;; tvar <= top-s, is constraint
|
||||
(unless (Tvar-leq-top-s tvar)
|
||||
(set-Tvar-leq-top-s! tvar #t)
|
||||
(new-con! tvar con-top-s)))
|
||||
|
||||
(define (new-geq-top-s! tvar)
|
||||
;; top-s <= tvar, is AV
|
||||
(new-AV! tvar AV-top-s))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define keep-S-closed
|
||||
(let ([closed #t])
|
||||
(case-lambda
|
||||
[() closed]
|
||||
[(x)
|
||||
(set! closed x)
|
||||
(if x
|
||||
(begin
|
||||
(set! new-edge! extend-edge!)
|
||||
(set! new-AV! extend-AV!)
|
||||
(set! new-con! extend-con!))
|
||||
(begin
|
||||
(set! new-edge! check-add-edge!)
|
||||
(set! new-AV! check-add-AV!)
|
||||
(set! new-con! check-add-con!)))])))
|
||||
|
||||
(define new-create-AV!
|
||||
(lambda (tvar template misc fields)
|
||||
(new-AV! tvar (create-AV template misc fields))))
|
||||
|
||||
(define new-bidir-edge!
|
||||
(lambda (from to)
|
||||
(new-edge! from to)
|
||||
(new-edge! to from)))
|
||||
|
||||
(define new-edge-para
|
||||
(case-lambda
|
||||
[() new-edge!]
|
||||
[(x) (set! new-edge! x)]))
|
||||
|
||||
(define (close-constraints tvars)
|
||||
(pretty-debug `(close-constraints ,(map Tvar-name tvars)))
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(for-each
|
||||
(lambda (AV)
|
||||
(for-each
|
||||
(lambda (to) (prop-AV! to AV))
|
||||
(Tvar-edgeto tvar))
|
||||
(for-each
|
||||
(lambda (con) (SBA-constraint tvar con AV))
|
||||
(Tvar-constraints tvar)))
|
||||
(get-Tvar-objs tvar)))
|
||||
tvars))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
;; Handling constraints
|
||||
|
||||
(define gSBA-constraint (void))
|
||||
|
||||
(define SBA-constraint
|
||||
(lambda (tvar con AV)
|
||||
(set! gSBA-constraint (list tvar con AV))
|
||||
(match con
|
||||
;; Regular constraints
|
||||
[($ con _ template field-no tvar-con sign)
|
||||
(match AV
|
||||
[($ AV _ template2 misc fields+ fields-)
|
||||
(when (or
|
||||
(eq? template template2)
|
||||
(memq template (template-super-templates template2)))
|
||||
;;(pretty-print `(,con ,AV))
|
||||
(if sign
|
||||
(when (< field-no (vector-length fields+))
|
||||
;; Propogate field from AV into tvar-con
|
||||
(new-edge! (vector-ref fields+ field-no) tvar-con))
|
||||
(when (< field-no (vector-length fields-))
|
||||
;; Propogate field from tvar-con into AV
|
||||
(new-edge! tvar-con (vector-ref fields- field-no)))))
|
||||
(when (eq? template2 template-top-s)
|
||||
(if sign
|
||||
(new-geq-top-s! tvar-con)
|
||||
(new-leq-top-s! tvar-con)))])]
|
||||
|
||||
;; Filter constraints
|
||||
[($ con-filter _ ($ filter bool templates) tvar-con)
|
||||
'(printf "template ~s templates ~s memq ~s bool ~s add ~s~n"
|
||||
(template-type (AV-template AV))
|
||||
(map template-type templates)
|
||||
(memq (AV-template AV) templates)
|
||||
bool
|
||||
(case (memq (AV-template AV) templates)
|
||||
[#f (not bool)]
|
||||
[else bool]))
|
||||
(let* ( [AV-t (AV-template AV)]
|
||||
[found (ormap
|
||||
(lambda (t2)
|
||||
(or
|
||||
(eq? AV-t t2)
|
||||
(memq t2 (template-super-templates AV-t))))
|
||||
templates)])
|
||||
'(pretty-print-debug
|
||||
`(con-filter found ,found
|
||||
memq ,(memq AV-t templates)
|
||||
AV-t ,(template-type AV-t)
|
||||
,(map template-type templates)))
|
||||
(when (or (case found
|
||||
[(#f) (not bool)]
|
||||
[else bool])
|
||||
(eq? AV-t template-top-s))
|
||||
;; Add AV to tvar-con
|
||||
(prop-AV! tvar-con AV)))]
|
||||
[($ con-top-s)
|
||||
(match AV
|
||||
[($ AV _ template2 misc fields+ fields-)
|
||||
(vector-for-each new-leq-top-s! fields+)
|
||||
(vector-for-each new-geq-top-s! fields-)])])))
|
||||
|
||||
;;------------------------------------------------------------
|
||||
;; Functions/predicates for examining the graph
|
||||
|
||||
(define (Tvar-AV-mem? tvar AV)
|
||||
(hash-find (hash-fn (FlowType-num tvar) (AV-num AV))
|
||||
(lambda (entry)
|
||||
(and (eq? (car entry) tvar)
|
||||
(eq? (cdr entry) AV)))))
|
||||
|
||||
(define (Tvar-edge? from to)
|
||||
(hash-find (hash-fn (FlowType-num from) (FlowType-num to))
|
||||
(lambda (entry)
|
||||
(and (eq? (car entry) from)
|
||||
(eq? (cdr entry) to)))))
|
||||
|
||||
(define get-Tvar-objs Tvar-objs)
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
|
||||
(define (really-check-kernel-ok)
|
||||
(dynamic-let
|
||||
([st:check-kernel #t])
|
||||
(check-kernel-ok)))
|
||||
|
||||
(define check-kernel-ok:tvar #f)
|
||||
|
||||
(define (check-kernel-ok)
|
||||
;; Sanity check
|
||||
(when (st:check-kernel)
|
||||
(assert (= num-ftype (length list-ftype)))
|
||||
(let ([Tvar-edge?
|
||||
(lambda (a b)
|
||||
(or (eq? a b)
|
||||
(Tvar-edge? a b)))])
|
||||
|
||||
(printf "check-kernel-ok: Consistency tests~n")
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(when (Tvar? tvar)
|
||||
(assert (= (length (Tvar-objs tvar))
|
||||
(length (list->set (Tvar-objs tvar)))))
|
||||
(assert (= (length (Tvar-edgeto tvar))
|
||||
(length (list->set (Tvar-edgeto tvar)))))
|
||||
(assert (= (length (Tvar-constraints tvar))
|
||||
(length (list->set (Tvar-constraints tvar)))))
|
||||
(for-each (lambda (AV) (assert (Tvar-AV-mem? tvar AV) (Tvar-name tvar)))
|
||||
(Tvar-objs tvar))
|
||||
(for-each (lambda (to) (assert (Tvar-edge? tvar to)))
|
||||
(Tvar-edgeto tvar))))
|
||||
list-ftype)
|
||||
|
||||
;; Now check kernel is closed under S
|
||||
(printf "check-kernel-ok: Closure tests~n")
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(when (Tvar? tvar)
|
||||
(for-each
|
||||
(lambda (AV)
|
||||
;; First check AV prop'd
|
||||
(for-each
|
||||
(lambda (to)
|
||||
(when (Tvar? to)
|
||||
(assert (Tvar-AV-mem? to AV)
|
||||
(Tvar-name tvar) (Tvar-name to)
|
||||
(template-type (AV-template AV)))))
|
||||
(Tvar-edgeto tvar))
|
||||
;; Check AV applied to all constraints
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ template field-no tvar-con sign)
|
||||
(match AV
|
||||
[($ AV _ template2 misc fields+ fields-)
|
||||
(when
|
||||
(or
|
||||
(eq? template template2)
|
||||
(memq template (template-super-templates template2)))
|
||||
(if sign
|
||||
(when (< field-no (vector-length fields+))
|
||||
;; Propogate field from AV into tvar-con
|
||||
(assert
|
||||
(Tvar-edge?
|
||||
(vector-ref fields+ field-no) tvar-con)
|
||||
`(Tvar-edge?
|
||||
,(Tvar-name (vector-ref fields+ field-no))
|
||||
,(Tvar-name tvar-con))
|
||||
(Tvar-name tvar) field-no
|
||||
(template-type template)))
|
||||
(when (< field-no (vector-length fields-))
|
||||
;; Propogate field from tvar-con into AV
|
||||
(assert
|
||||
(Tvar-edge?
|
||||
tvar-con (vector-ref fields- field-no))
|
||||
(Tvar-name tvar)
|
||||
field-no
|
||||
(Tvar-name tvar-con)
|
||||
sign
|
||||
(template-type template)))))]
|
||||
|
||||
[_
|
||||
;; Constraint does not apply to this AV
|
||||
(void)])]
|
||||
[($ con-filter _ ($ filter bool templates) tvar-con)
|
||||
;; ignore for now
|
||||
(void)])
|
||||
(Tvar-constraints tvar)))
|
||||
(get-Tvar-objs tvar))))
|
||||
(reverse list-ftype))
|
||||
|
||||
;; Now check all reachable tvars are in list-ftype
|
||||
(printf "check-kernel-ok: list-ftype tests~n")
|
||||
(let*-vals
|
||||
( [(get set) (alloc-Tvar-field (lambda () #f))]
|
||||
[ok-tvar? (lambda (tvar)
|
||||
(unless (get tvar)
|
||||
(printf
|
||||
"Tvar ~s reachable from ~s but not in list-ftype ~s~n"
|
||||
(FlowType-num tvar)
|
||||
(FlowType-num check-kernel-ok:tvar)
|
||||
(memq tvar list-ftype))))]
|
||||
[ok-AV?
|
||||
(match-lambda
|
||||
[($ AV _ _ _ fields+ fields-)
|
||||
(vector-for-each ok-tvar? fields+)
|
||||
(vector-for-each ok-tvar? fields-)])])
|
||||
|
||||
(for-each
|
||||
(lambda (ftype)
|
||||
(when (Tvar? ftype) (set ftype #t)))
|
||||
list-ftype)
|
||||
|
||||
(for-each
|
||||
(lambda (ftype)
|
||||
(when (Tvar? ftype)
|
||||
(set! check-kernel-ok:tvar ftype)
|
||||
(for-each ok-tvar? (Tvar-edgeto ftype))
|
||||
(for-each ok-tvar? (Tvar-edgefrom ftype))
|
||||
(for-each ok-AV? (Tvar-objs ftype))
|
||||
(for-each ok-AV? (Tvar-orig-objs ftype))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ _ _ tvar) (ok-tvar? tvar)]
|
||||
[($ con-filter _ _ tvar) (ok-tvar? tvar)])
|
||||
(Tvar-constraints ftype))))
|
||||
list-ftype))
|
||||
|
||||
)))
|
||||
|
||||
(define (check-unreachable ftypes unreachable)
|
||||
(let* ( [check-ok
|
||||
(lambda (ftype)
|
||||
(when (memq ftype unreachable)
|
||||
(error 'check-unreachable "Ftype ~s in old ~s"
|
||||
(FlowType-name ftype)
|
||||
(map FlowType-name unreachable))))])
|
||||
(for-each
|
||||
(lambda (ftype)
|
||||
(when (Tvar? ftype)
|
||||
(for-each check-ok (Tvar-edgeto ftype))
|
||||
(for-each check-ok (Tvar-edgefrom ftype))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _ _ _ fields+ fields-)
|
||||
(vector-for-each check-ok fields+)
|
||||
(vector-for-each check-ok fields-)])
|
||||
(Tvar-objs ftype))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ _ _ tvar) (check-ok tvar)]
|
||||
[($ con-filter _ _ tvar) (check-ok tvar)])
|
||||
(Tvar-constraints ftype))))
|
||||
ftypes)))
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
|
||||
(define-structure (kernel-state
|
||||
num-ftype list-ftype num-edge
|
||||
num-con num-AV num-AV-in-Tvar
|
||||
closed? new-edge! hash-table-state))
|
||||
|
||||
(define (save-kernel-state)
|
||||
(make-kernel-state
|
||||
num-ftype list-ftype num-edge
|
||||
num-con num-AV num-AV-in-Tvar
|
||||
(keep-S-closed) new-edge!
|
||||
(capture-hash-table-state)))
|
||||
|
||||
(define restore-kernel-state!
|
||||
(match-lambda
|
||||
[($ kernel-state
|
||||
saved-num-ftype saved-list-ftype saved-num-edge
|
||||
saved-num-con saved-num-AV saved-num-AV-in-Tvar
|
||||
closed? saved-new-edge!
|
||||
hash-table-state)
|
||||
(let ([old-size (constraint-system-size)])
|
||||
(set! num-ftype saved-num-ftype)
|
||||
(set! list-ftype saved-list-ftype)
|
||||
(set! num-edge saved-num-edge)
|
||||
(set! num-con saved-num-con)
|
||||
(set! num-AV saved-num-AV)
|
||||
(set! num-AV-in-Tvar saved-num-AV-in-Tvar)
|
||||
(keep-S-closed closed?)
|
||||
(set! new-edge! saved-new-edge!)
|
||||
(restore-hash-table-state! hash-table-state)
|
||||
|
||||
(set! max-constraint-system-size
|
||||
(max max-constraint-system-size
|
||||
(+ (constraint-system-size) old-size)))
|
||||
)]))
|
||||
|
||||
(define free-kernel-state!
|
||||
(match-lambda
|
||||
[($ kernel-state
|
||||
saved-num-ftype saved-list-ftype saved-num-edge
|
||||
saved-num-con saved-num-AV saved-num-AV-in-Tvar
|
||||
closed? saved-new-edge!
|
||||
hash-table-state)
|
||||
|
||||
(free-hash-table-state! hash-table-state)
|
||||
(for-each
|
||||
(lambda (ftype)
|
||||
(set-FlowType-expr! ftype 'zerod1!)
|
||||
(set-FlowType-arrowto! ftype 'zerod2!)
|
||||
(set-FlowType-arrowfrom! ftype 'zerod3!)
|
||||
(set-FlowType-type-annotation! ftype 'zerod4!)
|
||||
(set-FlowType-proplist! ftype 'zerod5!)
|
||||
(set-FlowType-values-ftype! ftype 'zerod6!)
|
||||
(when (Tvar? ftype)
|
||||
(set-Tvar-objs! ftype 'zerod7!)
|
||||
(set-Tvar-orig-objs! ftype 'zerod8!)
|
||||
(set-Tvar-constraints! ftype 'zerod9!)
|
||||
(set-Tvar-edgeto! ftype 'zeroda!)
|
||||
(set-Tvar-edgefrom! ftype 'zerodb!)
|
||||
(set-Tvar-L! ftype 'zerodc!)
|
||||
(set-Tvar-U! ftype 'zerodd!)
|
||||
(set-Tvar-PL! ftype 'zerode!)
|
||||
(set-Tvar-PU! ftype 'zerodf!)))
|
||||
saved-list-ftype)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define-structure (prompt-kernel-state saved-state prompt-hash-state ftypes))
|
||||
|
||||
(define (prompt-kernel-state)
|
||||
(make-prompt-kernel-state
|
||||
(save-kernel-state)
|
||||
(prompt-hash-table-state)
|
||||
(map
|
||||
(lambda (ftype)
|
||||
(list
|
||||
ftype
|
||||
(match ftype
|
||||
[($ FlowType _ _ arrowto arrowfrom _ _ values-ftype)
|
||||
(list arrowto arrowfrom values-ftype)])
|
||||
(match ftype
|
||||
[($ Tvar _ _ _ _ _ _ _
|
||||
objs orig-objs con edgeto edgefrom)
|
||||
(list objs orig-objs con edgeto edgefrom)]
|
||||
[_ #f])))
|
||||
list-ftype)))
|
||||
|
||||
(define unprompt-kernel-state!
|
||||
(match-lambda
|
||||
[($ prompt-kernel-state saved-state prompt-hash-state ftypes)
|
||||
(restore-kernel-state! saved-state)
|
||||
(unprompt-hash-table-state! prompt-hash-state)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(ftype (arrowto arrowfrom values-ftype) tvar-info)
|
||||
(set-FlowType-arrowto! ftype arrowto)
|
||||
(set-FlowType-arrowfrom! ftype arrowfrom)
|
||||
(set-FlowType-values-ftype! ftype values-ftype)
|
||||
(match tvar-info
|
||||
[#f (void)]
|
||||
[(objs orig-objs con edgeto edgefrom)
|
||||
(set-Tvar-objs! ftype objs)
|
||||
(set-Tvar-orig-objs! ftype orig-objs)
|
||||
(set-Tvar-constraints! ftype con)
|
||||
(set-Tvar-edgeto! ftype edgeto)
|
||||
(set-Tvar-edgefrom! ftype edgefrom)])])
|
||||
ftypes)]))
|
||||
|
||||
;; ------------------------------------------------------------
|
||||
;; Auxiliary info on Tvars
|
||||
|
||||
(define alloc-Tvar-field
|
||||
(case-lambda
|
||||
[(default-fn)
|
||||
(let* ( [table (make-hash-table)]
|
||||
[get-info
|
||||
(lambda (tvar)
|
||||
(assert (FlowType? tvar) tvar 'get-info)
|
||||
(hash-table-get table tvar default-fn))]
|
||||
[set-info!
|
||||
(lambda (tvar v)
|
||||
(assert (FlowType? tvar) tvar 'set-info!)
|
||||
(hash-table-put! table tvar v))])
|
||||
(values get-info set-info!))]
|
||||
[() (alloc-Tvar-field (lambda () #f))]))
|
||||
|
||||
(define alloc-AV-field
|
||||
(case-lambda
|
||||
[(default-fn)
|
||||
(let* ( [table (make-hash-table)]
|
||||
[get-info
|
||||
(lambda (AV)
|
||||
(hash-table-get table AV default-fn))]
|
||||
[set-info!
|
||||
(lambda (AV v)
|
||||
(hash-table-put! table AV v))])
|
||||
(values get-info set-info!))]
|
||||
[() (alloc-AV-field (lambda () #f))]))
|
||||
|
||||
(define (field->set alloc-field)
|
||||
(let*-vals ( [(get-info set-info!) (alloc-field)]
|
||||
[list-obj '()]
|
||||
[in? (lambda (obj) (get-info obj))]
|
||||
[add! (lambda (obj)
|
||||
(unless (in? obj)
|
||||
(set-info! obj #t)
|
||||
(set! list-obj (cons obj list-obj))))]
|
||||
[get-list (lambda () list-obj)])
|
||||
(values in? add! get-list)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define mk-Tvar-init-AV
|
||||
(lambda (sym AV)
|
||||
(let ([r (mk-Tvar sym)])
|
||||
(new-AV! r AV)
|
||||
r)))
|
||||
|
||||
(define (Tvar-name tvar) (FlowType-name tvar))
|
||||
|
||||
;; ======================================================================
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
||||
;; ======================================================================
|
||||
|
||||
(define (init-R4RS!)
|
||||
;; Also extends it with void
|
||||
|
||||
(apply add-default-constructor! (type: sym) (type: (listof bool)))
|
||||
(add-default-primitive! (type: (list sym sexp))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (init-Chez-on-R4RS!) (void))
|
||||
(define (init-Rice-on-Chez!) (void))
|
||||
(define (init-MzScheme-on-R4RS!) (void))
|
||||
(define (init-DrScheme-on-MzScheme!) (void))
|
||||
(define (init-smart-numops!) (void))
|
@ -0,0 +1,371 @@
|
||||
; ldexpand.ss - loads and macro expands source files
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (open-code-file filename)
|
||||
(let ([filename (normalize-path filename)]
|
||||
[cd (current-directory)])
|
||||
(dynamic-let
|
||||
([current-directory (path-only filename)])
|
||||
(unless (file-exists? filename)
|
||||
(mrspidey:error (format "Can't open file ~s, current directory ~s"
|
||||
filename (current-directory))))
|
||||
(let* ( [p (open-input-file filename 'text)]
|
||||
[p (system-expand-if-necy p)])
|
||||
p))))
|
||||
|
||||
(define (zodiac:read* port filename)
|
||||
(let* ( [default-loc (zodiac:make-location 1 1 0 filename)]
|
||||
|
||||
[reader (if (st:fake-reader)
|
||||
(fake-zodiac-reader port default-loc)
|
||||
(zodiac:read port default-loc))]
|
||||
[sexps
|
||||
(recur loop ()
|
||||
(let* ([expr (reader)])
|
||||
(if (or (zodiac:eof? expr) (eof-object? expr))
|
||||
'()
|
||||
(begin
|
||||
(when (zodiac:zodiac? expr)
|
||||
(mrspidey:zprogress "Reading"
|
||||
(zodiac:zodiac-start expr)))
|
||||
(cons expr (loop))))))])
|
||||
(unless (null? sexps)
|
||||
(mrspidey:zprogress "Reading" (zodiac:zodiac-finish (rac sexps))))
|
||||
(close-input-port port)
|
||||
(when debugging-front
|
||||
(printf "~n--Loaded file---------------------~n")
|
||||
(for-each (lambda (sexp) (pretty-print (zodiac:stripper sexp))) sexps)
|
||||
(printf "----------------------------------~n"))
|
||||
sexps))
|
||||
|
||||
(define mrspidey:zprogress
|
||||
(let ( [cur-phase '()]
|
||||
[cur-line -100]
|
||||
[cur-file ""])
|
||||
(lambda (phase loc)
|
||||
(let ( [file (zodiac:location-file loc)]
|
||||
[line (zodiac:location-line loc)])
|
||||
(unless (and
|
||||
(equal? file cur-file)
|
||||
(eq? phase cur-phase)
|
||||
;;(>= line cur-line)
|
||||
(< line (+ cur-line 10)))
|
||||
(set! cur-phase phase)
|
||||
(set! cur-line line)
|
||||
(set! cur-file file)
|
||||
(mrspidey:progress
|
||||
(format "~a ~a: "
|
||||
(padr phase 10)
|
||||
(file-name-from-path file))
|
||||
line))))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define fake-zodiac-reader
|
||||
(case-lambda
|
||||
[(p) (fake-zodiac-reader p (zodiac:make-location 1 1 0 "filename"))]
|
||||
[(p loc)
|
||||
(lambda ()
|
||||
(let ([x (read p)])
|
||||
(recur loop ([x x])
|
||||
(match x
|
||||
[(? string?) (zodiac:make-string loc loc loc x)]
|
||||
[(? boolean?) (zodiac:make-boolean loc loc loc x)]
|
||||
[(? number?) (zodiac:make-number loc loc loc x)]
|
||||
[(? symbol?) (zodiac:make-symbol loc loc loc x x x)]
|
||||
[(? char?) (zodiac:make-char loc loc loc x)]
|
||||
[(? vector?) (zodiac:make-vector loc loc loc
|
||||
(map loop (vector->list x))
|
||||
(vector-length x))]
|
||||
[(? list?) (zodiac:make-list loc loc loc
|
||||
(map loop x)
|
||||
(length x)
|
||||
'marks)]
|
||||
[(? pair?) (zodiac:make-improper-list
|
||||
loc loc loc
|
||||
(recur loop2 ([x x])
|
||||
(match x
|
||||
[(a . d) (cons (loop a) (loop2 d))]
|
||||
[r (list (loop r))]))
|
||||
0
|
||||
'period 'marks)]
|
||||
[_ (if (eof-object? x)
|
||||
(zodiac:make-eof loc)
|
||||
(mrspidey:internal-error
|
||||
'fake-zodiac-reader
|
||||
"Bad object ~s" x))]))))]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (expand-zexp->port exp)
|
||||
(let* ( [exp (zodiac:stripper exp)]
|
||||
[s (format "~s" exp)]
|
||||
[p (open-input-string s)]
|
||||
[p (system-expand-if-necy p)])
|
||||
p))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (system-expand-if-necy p)
|
||||
(if (st:system-expand)
|
||||
(system-expand-port p)
|
||||
p))
|
||||
|
||||
(define system-macros
|
||||
'(;; --- r4rs
|
||||
case cond do recur rec let* letrec let and or define
|
||||
;; --- Chez things
|
||||
parameterize fluid-let case-lambda let-values #%let-values
|
||||
;; --- Rice things
|
||||
match match-lambda match-lambda* match-let match-let*
|
||||
;; --- My things
|
||||
define-module global assert for
|
||||
;; --- Misc
|
||||
defmacro
|
||||
;; Units w/ signatures
|
||||
define-signature
|
||||
unit-with-signature unit/sig
|
||||
compound-unit/sig compound-unit-with-signature
|
||||
invoke-unit/sig invoke-unit-with-signature
|
||||
unit->unit/sig
|
||||
))
|
||||
|
||||
|
||||
(define (expander-eval e)
|
||||
(parameterize ([current-namespace expander-namespace])
|
||||
(eval e)))
|
||||
(when (st:system-expand)
|
||||
(expander-eval '(load "/home/cormac/Spidey/Code/Sba/expander-boot.ss")))
|
||||
(define (my-expand e) (expander-eval `(expand-defmacro ',e)))
|
||||
(define (my-expand-once e) (expander-eval `(expand-defmacro-once ',e)))
|
||||
|
||||
(define unchanged-list
|
||||
'( define-constructor
|
||||
define-type
|
||||
primitive:
|
||||
type:))
|
||||
|
||||
(define system-expanded-exp (void))
|
||||
|
||||
(define (system-expand-exp exp)
|
||||
(set! system-expanded-exp exp)
|
||||
(match exp
|
||||
[((? (lambda (x) (memq x unchanged-list))) . _)
|
||||
exp]
|
||||
[_ (match (my-expand exp)
|
||||
[(and e ((or '#%define-expansion-time '#%define-macro) . _))
|
||||
(expander-eval e)
|
||||
'(void)]
|
||||
[e e])]))
|
||||
|
||||
(define (remove-signature-stuff e)
|
||||
(recur loop ([e e])
|
||||
(match e
|
||||
[('#%make-unit-with-signature x _ _) (loop x)]
|
||||
[('#%verify-signed-compound-sub-units . _) '(void)]
|
||||
[('#%verify-linkage-signature-match . _) '(void)]
|
||||
[('#%unit-with-signature-unit x) x]
|
||||
[('#%invoke-open-unit expr name-specifier . imports)
|
||||
`(#%invoke-unit ,(loop expr) ,@imports)]
|
||||
[('#%invoke-open-unit expr)
|
||||
`(#%invoke-unit ,(loop expr))]
|
||||
[(('#%global-defined-value ('#%quote match:error)) . args)
|
||||
'(error 'match "Match error")]
|
||||
[(a . d) (cons (loop a) (loop d))]
|
||||
[x x])))
|
||||
|
||||
(define (system-expand-port p)
|
||||
(pretty-debug `(system-expand-port ,p ,(current-directory)))
|
||||
(let* ([o (open-output-string)])
|
||||
(parameterize
|
||||
([pretty-print-depth #f])
|
||||
(recur loop ([p p])
|
||||
(let ([e (read p)])
|
||||
(printf ".") (flush-output)
|
||||
(unless (eof-object? e)
|
||||
(recur process ([e e])
|
||||
(match (system-expand-exp e)
|
||||
[('#%begin . e*)
|
||||
(for-each process e*)]
|
||||
[e
|
||||
(let* ([e (remove-signature-stuff e)])
|
||||
(match e
|
||||
[((or 'load '#%load '#%load/cd 'load/cd) exp)
|
||||
(let ([filename (normalize-path (expander-eval exp))])
|
||||
(unless (file-exists? filename)
|
||||
(mrspidey:error (format "Can't load ~s" filename)))
|
||||
(dynamic-let
|
||||
([current-directory
|
||||
(if (memq (car e) '(load/cd #%load/cd))
|
||||
(path-only filename)
|
||||
(current-directory))])
|
||||
(let* ([p (open-input-file filename 'text)])
|
||||
(printf "[File:~s " (file-name-from-path filename))
|
||||
(loop p)
|
||||
(printf "done]")
|
||||
(close-input-port p))))]
|
||||
[('load-recent s)
|
||||
(process `(load ,(string-append s ".ss")))]
|
||||
[(or '(void) (? void?)) (void)]
|
||||
[e (pretty-print (strip-hash-percent e) o)]))]))
|
||||
(loop p)))))
|
||||
(begin0
|
||||
(open-input-string (get-output-string o))
|
||||
(close-output-port o)
|
||||
(close-input-port p))))
|
||||
|
||||
(define (strip-hash-percent expr)
|
||||
(recur loop ([expr expr])
|
||||
(match expr
|
||||
[('|#primitive| prim) prim]
|
||||
[(a . d) (cons (loop a) (loop d))]
|
||||
[(? symbol? x)
|
||||
(let* ([s (symbol->string x)]
|
||||
[l (string-length s)])
|
||||
(if (and (> l 2)
|
||||
(string=? (substring s 0 2) "#%"))
|
||||
(string->symbol (substring s 2 l))
|
||||
x))]
|
||||
[x x])))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define expand-file
|
||||
(case-lambda
|
||||
[(infile)
|
||||
(let ([infile (normalize-path infile)])
|
||||
(let ([outfile (regexp-replace ".ss$" infile ".expanded")])
|
||||
(when (eq? outfile infile)
|
||||
(error 'expand-file "Bad suffix on ~s" infile))
|
||||
(expand-file infile outfile)))]
|
||||
[(infile outfile)
|
||||
(when (file-exists? outfile) (delete-file outfile))
|
||||
(dynamic-let ( [st:system-expand #t]
|
||||
[current-directory (path-only (normalize-path infile))])
|
||||
(let* ( [p (open-input-file infile 'text)]
|
||||
[p2 (system-expand-if-necy p)]
|
||||
[p3 (open-output-file outfile 'text)])
|
||||
(printf "~nCopying:")
|
||||
(recur loop ()
|
||||
(let ([e (read p2)])
|
||||
(unless (eof-object? e)
|
||||
(pretty-print e p3)
|
||||
(printf ".") (flush-output)
|
||||
(loop))))
|
||||
(newline)
|
||||
(close-input-port p2)
|
||||
(close-output-port p3)
|
||||
outfile))]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define file-time-cache '())
|
||||
|
||||
(define (clear-file-time-cache!)
|
||||
(set! file-time-cache '()))
|
||||
|
||||
(define (extend-file-time-cache! file n)
|
||||
(set! file-time-cache (cons (cons file n) file-time-cache)))
|
||||
|
||||
(define (file-time file)
|
||||
(or (lookup-or-#f file-time-cache file)
|
||||
(let* ([n (file-modify-seconds file)])
|
||||
(unless (number? n)
|
||||
(error 'file-time "file-modify-seconds failed on ~a" file))
|
||||
(extend-file-time-cache! file n)
|
||||
n)))
|
||||
|
||||
(define (zodiac-time x)
|
||||
(let* ([start (zodiac:zodiac-start x)]
|
||||
[file (zodiac:location-file start)])
|
||||
(file-time file)))
|
||||
|
||||
(define (zodiac-time* x)
|
||||
;; ## should be either current time, or file time of any imported file
|
||||
;; is in right directory
|
||||
(let* ([t (zodiac-time x)]
|
||||
[fn (lambda (exp cl-fn)
|
||||
(match exp
|
||||
[($ zodiac:reference-unit-form _ _ _ _ file cd)
|
||||
(let*-vals
|
||||
( [_ (unless (zodiac:string? file)
|
||||
(mrspidey:error
|
||||
(format "reference-unit requires a string argument, given ~s" file)))]
|
||||
[file (zodiac:read-object file)]
|
||||
[file (if (relative-path? file)
|
||||
(build-path cd file)
|
||||
file)])
|
||||
(when (file-exists? file)
|
||||
(pretty-debug `(zodiac:time* includes ,file))
|
||||
(set! t (max t (file-time file))))
|
||||
#f)]
|
||||
[_ #f]))])
|
||||
((zodiac:compat fn) x)
|
||||
t))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define attributes #f)
|
||||
(define expander-namespace #f)
|
||||
|
||||
(define (init-expand!)
|
||||
(set! attributes (zodiac:make-attributes))
|
||||
(set! expander-namespace (make-expander-namespace)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define g:prog #f)
|
||||
|
||||
(define (my-scheme-expand-program defs)
|
||||
;;(printf "my-scheme-expand-program cd=~s~n" (cd))
|
||||
(let* ( [p (make-parameterization)]
|
||||
[_ (with-parameterization p
|
||||
(lambda ()
|
||||
(current-namespace
|
||||
expander-namespace
|
||||
;(make-expander-namespace)
|
||||
)
|
||||
(reference-library "core.ss")
|
||||
(reference-library "macro.ss")
|
||||
'(reference
|
||||
(begin-elaboration-time
|
||||
(build-path
|
||||
mred:plt-home-directory "mred" "system" "sig.ss")))
|
||||
'(eval '(unit/sig () (import mred^) 1))
|
||||
;;(printf "np=~s~n" normalize-path)
|
||||
))]
|
||||
; [defs2 (zodiac:expand-program
|
||||
; defs attributes zodiac:mrspidey-vocabulary p)]
|
||||
[defs2 (call/nal
|
||||
zodiac:expand-program/nal
|
||||
zodiac:expand-program
|
||||
(expressions: defs)
|
||||
(attributes: attributes)
|
||||
(vocabulary: zodiac:mrspidey-vocabulary))]
|
||||
; (parameterization: p))]
|
||||
[defs2 (zodiac:inline-begins defs2)]
|
||||
[_ (zodiac:initialize-mutated defs2)]
|
||||
[free (zodiac:free-vars-defs defs2)])
|
||||
(set! g:prog defs2)
|
||||
;;(pretty-print defs2)
|
||||
'(when debugging
|
||||
(pretty-print (map zodiac:stripper defs2)))
|
||||
(values defs2 free)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
@ -0,0 +1,69 @@
|
||||
;; env.ss
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Environments
|
||||
|
||||
(define empty-env '())
|
||||
|
||||
(define lookup-or-fail
|
||||
(lambda (env x fail-thunk)
|
||||
(match (assq x env)
|
||||
[#f (fail-thunk)]
|
||||
[(_ . b) b])))
|
||||
|
||||
(define lookup-or-#f
|
||||
(lambda (env x)
|
||||
(match (assq x env)
|
||||
[#f #f]
|
||||
[(_ . b) b])))
|
||||
|
||||
(define lookup
|
||||
(lambda (env x)
|
||||
(match (assq x env)
|
||||
[#f (mrspidey:internal-error 'lookup "no binding for ~a" x)]
|
||||
[(_ . b) b])))
|
||||
|
||||
(define bound-in-env?
|
||||
(lambda (env x)
|
||||
(match (assq x env)
|
||||
[#f #f]
|
||||
[_ #t])))
|
||||
|
||||
(define extend-env
|
||||
(lambda (env x v)
|
||||
(cons (cons x v) env)))
|
||||
|
||||
(define extend-env*
|
||||
(lambda (env xs vs)
|
||||
(append (map cons xs vs) env)))
|
||||
|
||||
(define join-env
|
||||
(lambda (env newenv)
|
||||
(append newenv env)))
|
||||
|
||||
(define bang-env!
|
||||
(lambda (env x nu-v)
|
||||
(let ([binding (assq x env)])
|
||||
(if binding
|
||||
(set-cdr! binding nu-v)
|
||||
(mrspidey:internal-error 'lookup "no binding for ~a" x)))))
|
||||
|
||||
(define (env:change-binding env x f err)
|
||||
(recur loop ([env env])
|
||||
(if (null? env)
|
||||
(err)
|
||||
(if (eq? x (caar env))
|
||||
(cons (cons x (f (cdar env))) (cdr env))
|
||||
(cons (car env) (loop (cdr env)))))))
|
||||
|
||||
(define (env:remove env x)
|
||||
(let* ([bind #f]
|
||||
[env
|
||||
(recur loop ([env env])
|
||||
(if (null? env)
|
||||
'()
|
||||
(if (eq? x (caar env))
|
||||
(begin
|
||||
(set! bind (cdar env))
|
||||
(cdr env))
|
||||
(cons (car env) (loop (cdr env))))))])
|
||||
(values bind env)))
|
@ -0,0 +1,247 @@
|
||||
;; library-list.ss
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
;; map from left to right
|
||||
(define mapLR
|
||||
(lambda (f l)
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y) (let ([v (f x)]) (cons v (mapLR f y)))]
|
||||
[l (error 'mapLR "Bad list ~s" l)])))
|
||||
|
||||
;; map from right to left
|
||||
(define mapRL
|
||||
(lambda (f l)
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y) (let ([v (mapRL f y)]) (cons (f x) v))])))
|
||||
|
||||
(define foldl-with-n
|
||||
(lambda (f i l)
|
||||
(recur loop ([l l][acc i][n 0])
|
||||
(match l
|
||||
[() acc]
|
||||
[(x . y) (loop y (f x n acc) (add1 n))]))))
|
||||
|
||||
;; fold for a 2-argument function
|
||||
;; right operand of f is accumulator
|
||||
(define foldr2
|
||||
(lambda (f i l1 l2)
|
||||
(recur loop ([l1 l1][l2 l2])
|
||||
(match (list l1 l2)
|
||||
[(() ()) i]
|
||||
[((x1 . y1) (x2 . y2)) (f x1 x2 (loop y1 y2))]))))
|
||||
|
||||
;; filter elements out of a list by a predicate
|
||||
(define filter
|
||||
(lambda (p l)
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y) (if (p x) (cons x (filter p y)) (filter p y))])))
|
||||
|
||||
;; filter and map left to right
|
||||
(define filter-map
|
||||
(lambda (p l)
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y)
|
||||
(match (p x)
|
||||
[#f (filter-map p y)]
|
||||
[x (cons x (filter-map p y))])])))
|
||||
|
||||
;; filter and map left to right, and return (filtered-list . unfiltered)
|
||||
|
||||
(define filter-map-split
|
||||
(lambda (p l)
|
||||
(recur loop ([done-filtered '()][done-unfiltered '()][l l])
|
||||
(match l
|
||||
[() (values done-filtered done-unfiltered)]
|
||||
[(x . y)
|
||||
(match (p x)
|
||||
[#f (loop done-filtered (cons x done-unfiltered) y)]
|
||||
[x (loop (cons x done-filtered) done-unfiltered y)])]))))
|
||||
|
||||
;; last element of a list
|
||||
(define rac
|
||||
(lambda (l)
|
||||
(match l
|
||||
[(last) last]
|
||||
[(_ . rest) (rac rest)])))
|
||||
|
||||
;; all but the last element of a list
|
||||
(define rdc
|
||||
(lambda (l)
|
||||
(match l
|
||||
[(_) '()]
|
||||
[(x . rest) (cons x (rdc rest))])))
|
||||
|
||||
;; map left to right over a list, but also pass f a 0-based index
|
||||
(define map-with-n
|
||||
(lambda (f l)
|
||||
(recur loop ([l l][n 0])
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y) (let ([v (f x n)]) (cons v (loop y (+ 1 n))))]
|
||||
[l (error 'map-with-n "Bad list ~s" l)]))))
|
||||
|
||||
;; for-each, but also pass f a 0-based index
|
||||
(define for-each-with-n
|
||||
(lambda (f l)
|
||||
(recur loop ([l l][n 0])
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y) (f x n) (loop y (+ 1 n))]))))
|
||||
|
||||
;; map on a (possibly improper) list
|
||||
(define map-ilist
|
||||
(lambda (f l)
|
||||
(recur loop ([l l])
|
||||
(match l
|
||||
[() '()]
|
||||
[(x . y) (cons (f x) (loop y))]
|
||||
[x (f x)]))))
|
||||
|
||||
;; length on a (possibly improper) list
|
||||
(define length-ilist
|
||||
(match-lambda
|
||||
[(x . y) (add1 (length-ilist y))]
|
||||
[_ 0]))
|
||||
|
||||
(define improper?
|
||||
(match-lambda
|
||||
[(x . y) (improper? y)]
|
||||
[() #f]
|
||||
[_ #t]))
|
||||
|
||||
(define (flatten-ilist l)
|
||||
(cond [(null? l) '()]
|
||||
[(pair? l) (cons (car l) (flatten-ilist (cdr l)))]
|
||||
[else (list l)]))
|
||||
|
||||
;; map a binary function down 2 lists, left to right
|
||||
(define map2
|
||||
(lambda (f a b)
|
||||
(match (cons a b)
|
||||
[(() . ())
|
||||
'()]
|
||||
[((ax . ay) . (bx . by))
|
||||
(let ([v (f ax bx)]) (cons v (map2 f ay by)))]
|
||||
[else (error 'map2 "lists differ in length")])))
|
||||
|
||||
; map over a list of lists
|
||||
|
||||
(define (mapmap f ll) (map (lambda (l) (map f l)) ll))
|
||||
|
||||
;; interate a binary function down 2 lists, left to right
|
||||
(define for-each2
|
||||
(lambda (f a b)
|
||||
(match (cons a b)
|
||||
[(() . ())
|
||||
(void)]
|
||||
[((ax . ay) . (bx . by))
|
||||
(f ax bx)
|
||||
(for-each2 f ay by)]
|
||||
[else (error 'for-each2 "lists differ in length")])))
|
||||
|
||||
;; andmap for 2 lists
|
||||
(define andmap2
|
||||
(lambda (f a b)
|
||||
(match (cons a b)
|
||||
[(() . ())
|
||||
#t]
|
||||
[((ax) . (bx))
|
||||
(f ax bx)]
|
||||
[((ax . ay) . (bx . by))
|
||||
(and (f ax bx) (andmap2 f ay by))]
|
||||
[else (error 'andmap2 "lists differ in length")])))
|
||||
|
||||
;; andmap for 2 lists, fail on inequal lengths
|
||||
(define andmap2len
|
||||
(lambda (f a b)
|
||||
(match (cons a b)
|
||||
[(() . ())
|
||||
#t]
|
||||
[((ax) . (bx))
|
||||
(f ax bx)]
|
||||
[((ax . ay) . (bx . by))
|
||||
(and (f ax bx) (andmap2len f ay by))]
|
||||
[else #f])))
|
||||
;(define andmap andmap2)
|
||||
|
||||
;; ormap for 2 lists
|
||||
(define ormap2
|
||||
(lambda (f a b)
|
||||
(match (cons a b)
|
||||
[(() . ())
|
||||
#f]
|
||||
[((ax) . (bx))
|
||||
(f ax bx)]
|
||||
[((ax . ay) . (bx . by))
|
||||
(or (f ax bx) (ormap2 f ay by))]
|
||||
[else (error 'ormap2 "lists differ in length")])))
|
||||
|
||||
;; make a list containing n copies of e
|
||||
(define list-n-copies
|
||||
(lambda (n e)
|
||||
(if (zero? n)
|
||||
'()
|
||||
(cons e (list-n-copies (sub1 n) e)))))
|
||||
|
||||
(define (count p l)
|
||||
(recur loop ([c 0][l l])
|
||||
(cond
|
||||
[(null? l) c]
|
||||
[(p (car l)) (loop (add1 c) (cdr l))]
|
||||
[else (loop c (cdr l))])))
|
||||
|
||||
(define (index l x)
|
||||
(recur loop ([l l][i 0])
|
||||
(cond
|
||||
[(null? l) #f]
|
||||
[(eq? x (car l)) i]
|
||||
[else (loop (cdr l) (add1 i))])))
|
||||
|
||||
(define (get-prefix l1 l2)
|
||||
(if (eq? l1 l2)
|
||||
'()
|
||||
(cons (car l1) (get-prefix (cdr l1) l2))))
|
||||
|
||||
(define (mklist n)
|
||||
(if (zero? n)
|
||||
'()
|
||||
(cons n (mklist (sub1 n)))))
|
||||
|
||||
(define (nth l n)
|
||||
(if (zero? n)
|
||||
(car l)
|
||||
(nth (cdr l) (sub1 n))))
|
||||
|
||||
|
||||
; Takes an atom and a list and returns the position of the atom in the list
|
||||
(define list-pos
|
||||
(lambda (a l)
|
||||
(recur loop ([l l][i 0])
|
||||
(cond
|
||||
[(null? l) #f]
|
||||
[(eqv? a (car l)) i]
|
||||
[else (loop (cdr l) (add1 i))]))))
|
||||
|
||||
; Takes an atom and a list and returns the position of the atom in the list
|
||||
; uses equal?, returns #f if no match
|
||||
(define list-pos-equal
|
||||
(lambda (a l)
|
||||
(recur loop ([l l][n 0])
|
||||
(cond
|
||||
[(null? l) #f]
|
||||
[(equal? a (car l)) n]
|
||||
[else (loop (cdr l) (add1 n))]))))
|
||||
|
||||
;; Returns first element in set satisfying a predicate, or #f
|
||||
(define (find p l)
|
||||
(recur loop ([l l])
|
||||
(cond
|
||||
[(null? l) #f]
|
||||
[(p (car l)) (car l)]
|
||||
[else (loop (cdr l))])))
|
||||
|
||||
|
@ -0,0 +1,150 @@
|
||||
; library-misc.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define symbol-append
|
||||
(lambda l
|
||||
(string->symbol
|
||||
(apply string-append (map (lambda (x) (#%format "~a" x)) l)))))
|
||||
|
||||
(define (get-cpu-time str thunk)
|
||||
(match-let
|
||||
([(t . r) (get&return-cpu-time thunk)])
|
||||
(printf "~a ~ss~n" str (/ t 1000.0))
|
||||
r))
|
||||
|
||||
(define (get&return-cpu-time thunk)
|
||||
(let* ([s1 (- (current-process-milliseconds) (current-gc-milliseconds))]
|
||||
[r (thunk)]
|
||||
[s2 (- (current-process-milliseconds) (current-gc-milliseconds))]
|
||||
[t (- s2 s1)])
|
||||
(cons t r)))
|
||||
|
||||
(define (make-timer) (cons 0 0))
|
||||
(define (clear-timer! c) (set-car! c 0) (set-cdr! c 0))
|
||||
|
||||
(define (record-time timer thunk)
|
||||
(match-let
|
||||
([(t . r) (get&return-cpu-time (lambda () (call-with-values thunk list)))])
|
||||
(set-car! timer (add1 (car timer)))
|
||||
(set-cdr! timer (+ t (cdr timer)))
|
||||
(apply #%values r)))
|
||||
|
||||
(define (strip-string s c)
|
||||
;; Strips leading chars off s, up to and including c
|
||||
(recur loop ([s (string->list s)])
|
||||
(cond
|
||||
[(null? s) ""]
|
||||
[(char=? (car s) c) (list->string (cdr s))]
|
||||
[else (loop (cdr s))])))
|
||||
|
||||
;; pad on left
|
||||
(define padl
|
||||
(lambda (arg n)
|
||||
(let ((s (format "~a" arg)))
|
||||
(recur loop ((s s))
|
||||
(if (< (string-length s) n)
|
||||
(loop (string-append " " s))
|
||||
s)))))
|
||||
|
||||
;; pad on right
|
||||
(define padr
|
||||
(lambda (arg n)
|
||||
(let ((s (format "~a" arg)))
|
||||
(recur loop ((s s))
|
||||
(if (< (string-length s) n)
|
||||
(loop (string-append s " "))
|
||||
s)))))
|
||||
|
||||
(define chop-number
|
||||
(lambda (x n)
|
||||
(substring (format "~s00000000000000000000" x) 0 (- n 1))))
|
||||
|
||||
;; Is the first string a substring of the second string?
|
||||
;;
|
||||
(define substring?
|
||||
(lambda (s1 s2)
|
||||
(let ([l1 (string-length s1)][l2 (string-length s2)])
|
||||
(let loop ([i 0])
|
||||
(cond
|
||||
[(>= (+ i l1) l2) #f]
|
||||
[(string=? (substring s2 i (+ i l1)) s1) #t]
|
||||
[else (loop (add1 i))])))))
|
||||
|
||||
; Returns the part of the string after the last slash
|
||||
;
|
||||
(define get-base-name
|
||||
(lambda (filename)
|
||||
(let ([len (string-length filename)])
|
||||
(let loop ([i 0][fname-start 0])
|
||||
(cond
|
||||
[(= i len) (substring filename fname-start len)]
|
||||
[(char=? (string-ref filename i) #\/)
|
||||
(loop (add1 i) (add1 i))]
|
||||
[else (loop (add1 i) fname-start)])))))
|
||||
|
||||
; removes an object fro a list destructively using eqv?
|
||||
;
|
||||
(define remv!
|
||||
(lambda (obj l)
|
||||
(let ([head l])
|
||||
(if (eqv? obj (car l))
|
||||
(if (pair? l)
|
||||
(cdr l)
|
||||
'())
|
||||
(let loop ([l l])
|
||||
(cond
|
||||
[(null? l) head]
|
||||
[(null? (cdr l)) head]
|
||||
[(eqv? obj (cadr l))
|
||||
(if (pair? (cdr l))
|
||||
(set-cdr! l (cddr l))
|
||||
(set-cdr! l '()))
|
||||
head]
|
||||
[ else (loop (cdr l))]))))))
|
||||
|
||||
; takes a string, a position (i) and a char and resturns a substring of the characters
|
||||
; from the position to the char
|
||||
;
|
||||
(define (char-find str i char)
|
||||
(apply string
|
||||
(let loop ([i i])
|
||||
(if (< i (string-length str))
|
||||
(let ([c (string-ref str i)])
|
||||
(if (char=? c char)
|
||||
'()
|
||||
(cons c (loop (add1 i)))))
|
||||
'()))))
|
||||
;;
|
||||
|
||||
(define (file-newer f1 f2)
|
||||
(let ([s1 (file-modify-seconds f1)]
|
||||
[s2 (file-modify-seconds f2)])
|
||||
(and (number? s1)
|
||||
(number? s2)
|
||||
(> s1 s2))))
|
||||
|
||||
|
||||
;; curried eq?
|
||||
|
||||
(define eqc?
|
||||
(lambda (x)
|
||||
(lambda (y)
|
||||
(eq? x y))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
@ -0,0 +1,71 @@
|
||||
;; library-paras.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define make-parameter-list
|
||||
(case-lambda
|
||||
[(default list-opt)
|
||||
(make-parameter-list default list-opt
|
||||
(lambda (x) (void))
|
||||
(lambda (x) #f))]
|
||||
[(default list-opt call)
|
||||
(make-parameter-list default list-opt call
|
||||
(lambda (x) #f))]
|
||||
[(default list-opt call also-ok?)
|
||||
(let* ([list-opt
|
||||
(map
|
||||
(match-lambda
|
||||
[(tag (? string? name) (? string? help)) (list tag name help)]
|
||||
[(tag (? string? name)) (list tag name "")]
|
||||
[(or (tag) (tag "") tag) (list tag (format "~a" tag) "")])
|
||||
list-opt)]
|
||||
[list-tag (map car list-opt)])
|
||||
;(assert (memq default list-tag))
|
||||
(let ([current default])
|
||||
(call current)
|
||||
(match-lambda*
|
||||
[() current]
|
||||
[('?) list-opt]
|
||||
[(x)
|
||||
(unless (or (member x list-tag) (also-ok? x))
|
||||
(error
|
||||
'parameter
|
||||
"Parameter argument ~s is not one of ~s" x list-tag))
|
||||
(set! current x)
|
||||
(call current)])))]))
|
||||
|
||||
(define (make-parameter-boolean x)
|
||||
(make-parameter-list x
|
||||
(list
|
||||
(list #f "Off" "")
|
||||
(list #t "On" ""))))
|
||||
|
||||
'(define (make-parameter-integer x)
|
||||
(make-parameter x
|
||||
(lambda (x)
|
||||
(unless (integer? x)
|
||||
(error 'parameter "Must be an integer"))
|
||||
x)))
|
||||
|
||||
(define (make-parameter-integer x)
|
||||
(unless (integer? x) (error 'parameter "Must be an integer"))
|
||||
(case-lambda
|
||||
[() x]
|
||||
[(y)
|
||||
(unless (integer? y) (error 'parameter "Must be an integer"))
|
||||
(set! x y)]))
|
@ -0,0 +1,111 @@
|
||||
;; library-set.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;;
|
||||
;; Set operations implemented by lists.
|
||||
;; Identity of elements is based on eq?.
|
||||
;; These should probably be sped up some day.
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define empty-set '())
|
||||
|
||||
(define empty-set? null?)
|
||||
|
||||
;; construct a set
|
||||
(define set
|
||||
(lambda l
|
||||
(list->set l)))
|
||||
|
||||
;; construct a set from a list by removing duplicates
|
||||
(define list->set
|
||||
(match-lambda
|
||||
[() '()]
|
||||
[(x . y) (if (memq x y)
|
||||
(list->set y)
|
||||
(cons x (list->set y)))]))
|
||||
|
||||
(define list->set-equal?
|
||||
(match-lambda
|
||||
[() '()]
|
||||
[(x . y) (if (member x y)
|
||||
(list->set y)
|
||||
(cons x (list->set y)))]))
|
||||
|
||||
;; test for membership
|
||||
(define element-of?
|
||||
(lambda (x set)
|
||||
(and (memq x set) #t)))
|
||||
|
||||
(define (set-add x set)
|
||||
(if (memq x set) set (cons x set)))
|
||||
|
||||
(define cardinality length)
|
||||
|
||||
;; does s2 contain s1?
|
||||
(define set<=
|
||||
(lambda (a b)
|
||||
(and (andmap (lambda (x) (memq x b)) a) #t)))
|
||||
|
||||
;; are two sets equal? (mutually containing)
|
||||
(define set-eq?
|
||||
(lambda (a b)
|
||||
(and (= (cardinality a) (cardinality b)) (set<= a b))))
|
||||
|
||||
;; unite two sets
|
||||
(define union2
|
||||
(lambda (a b)
|
||||
(if (null? b)
|
||||
a
|
||||
(foldr (lambda (x b)
|
||||
(if (memq x b)
|
||||
b
|
||||
(cons x b)))
|
||||
b
|
||||
a))))
|
||||
|
||||
;; unite any number of sets
|
||||
(define union
|
||||
(lambda l
|
||||
(foldr union2 '() l)))
|
||||
|
||||
(define setdiff2
|
||||
(lambda (a b)
|
||||
(if (or (null? a) (null? b))
|
||||
a
|
||||
(if (memq (car a) b)
|
||||
(setdiff2 (cdr a) b)
|
||||
(cons (car a) (setdiff2 (cdr a) b))))))
|
||||
|
||||
(define setdiff
|
||||
(lambda l
|
||||
(if (null? l)
|
||||
'()
|
||||
(setdiff2 (car l) (foldr union2 '() (cdr l))))))
|
||||
|
||||
(define intersect2
|
||||
(lambda (a b)
|
||||
(cond [(or (null? a) (null? b)) '()]
|
||||
[(memq (car b) a) (cons (car b) (intersect2 a (cdr b)))]
|
||||
[else (intersect2 a (cdr b))])))
|
||||
|
||||
(define intersect
|
||||
(lambda l
|
||||
(if (null? l)
|
||||
'()
|
||||
(foldl intersect2 (car l) l))))
|
||||
|
||||
|
@ -0,0 +1,106 @@
|
||||
;; library-vec.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (vector-copy v)
|
||||
(let* ( [l (vector-length v)]
|
||||
[w (make-vector l)])
|
||||
(for i 0 l (vector-set! w i (vector-ref v i)))
|
||||
w))
|
||||
|
||||
;; vector map
|
||||
(define vector-map1
|
||||
(lambda (f v)
|
||||
(let* ([l (vector-length v)]
|
||||
[w (make-vector l)])
|
||||
(for i 0 l
|
||||
(vector-set! w i (f (vector-ref v i))))
|
||||
w)))
|
||||
|
||||
(define vector-map2
|
||||
(lambda (f v1 v2)
|
||||
(let* ([l (vector-length v1)]
|
||||
[w (make-vector l)])
|
||||
(assert (= l (vector-length v2)))
|
||||
(for i 0 l
|
||||
(vector-set! w i (f (vector-ref v1 i) (vector-ref v2 i))))
|
||||
w)))
|
||||
|
||||
(define vector-map
|
||||
(case-lambda
|
||||
[(f v) (vector-map1 f v)]
|
||||
[(f v1 v2) (vector-map2 f v1 v2)]))
|
||||
|
||||
;; for-each over a vector, but also pass f a 0-based index
|
||||
(define vector-for-each-with-n
|
||||
(lambda (f v)
|
||||
(for i 0 (vector-length v)
|
||||
(f (vector-ref v i) i))))
|
||||
|
||||
(define vector-for-each
|
||||
(case-lambda
|
||||
[(f v)
|
||||
(for i 0 (vector-length v)
|
||||
(f (vector-ref v i)))]
|
||||
[(f v1 v2)
|
||||
(assert (= (vector-length v1) (vector-length v2)) 'vector-for-each)
|
||||
(for i 0 (vector-length v1)
|
||||
(f (vector-ref v1 i) (vector-ref v2 i)))]))
|
||||
|
||||
(define (vector-andmap1 f v)
|
||||
(let ([l (vector-length v)])
|
||||
(recur loop ([i 0])
|
||||
(or (= i l)
|
||||
(and (f (vector-ref v i)) (loop (add1 i)))))))
|
||||
|
||||
(define (vector-andmap2 f v1 v2)
|
||||
(let ([l (vector-length v1)])
|
||||
(assert (= l (vector-length v2)))
|
||||
(recur loop ([i 0])
|
||||
(or (= i l)
|
||||
(and (f (vector-ref v1 i) (vector-ref v2 i))
|
||||
(loop (add1 i)))))))
|
||||
|
||||
(define vector-andmap
|
||||
(match-lambda*
|
||||
[(f v) (vector-andmap1 f v)]
|
||||
[(f v1 v2) (vector-andmap2 f v1 v2)]))
|
||||
|
||||
|
||||
(define (vector-ormap1 f v)
|
||||
(let ([l (vector-length v)])
|
||||
(recur loop ([i 0])
|
||||
(and (not (= i l))
|
||||
(or (f (vector-ref v i)) (loop (add1 i)))))))
|
||||
|
||||
(define (vector-ormap2 f v1 v2)
|
||||
(let ([l (vector-length v1)])
|
||||
(assert (= l (vector-length v2)))
|
||||
(recur loop ([i 0])
|
||||
(and (not (= i l))
|
||||
(or (f (vector-ref v1 i) (vector-ref v2 i))
|
||||
(loop (add1 i)))))))
|
||||
|
||||
(define vector-ormap
|
||||
(match-lambda*
|
||||
[(f v) (vector-ormap1 f v)]
|
||||
[(f v1 v2) (vector-ormap2 f v1 v2)]))
|
||||
|
||||
|
||||
(define (vector-zero! p)
|
||||
(for i 0 (vector-length p) (vector-set! p i 'zerod!)))
|
@ -0,0 +1,29 @@
|
||||
;; Sba/lib/main.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;; elaboration-time context:
|
||||
;; mrspidey signatures
|
||||
|
||||
(unit/sig mrspidey:library^
|
||||
(import mrspidey:interaction^ mzlib:unprefixed-core^)
|
||||
(include "lib-para.ss")
|
||||
(include "lib-list.ss")
|
||||
(include "lib-vec.ss")
|
||||
(include "lib-set.ss")
|
||||
(include "lib-misc.ss")
|
||||
(include "env.ss"))
|
@ -0,0 +1,132 @@
|
||||
;; link.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define mrspidey:sba@
|
||||
(compound-unit/sig
|
||||
(import
|
||||
(INTERACTION : mrspidey:interaction^)
|
||||
(MZLIB : mzlib:unprefixed-core^)
|
||||
(WX : wx^)
|
||||
)
|
||||
(link
|
||||
[CDL :
|
||||
mrspidey:CDL^
|
||||
(mrspidey:CDL@ INTERACTION MZLIB WX)]
|
||||
[ZODIAC :
|
||||
mrspidey:zodiac^
|
||||
(mrspidey:zodiac@ CDL INTERACTION)]
|
||||
[LOADEXPAND :
|
||||
mrspidey:loadexpand^
|
||||
(mrspidey:loadexpand@ CDL INTERACTION LANGUAGES ZODIAC MZLIB)]
|
||||
[HASH :
|
||||
mrspidey:hash^
|
||||
(mrspidey:hash@ CDL INTERACTION MZLIB)]
|
||||
[KERNEL :
|
||||
mrspidey:kernel^
|
||||
(mrspidey:kernel@ CDL HASH KERNEL-AUX TEMPLATES)]
|
||||
[MIN :
|
||||
mrspidey:min^
|
||||
(mrspidey:all-min@ CDL INTERACTION KERNEL KERNEL-AUX
|
||||
TEMPLATES MZLIB)]
|
||||
[TEMPLATES :
|
||||
mrspidey:templates^
|
||||
(mrspidey:templates@ CDL INTERACTION KERNEL)]
|
||||
[KERNEL-AUX :
|
||||
mrspidey:kernel-aux^
|
||||
(mrspidey:kernel-aux@ CDL INTERACTION KERNEL TEMPLATES ZODIAC)]
|
||||
[ATYPE :
|
||||
mrspidey:atype^
|
||||
(mrspidey:atype@ CDL INTERACTION KERNEL KERNEL-AUX
|
||||
MIN TYPELANG TEMPLATES
|
||||
TYPE-ENV SDL ATLUNIT MZLIB)]
|
||||
[TYPELANG :
|
||||
mrspidey:typelang^
|
||||
(mrspidey:typelang@ CDL INTERACTION KERNEL KERNEL-AUX
|
||||
TEMPLATES TYPE-ENV ATYPE CONTAINED MZLIB ZODIAC)]
|
||||
[CONTAINED :
|
||||
mrspidey:contained^
|
||||
(mrspidey:contained@ CDL KERNEL SDL)]
|
||||
[TYPE-ENV :
|
||||
mrspidey:type-env^
|
||||
(mrspidey:type-env@ CDL INTERACTION KERNEL KERNEL-AUX
|
||||
TEMPLATES MIN ATYPE ZODIAC)]
|
||||
[SDL :
|
||||
mrspidey:sdl^
|
||||
(mrspidey:sdl@
|
||||
CDL KERNEL MIN TYPELANG KERNEL-AUX TEMPLATES ATYPE
|
||||
MZLIB)]
|
||||
[LANGUAGES :
|
||||
mrspidey:languages^
|
||||
(mrspidey:languages@ CDL INTERACTION KERNEL
|
||||
TEMPLATES KERNEL-AUX
|
||||
ATYPE TYPE-ENV TYPELANG ATENV LOADEXPAND TRAVERSE
|
||||
MZLIB ZODIAC )]
|
||||
[ATENV :
|
||||
mrspidey:atenv^
|
||||
(mrspidey:atenv@ CDL INTERACTION KERNEL KERNEL-AUX ATYPE
|
||||
ZODIAC MZLIB)]
|
||||
[TRAVERSE :
|
||||
mrspidey:traverse^
|
||||
(mrspidey:traverse@ CDL INTERACTION KERNEL MIN
|
||||
LOADEXPAND
|
||||
TEMPLATES KERNEL-AUX TYPELANG TYPE-ENV
|
||||
LANGUAGES ATYPE ATLUNIT ATENV
|
||||
ZODIAC MZLIB)]
|
||||
[ATLUNIT :
|
||||
mrspidey:atlunit^
|
||||
(mrspidey:atlunit@ CDL INTERACTION KERNEL KERNEL-AUX
|
||||
MIN LOADEXPAND TYPE-ENV
|
||||
TEMPLATES LANGUAGES ATYPE ATENV TRAVERSE
|
||||
ZA ZODIAC MZLIB WX)]
|
||||
[ZA :
|
||||
mrspidey:za^
|
||||
(mrspidey:za@ CDL INTERACTION KERNEL TEMPLATES
|
||||
TYPE-ENV TYPELANG ATYPE MZLIB)]
|
||||
[PROGRAM :
|
||||
mrspidey:program^
|
||||
(mrspidey:program@ CDL INTERACTION
|
||||
KERNEL KERNEL-AUX TYPE-ENV
|
||||
LOADEXPAND TRAVERSE
|
||||
TEMPLATES ATENV ATYPE LANGUAGES
|
||||
ZODIAC MZLIB)]
|
||||
[CHECKS :
|
||||
mrspidey:calc-checks^
|
||||
(mrspidey:calc-checks@ CDL INTERACTION LOADEXPAND
|
||||
KERNEL KERNEL-AUX
|
||||
TYPELANG TEMPLATES ATYPE SDL
|
||||
ZODIAC MZLIB)]
|
||||
[DRIVER :
|
||||
mrspidey:driver^
|
||||
(mrspidey:driver@ CDL INTERACTION KERNEL
|
||||
TEMPLATES TYPELANG TYPE-ENV ATYPE ATENV
|
||||
PROGRAM CHECKS LANGUAGES ZODIAC)]
|
||||
[HYPER :
|
||||
mrspidey:hyper^
|
||||
(mrspidey:hyper@ CDL INTERACTION LOADEXPAND
|
||||
PROGRAM CHECKS TEMPLATES KERNEL KERNEL-AUX ATYPE MZLIB)]
|
||||
)
|
||||
(export
|
||||
(open DRIVER)
|
||||
(open CDL)
|
||||
(open ATYPE)
|
||||
(open HYPER)
|
||||
(open KERNEL)
|
||||
(open CHECKS)
|
||||
(open LANGUAGES)
|
||||
(unit ZODIAC zodiac))))
|
||||
|
@ -0,0 +1,92 @@
|
||||
;; Sba/load.ss
|
||||
;; Loads analysis, assumes zodiac, ../aux.ss, ../macros.ss already loaded
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(load-relative "sigs.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Library stuff
|
||||
|
||||
(load-relative (build-path "lib" "lib-para.ss"))
|
||||
(load-relative (build-path "lib" "lib-list.ss"))
|
||||
(load-relative (build-path "lib" "lib-vec.ss"))
|
||||
(load-relative (build-path "lib" "lib-set.ss"))
|
||||
(load-relative (build-path "lib" "lib-misc.ss"))
|
||||
(load-relative (build-path "lib" "env.ss"))
|
||||
(load-relative "config.ss")
|
||||
(load-relative "debug.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Extended Zodiac
|
||||
|
||||
(load-relative "zod-extra.ss")
|
||||
(invoke-open-unit/sig
|
||||
mrspidey:zodiac@
|
||||
zodiac
|
||||
mrspidey:CDL^ mrspidey:interaction^)
|
||||
|
||||
;; ---------------------------------------------------------------------
|
||||
;; Front End Stuff
|
||||
|
||||
(load-relative "ldexpand.ss")
|
||||
|
||||
;; ======================================================================
|
||||
;; Kernel stuff
|
||||
|
||||
(load-relative "hash.ss")
|
||||
(load-relative "kernel.ss")
|
||||
(load-relative (build-path "min" "min.ss"))
|
||||
(load-relative (build-path "min" "nonempty.ss"))
|
||||
(load-relative (build-path "min" "min-live.ss"))
|
||||
(load-relative (build-path "min" "livefewe.ss"))
|
||||
(load-relative (build-path "min" "hopcroft.ss"))
|
||||
(load-relative (build-path "min" "min-dfa.ss"))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; top level stuff
|
||||
|
||||
(load-relative "template.ss")
|
||||
(load-relative "kern-aux.ss")
|
||||
(load-relative "typelang.ss")
|
||||
(load-relative "contain.ss")
|
||||
(load-relative "type-env.ss")
|
||||
(load-relative "sdl.ss")
|
||||
(load-relative "language.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Traversal
|
||||
|
||||
(load-relative "atype.ss")
|
||||
(load-relative "atenv.ss")
|
||||
(load-relative "atlunit.ss")
|
||||
(load-relative "traverse.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(load-relative "za.ss")
|
||||
(load-relative "program.ss")
|
||||
(load-relative "checks.ss")
|
||||
(load-relative "driver.ss")
|
||||
(load-relative "results.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (t) (st: "../test/t.ss"))
|
||||
;(load "test-sba.ss")
|
||||
;(load "devel.ss")
|
||||
;(load "poly.ss")
|
@ -0,0 +1,489 @@
|
||||
;; sba-unit.ss
|
||||
;; Defines all the units in SBA
|
||||
;; ----------------------------------------------------------------------
|
||||
;; elaboration-time context:
|
||||
;; sparams.ss Spidey/Code/macros.ss
|
||||
|
||||
(load-relative "sigs.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Library
|
||||
|
||||
(define mrspidey:library@
|
||||
(reference (build-path "lib" "main.ss")))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define mrspidey:config@
|
||||
(unit/sig mrspidey:config^
|
||||
(import mrspidey:library^ mzlib:unprefixed-core^ [wx : wx^])
|
||||
(include "config.ss")))
|
||||
|
||||
(define mrspidey:debugging@
|
||||
(unit/sig mrspidey:debugging^
|
||||
(import
|
||||
mrspidey:library^
|
||||
mzlib:unprefixed-core^)
|
||||
(include "debug.ss")))
|
||||
|
||||
(define mrspidey:CDL@
|
||||
(compound-unit/sig
|
||||
(import
|
||||
(I : mrspidey:interaction^)
|
||||
(MZLIB : mzlib:unprefixed-core^)
|
||||
(WX : wx^))
|
||||
(link
|
||||
[L :
|
||||
mrspidey:library^
|
||||
(mrspidey:library@ I MZLIB)]
|
||||
[C :
|
||||
mrspidey:config^
|
||||
(mrspidey:config@ L MZLIB WX)]
|
||||
[D :
|
||||
mrspidey:debugging^
|
||||
(mrspidey:debugging@ L MZLIB)])
|
||||
(export (open C) (open D) (open L))))
|
||||
|
||||
;; ---------------------------------------------------------------------
|
||||
;; Front End Stuff
|
||||
|
||||
(define mrspidey:loadexpand@
|
||||
(unit/sig mrspidey:loadexpand^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:languages^
|
||||
(zodiac : mrspidey:zodiac^)
|
||||
mzlib:unprefixed-core^)
|
||||
(include "ldexpand.ss")))
|
||||
|
||||
;; ======================================================================
|
||||
;; Kernel stuff
|
||||
|
||||
(define mrspidey:hash@
|
||||
(unit/sig mrspidey:hash^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mzlib:unprefixed-core^)
|
||||
(include "hash.ss")))
|
||||
|
||||
(define mrspidey:kernel@
|
||||
(unit/sig mrspidey:kernel^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:hash^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:templates^)
|
||||
(include "kernel.ss")))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Minimization
|
||||
|
||||
(define mrspidey:min-live@
|
||||
(unit/sig
|
||||
mrspidey:min-live^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:templates^)
|
||||
(include (begin-elaboration-time (build-path "min" "min-live.ss")))))
|
||||
|
||||
(define mrspidey:find-nonempty-tvars@
|
||||
(unit/sig
|
||||
mrspidey:find-nonempty-tvars^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min-live^
|
||||
mrspidey:templates^)
|
||||
(include (begin-elaboration-time (build-path "min" "nonempty.ss")))))
|
||||
|
||||
(define mrspidey:min-live-few-e@
|
||||
(unit/sig
|
||||
mrspidey:min-live-few-e^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:min-live^)
|
||||
(include (begin-elaboration-time (build-path "min" "livefewe.ss")))))
|
||||
|
||||
(define mrspidey:hopcroft@
|
||||
(unit/sig
|
||||
mrspidey:hopcroft^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mzlib:unprefixed-core^
|
||||
mrspidey:min^)
|
||||
(include (begin-elaboration-time (build-path "min" "hopcroft.ss")))))
|
||||
|
||||
'(define-signature mrspidey:min-dfa^ (minimize-constraints-dfa-min))
|
||||
'(mrspidey:load-unit "min/" min-dfa-old ( mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:find-nonempty-tvars^
|
||||
mrspidey:min-live^
|
||||
mrspidey:hopcroft^))
|
||||
|
||||
'(define-signature mrspidey:min-dfa-inv^ (minimize-constraints-dfa-min-inv))
|
||||
'(mrspidey:load-unit "min/" min-dfa-inv ( mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:min-live^
|
||||
mrspidey:hopcroft^))
|
||||
|
||||
'(define-signature mrspidey:min-dfa-strange ( minimize-constraints-dfa-min-1
|
||||
minimize-constraints-dfa-min-2))
|
||||
'(mrspidey:load-unit "min/" min-dfa-strange ( mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min-live^
|
||||
mrspidey:hopcroft^))
|
||||
|
||||
(define mrspidey:min-dfa-fast@
|
||||
(unit/sig
|
||||
mrspidey:min-dfa-fast^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:min-live^
|
||||
mrspidey:min-live-few-e^
|
||||
mrspidey:hopcroft^)
|
||||
(include (begin-elaboration-time (build-path "min" "min-dfa.ss")))))
|
||||
|
||||
(define mrspidey:min@
|
||||
(unit/sig
|
||||
mrspidey:min^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:find-nonempty-tvars^
|
||||
mrspidey:min-live^
|
||||
mrspidey:min-live-few-e^
|
||||
;mrspidey:min-dfa^
|
||||
;mrspidey:min-dfa-inv^
|
||||
;mrspidey:min-dfa-strange^
|
||||
mrspidey:min-dfa-fast^
|
||||
)
|
||||
(include (begin-elaboration-time (build-path "min" "min.ss")))
|
||||
(define minimize-constraints-dfa-min 1)
|
||||
(define minimize-constraints-dfa-min-inv 1)
|
||||
(define minimize-constraints-dfa-min-1 1)
|
||||
(define minimize-constraints-dfa-min-2 1)
|
||||
(define min-table 1)
|
||||
))
|
||||
|
||||
(define mrspidey:all-min@
|
||||
(compound-unit/sig
|
||||
(import
|
||||
(CDL : mrspidey:CDL^)
|
||||
(INTERACTION : mrspidey:interaction^)
|
||||
(KERNEL : mrspidey:kernel^)
|
||||
(KERNEL-AUX : mrspidey:kernel-aux^)
|
||||
(TEMPLATES : mrspidey:templates^)
|
||||
(MZLIB : mzlib:unprefixed-core^)
|
||||
)
|
||||
(link
|
||||
[MIN : mrspidey:min^
|
||||
(mrspidey:min@ CDL INTERACTION KERNEL
|
||||
FIND LIVE FEW FAST)]
|
||||
[FIND : mrspidey:find-nonempty-tvars^
|
||||
(mrspidey:find-nonempty-tvars@ CDL KERNEL KERNEL-AUX LIVE TEMPLATES)]
|
||||
[LIVE : mrspidey:min-live^
|
||||
(mrspidey:min-live@ CDL KERNEL KERNEL-AUX MIN TEMPLATES)]
|
||||
[FEW : mrspidey:min-live-few-e^
|
||||
(mrspidey:min-live-few-e@ CDL KERNEL KERNEL-AUX MIN LIVE)]
|
||||
[HOPCROFT : mrspidey:hopcroft^
|
||||
(mrspidey:hopcroft@ CDL MZLIB MIN)]
|
||||
;;[DFA : mrspidey:min-dfa^
|
||||
;; (mrspidey:min-dfa@ CDL KERNEL KERNEL-AUX LIVE HOPCROFT)]
|
||||
;;[INV : mrspidey:min-dfa-inv^
|
||||
;; (mrspidey:min-dfa-inv@ CDL KERNEL KERNEL-AUX LIVE HOPCROFT)]
|
||||
;;[STRANGE : mrspidey:min-dfa-strange^
|
||||
;; (mrspidey:min-dfa-strange^@ CDL KERNEL KERNEL-AUX LIVE HOPCROFT)]
|
||||
[FAST : mrspidey:min-dfa-fast^
|
||||
(mrspidey:min-dfa-fast@ CDL KERNEL KERNEL-AUX MIN LIVE FEW HOPCROFT)])
|
||||
(export (open MIN))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; top level stuff
|
||||
|
||||
(define mrspidey:templates@
|
||||
(unit/sig
|
||||
mrspidey:templates^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^)
|
||||
(include "template.ss")))
|
||||
|
||||
(define mrspidey:kernel-aux@
|
||||
(unit/sig
|
||||
mrspidey:kernel-aux^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:templates^
|
||||
(zodiac : mrspidey:zodiac^))
|
||||
(include "kern-aux.ss")))
|
||||
|
||||
(define mrspidey:typelang@
|
||||
(unit/sig
|
||||
mrspidey:typelang^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:templates^
|
||||
mrspidey:type-env^
|
||||
mrspidey:atype^
|
||||
mrspidey:contained^
|
||||
mzlib:unprefixed-core^
|
||||
(zodiac : mrspidey:zodiac^))
|
||||
(include "typelang.ss")))
|
||||
|
||||
(define mrspidey:contained@
|
||||
(unit/sig
|
||||
mrspidey:contained^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:sdl^)
|
||||
(include "contain.ss")))
|
||||
|
||||
(define mrspidey:type-env@
|
||||
(unit/sig
|
||||
mrspidey:type-env^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:templates^
|
||||
mrspidey:min^
|
||||
mrspidey:atype^
|
||||
(zodiac : mrspidey:zodiac^))
|
||||
(include "type-env.ss")))
|
||||
|
||||
(define mrspidey:sdl@
|
||||
(unit/sig
|
||||
mrspidey:sdl^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:kernel^
|
||||
mrspidey:min^
|
||||
mrspidey:typelang^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:templates^
|
||||
mrspidey:atype^
|
||||
mzlib:unprefixed-core^)
|
||||
(include "sdl.ss")))
|
||||
|
||||
(define mrspidey:languages@
|
||||
(unit/sig
|
||||
mrspidey:languages^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:templates^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:atype^
|
||||
mrspidey:type-env^
|
||||
mrspidey:typelang^
|
||||
mrspidey:atenv^
|
||||
mrspidey:loadexpand^
|
||||
mrspidey:traverse^
|
||||
mzlib:unprefixed-core^
|
||||
(zodiac : mrspidey:zodiac^))
|
||||
(include "language.ss")))
|
||||
|
||||
(define mrspidey:za@
|
||||
(unit/sig
|
||||
mrspidey:za^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:templates^
|
||||
mrspidey:type-env^
|
||||
mrspidey:typelang^
|
||||
mrspidey:atype^
|
||||
mzlib:unprefixed-core^)
|
||||
(include "za.ss")))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Traversal
|
||||
|
||||
(define mrspidey:atype@
|
||||
(unit/sig
|
||||
mrspidey:atype^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:typelang^
|
||||
mrspidey:templates^
|
||||
mrspidey:type-env^
|
||||
mrspidey:sdl^
|
||||
mrspidey:atlunit^
|
||||
mzlib:unprefixed-core^)
|
||||
(include "atype.ss")))
|
||||
|
||||
(define mrspidey:atenv@
|
||||
(unit/sig
|
||||
mrspidey:atenv^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:atype^
|
||||
(zodiac : mrspidey:zodiac^)
|
||||
mzlib:unprefixed-core^)
|
||||
(include "atenv.ss")))
|
||||
|
||||
(define mrspidey:atlunit@
|
||||
(unit/sig
|
||||
mrspidey:atlunit^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:min^
|
||||
mrspidey:loadexpand^
|
||||
mrspidey:type-env^
|
||||
mrspidey:templates^
|
||||
mrspidey:languages^
|
||||
mrspidey:atype^
|
||||
mrspidey:atenv^
|
||||
mrspidey:traverse^
|
||||
mrspidey:za^
|
||||
(zodiac : mrspidey:zodiac^)
|
||||
mzlib:unprefixed-core^
|
||||
[wx : wx^])
|
||||
(include "atlunit.ss")))
|
||||
|
||||
(define mrspidey:traverse@
|
||||
(unit/sig
|
||||
mrspidey:traverse^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:min^
|
||||
mrspidey:loadexpand^
|
||||
mrspidey:templates^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:typelang^
|
||||
mrspidey:type-env^
|
||||
mrspidey:languages^
|
||||
mrspidey:atype^
|
||||
mrspidey:atlunit^
|
||||
mrspidey:atenv^
|
||||
(zodiac : mrspidey:zodiac^)
|
||||
mzlib:unprefixed-core^)
|
||||
(include "traverse.ss")))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define mrspidey:program@
|
||||
(unit/sig
|
||||
mrspidey:program^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:type-env^
|
||||
mrspidey:loadexpand^
|
||||
mrspidey:traverse^
|
||||
mrspidey:templates^
|
||||
mrspidey:atenv^
|
||||
mrspidey:atype^
|
||||
mrspidey:languages^
|
||||
(zodiac : mrspidey:zodiac^)
|
||||
mzlib:unprefixed-core^)
|
||||
(include "program.ss")))
|
||||
|
||||
(define mrspidey:calc-checks@
|
||||
(unit/sig
|
||||
mrspidey:calc-checks^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:loadexpand^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:typelang^
|
||||
mrspidey:templates^
|
||||
mrspidey:atype^
|
||||
mrspidey:sdl^
|
||||
(zodiac : mrspidey:zodiac^)
|
||||
mzlib:unprefixed-core^)
|
||||
(include "checks.ss")))
|
||||
|
||||
(define mrspidey:driver@
|
||||
(unit/sig
|
||||
mrspidey:driver^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:kernel^
|
||||
mrspidey:templates^
|
||||
mrspidey:typelang^
|
||||
mrspidey:type-env^
|
||||
mrspidey:atype^
|
||||
mrspidey:atenv^
|
||||
mrspidey:program^
|
||||
mrspidey:calc-checks^
|
||||
mrspidey:languages^
|
||||
(zodiac : mrspidey:zodiac^))
|
||||
(include "driver.ss")))
|
||||
|
||||
(define mrspidey:hyper@
|
||||
(unit/sig
|
||||
mrspidey:hyper^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
mrspidey:interaction^
|
||||
mrspidey:loadexpand^
|
||||
mrspidey:program^
|
||||
mrspidey:calc-checks^
|
||||
mrspidey:templates^
|
||||
mrspidey:kernel^
|
||||
mrspidey:kernel-aux^
|
||||
mrspidey:atype^
|
||||
mzlib:unprefixed-core^)
|
||||
(include "hyper.ss")))
|
||||
|
||||
(load-relative "zod-extra.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Put it all together
|
||||
|
||||
(load-relative "link.ss")
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
|
||||
(define src "/home/mflatt/proj/mred/mzscheme/src/exnsrc.ss")
|
||||
(define dest "/home/cormac/plt/mrspidey/Sba/exn-hierarchy.ss")
|
||||
(when (file-exists? dest) (delete-file dest))
|
||||
|
||||
(with-input-from-file src
|
||||
(lambda ()
|
||||
(let ([x (read)])
|
||||
(with-output-to-file dest
|
||||
(lambda ()
|
||||
(letrec
|
||||
([trav
|
||||
(lambda (tree parent)
|
||||
(match tree
|
||||
[(name fields+strings . subtrees)
|
||||
(let* ( [fields (filter symbol? fields+strings)]
|
||||
[s (symbol->string name)]
|
||||
[name (if (memq (string-ref s 0) '(#\* #\+))
|
||||
(string->symbol
|
||||
(substring s 1 (string-length s)))
|
||||
name)]
|
||||
[name (if parent (symbol-append parent ': name) name)])
|
||||
(display
|
||||
`(define-struct
|
||||
,(if parent
|
||||
`(,name ,(symbol-append 'struct: parent))
|
||||
name)
|
||||
,fields))
|
||||
(newline)
|
||||
(for-each
|
||||
(lambda (subtree) (trav subtree name))
|
||||
subtrees))]
|
||||
['- (void)]
|
||||
[(? string?) (void)]))])
|
||||
(trav x #f)))))))
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,246 @@
|
||||
;; dfa-min.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ======================================================================
|
||||
;; CHANGES
|
||||
;; 01.11.96: Commented out hack to put all partitions on worklist initially
|
||||
;; ======================================================================
|
||||
|
||||
(define-typed-structure state-aux (eqvcl prev next touched))
|
||||
(define-typed-structure dfa-eqvcl (states count on-worklist touched))
|
||||
|
||||
;(define inv-delta-traversal-timer (make-timer))
|
||||
;(define Fn-a-timer (make-timer))
|
||||
;(define finish-a-timer (make-timer))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (Hopcroft-calc-equivalences States seperate
|
||||
inv-delta-traversal
|
||||
state-aux set-state-aux! state->rep)
|
||||
|
||||
;; states must have an aux field with set-state-aux! and state-aux fns
|
||||
;; seperate is a list of list of States
|
||||
;; any partition must be included in some element of seperate
|
||||
|
||||
;; inv-delta-traversal: P(states) (Sigma P(states) -> void) -> void
|
||||
;; inv-delta-traversal(X, Fn)
|
||||
;; => Fn is called with all pairs (a,C) where C = { s | delta(s,sigma) in X}
|
||||
|
||||
(pretty-debug-dfa-min
|
||||
`(States ,(map state->rep States)))
|
||||
(pretty-debug-dfa-min
|
||||
`(seperate ,(map (lambda (c) (map state->rep c)) seperate)))
|
||||
|
||||
(for-each
|
||||
(lambda (s) (set-state-aux! s (make-state-aux (void) (void) (void) #f)))
|
||||
States)
|
||||
|
||||
(for-each
|
||||
(lambda (c)
|
||||
(for-each
|
||||
(lambda (s) (assert (state-aux? (state-aux s)) 1 (state->rep s)))
|
||||
c))
|
||||
seperate)
|
||||
|
||||
(let*
|
||||
( [t (lambda (s)
|
||||
(when timing-min (min-record-progress (cons 'hopcroft s))))]
|
||||
[_ (t 0)]
|
||||
[state-prev (lambda (s) (state-aux-prev (state-aux s)))]
|
||||
[state-next (lambda (s) (state-aux-next (state-aux s)))]
|
||||
[state-eqvcl (lambda (s) (state-aux-eqvcl (state-aux s)))]
|
||||
[state-touched (lambda (s) (state-aux-touched (state-aux s)))]
|
||||
[set-state-prev! (lambda (s p) (set-state-aux-prev! (state-aux s) p))]
|
||||
[set-state-next! (lambda (s p) (set-state-aux-next! (state-aux s) p))]
|
||||
[set-state-eqvcl! (lambda (s p) (set-state-aux-eqvcl! (state-aux s) p))]
|
||||
[set-state-touched!
|
||||
(lambda (s p) (set-state-aux-touched! (state-aux s) p))]
|
||||
|
||||
[partition '()]
|
||||
[mk-empty-eqvcl
|
||||
(lambda ()
|
||||
(let ([X (make-dfa-eqvcl '() 0 #f '())])
|
||||
(set! partition (cons X partition))
|
||||
X))]
|
||||
|
||||
[add-to-eqvcl!
|
||||
(lambda (X s)
|
||||
(let ([first (dfa-eqvcl-states X)])
|
||||
(set-state-next! s first)
|
||||
(unless (null? first) (set-state-prev! first s))
|
||||
(set-dfa-eqvcl-states! X s)
|
||||
(set-state-prev! s X)
|
||||
(set-state-eqvcl! s X)
|
||||
(set-dfa-eqvcl-count! X (add1 (dfa-eqvcl-count X)))))]
|
||||
[remove-from-eqvcl!
|
||||
(lambda (X s)
|
||||
(assert (eq? (state-eqvcl s) X))
|
||||
(let ([prev (state-prev s)]
|
||||
[next (state-next s)])
|
||||
(unless (null? next) (set-state-prev! next prev))
|
||||
(if (dfa-eqvcl? prev)
|
||||
(set-dfa-eqvcl-states! prev next)
|
||||
(set-state-next! prev next))
|
||||
(set-dfa-eqvcl-count! X (sub1 (dfa-eqvcl-count X)))))]
|
||||
[eqvcl->list
|
||||
(lambda (c)
|
||||
(recur loop ([state (dfa-eqvcl-states c)])
|
||||
(if (null? state)
|
||||
'()
|
||||
(cons state (loop (state-next state))))))]
|
||||
|
||||
[worklist '()]
|
||||
[add-to-worklist!
|
||||
(lambda (X)
|
||||
(assert (not (dfa-eqvcl-on-worklist X)))
|
||||
(set! worklist (cons X worklist))
|
||||
(set-dfa-eqvcl-on-worklist! X #t))]
|
||||
|
||||
[split
|
||||
(lambda (generate-split-states)
|
||||
|
||||
;; Change so each partition totally included or excluded in states
|
||||
;; See Cliff Click's thesis, page ~40.
|
||||
|
||||
(pretty-debug-dfa-min `(split))
|
||||
|
||||
(let* ([touched '()])
|
||||
(begin0
|
||||
(generate-split-states
|
||||
(lambda (s)
|
||||
(pretty-debug-dfa-min
|
||||
`(add-split ,(state->rep s) ,(state-aux s)))
|
||||
(assert (state-aux? (state-aux s))
|
||||
2 (state->rep s) (state-aux s))
|
||||
(let* ([s-eqvcl (state-eqvcl s)])
|
||||
(when (null? (dfa-eqvcl-touched s-eqvcl))
|
||||
(set! touched (cons s-eqvcl touched))
|
||||
(assert (not (state-touched s))))
|
||||
(unless (state-touched s)
|
||||
;;(assert (not (memq s (dfa-eqvcl-touched s-eqvcl))))
|
||||
(set-dfa-eqvcl-touched!
|
||||
s-eqvcl
|
||||
(cons s (dfa-eqvcl-touched s-eqvcl)))
|
||||
(set-state-touched! s #t)))))
|
||||
(for-each
|
||||
(lambda (Z)
|
||||
|
||||
(pretty-debug-dfa-min
|
||||
`(touched
|
||||
,(map state->rep (eqvcl->list Z))
|
||||
,(map state->rep (dfa-eqvcl-touched Z))
|
||||
,(= (dfa-eqvcl-count Z)
|
||||
(length (dfa-eqvcl-touched Z)))))
|
||||
(if (= (dfa-eqvcl-count Z)
|
||||
(length (dfa-eqvcl-touched Z)))
|
||||
|
||||
;; No need to change, just clear touched
|
||||
(for-each (lambda (s) (set-state-touched! s #f))
|
||||
(dfa-eqvcl-touched Z))
|
||||
|
||||
;; Need to make new eqvcl
|
||||
(let ([nu (mk-empty-eqvcl)])
|
||||
;;(printf ".") (flush-output)
|
||||
(for-each
|
||||
(lambda (s)
|
||||
(remove-from-eqvcl! Z s)
|
||||
(set-state-touched! s #f)
|
||||
(add-to-eqvcl! nu s))
|
||||
(dfa-eqvcl-touched Z))
|
||||
(assert (not (null? (dfa-eqvcl-states Z))))
|
||||
(assert (not (null? (dfa-eqvcl-states nu))))
|
||||
(cond
|
||||
[(dfa-eqvcl-on-worklist Z)
|
||||
(add-to-worklist! nu)]
|
||||
[(< (dfa-eqvcl-count nu) (dfa-eqvcl-count Z))
|
||||
(add-to-worklist! nu)
|
||||
;; Kludge cause not complete grammar
|
||||
(add-to-worklist! Z)
|
||||
]
|
||||
[else
|
||||
(add-to-worklist! Z)
|
||||
;; Kludge cause not complete grammar
|
||||
(add-to-worklist! nu)
|
||||
])))
|
||||
(set-dfa-eqvcl-touched! Z '()))
|
||||
touched))))])
|
||||
|
||||
(t 1)
|
||||
(let ([base-eqvcl (mk-empty-eqvcl)])
|
||||
(for-each (lambda (s) (add-to-eqvcl! base-eqvcl s))
|
||||
States))
|
||||
|
||||
(t 2)
|
||||
(for-each
|
||||
(lambda (nts) (split (lambda (add-split!) (for-each add-split! nts))))
|
||||
seperate)
|
||||
|
||||
|
||||
(t 3)
|
||||
;; ### HACK ###
|
||||
;; Put all partitions on the worklist
|
||||
'(for-each
|
||||
(lambda (eqvcl)
|
||||
(unless (dfa-eqvcl-on-worklist eqvcl)
|
||||
(add-to-worklist! eqvcl)))
|
||||
partition)
|
||||
;; ### END HACK ###
|
||||
|
||||
(t 4)
|
||||
(recur loop ()
|
||||
;; partition a partition of States union Final
|
||||
;; All equiv states in same eqvcl
|
||||
;; If s1,s2 in eqvcl B with si->a.si', and si' in Bi
|
||||
;; then either B1=B2, or (Bi,a) in worklist for one of i=1,2
|
||||
|
||||
(unless (null? worklist)
|
||||
(let* ([X (car worklist)])
|
||||
(set! worklist (cdr worklist))
|
||||
(set-dfa-eqvcl-on-worklist! X #f)
|
||||
(inv-delta-traversal (eqvcl->list X) split)
|
||||
(loop))))
|
||||
(t 5)
|
||||
|
||||
;; All done
|
||||
;; Return mapping from states to representative states,
|
||||
;; and a mapping from states to a list of equiv states
|
||||
;; and an equiv predicate on states
|
||||
;; and a list of representative states
|
||||
|
||||
(values
|
||||
(lambda (s) (dfa-eqvcl-states (state-eqvcl s)))
|
||||
(lambda (s) (eqvcl->list (state-eqvcl s)))
|
||||
(lambda (s1 s2) (eq? (state-eqvcl s1) (state-eqvcl s2)))
|
||||
(filter-map (lambda (X)
|
||||
(let ([rep (dfa-eqvcl-states X)])
|
||||
(if (null? rep) #f rep)))
|
||||
partition))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Prototypical inputs
|
||||
|
||||
'(define-type dfa-state (box void))
|
||||
'(MrSpidey-test
|
||||
(calc-equivalences (type: (listof dfa-state))
|
||||
(type: (listof dfa-state))
|
||||
(type: (_ (-> (list (dfa-state -> void) (-> void)))
|
||||
-> void))
|
||||
unbox
|
||||
set-box!))
|
||||
;(trace calc-equivalences)
|
||||
|
@ -0,0 +1,215 @@
|
||||
;; File: min-live-few-e.ss
|
||||
;; Can optimize later when sure only want min-live-few-e-L
|
||||
;; ======================================================================
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; CHANGES:
|
||||
;;
|
||||
;; (null? (Tvar-constraints tvar))
|
||||
;; -> (andmap con-filter? (Tvar-constraints tvar))
|
||||
;;
|
||||
;; rhs-nts not filter w/ live-nt?
|
||||
;;
|
||||
;; ======================================================================
|
||||
(define-typed-structure Tvar-class (parent L-unif U-unif children))
|
||||
|
||||
;; tvars is binary tree w/ tvar at leaves
|
||||
|
||||
; ======================================================================
|
||||
; minimize-constraints-live-few-e
|
||||
;
|
||||
; Input: lower : list Tvar
|
||||
; upper : list Tvar
|
||||
|
||||
(define (copy-live-constraints-few-e L-unif U-unif)
|
||||
(lambda (lower upper)
|
||||
|
||||
(pretty-debug-few
|
||||
`(copy-live-constraints-few-e
|
||||
lower ,(map Tvar-name lower)
|
||||
upper ,(map Tvar-name upper)))
|
||||
|
||||
;; Calc edgefrom
|
||||
;; Calculate live Tvar and live NT
|
||||
;; Only use Tvar-orig-objs
|
||||
;; Flag NTs with non-epsilon edges
|
||||
|
||||
(let*-vals
|
||||
( [t (lambda (s)
|
||||
(when timing-min
|
||||
(min-record-progress (cons 'copy-live-constraints-few-e s))))]
|
||||
[_ (t 0)]
|
||||
|
||||
;; --- Calc empty and live
|
||||
;; not empty == reached
|
||||
[(live-nts live-nt? live-tvars live-tvar? _ _ rhs-nts)
|
||||
(calc-live-tvars-nts lower upper #f)]
|
||||
[_ (t 1)]
|
||||
[_ (pretty-debug-few `(live-nts ,(map nt->sym live-nts)))]
|
||||
[_ (pretty-debug-few `(live-tvars ,(map Tvar-name live-tvars)))]
|
||||
[rhs-nts
|
||||
(lambda (nt)
|
||||
(filter (lambda (x) (or (eq? x #t) (live-nt? x))) (rhs-nts nt)))]
|
||||
|
||||
;; Now unify to equiv classes.
|
||||
;; Define AV `a' to be L-unifiable iff
|
||||
;; con(a) = 0 and
|
||||
;; #outedge(a)=1 and
|
||||
;; # prods for LaU = 1
|
||||
;; But aU -> bU is not counted in rhs-nts(aU)
|
||||
;; => require rhs-nts(aU) = 0
|
||||
;;
|
||||
;; Define AV `b' to be U-unifiable iff
|
||||
;; AV(a) = AV(b) for all predecessors a of b
|
||||
;; #inedge(b)<=1 and
|
||||
;; # prods for LbL = 1
|
||||
;;
|
||||
;; If a <= b and either a L-unif or b U-unif, then unify
|
||||
|
||||
;; Unify to equivalence classes
|
||||
[(tvar-class set-tvar-class!) (alloc-Tvar-field)]
|
||||
[_ (t 3)]
|
||||
[_ (for-each
|
||||
(lambda (tvar)
|
||||
(pretty-debug-few `(Tvar ,(Tvar-name tvar)))
|
||||
(let* ([pretty-and
|
||||
(lambda args
|
||||
(let ([r (andmap (lambda (x) x) args)])
|
||||
(pretty-debug-few `((and ,@args) ,r))
|
||||
r))]
|
||||
[L-u (pretty-and
|
||||
L-unif
|
||||
(andmap
|
||||
(match-lambda
|
||||
[($ con _ _ _ tvar) (not (live-tvar? tvar))]
|
||||
[($ con-filter) #t])
|
||||
(Tvar-constraints tvar))
|
||||
(let ([out
|
||||
(append
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[($ con) #f]
|
||||
[($ con-filter _ _ tvar)
|
||||
(and (live-tvar? tvar) tvar)])
|
||||
(Tvar-constraints tvar))
|
||||
(filter live-tvar?
|
||||
(Tvar-edgeto tvar)))])
|
||||
(or (null? out) (null? (cdr out))))
|
||||
(let ([nt (Tvar-U tvar)])
|
||||
(or (not (live-nt? nt))
|
||||
(let ([s (rhs-nts nt)])
|
||||
(pretty-debug-few
|
||||
`(rhs-nts
|
||||
,(map
|
||||
(lambda (nt)
|
||||
(or (eq? nt #t) (nt->sym nt)))
|
||||
s)))
|
||||
(null? s)
|
||||
;;(or (null? s) (null? (cdr s)))
|
||||
)))
|
||||
; Ignore lower, upper
|
||||
; Already counted in rhs-nts
|
||||
;(not (memq tvar lower))
|
||||
;(not (memq tvar upper))
|
||||
)]
|
||||
[U-u
|
||||
(let ( [in (Tvar-edgefrom tvar)])
|
||||
(pretty-and
|
||||
U-unif
|
||||
(or (null? in)
|
||||
(and (null? (cdr in))
|
||||
(<= (length (Tvar-objs tvar))
|
||||
(length (Tvar-objs (car in))))))
|
||||
(let ([nt (Tvar-L tvar)])
|
||||
(or (not (live-nt? nt))
|
||||
(let ([s (rhs-nts nt)])
|
||||
(pretty-debug-few
|
||||
`(rhs-nts
|
||||
,(map
|
||||
(lambda (nt)
|
||||
(or (eq? nt #t) (nt->sym nt)))
|
||||
s)))
|
||||
(or (null? s) (null? (cdr s)))
|
||||
)))
|
||||
;(not (memq tvar lower))
|
||||
;(not (memq tvar upper))
|
||||
))])
|
||||
|
||||
(set-tvar-class! tvar (make-Tvar-class #f L-u U-u tvar))))
|
||||
live-tvars)]
|
||||
[_ (t 4)]
|
||||
[get-class
|
||||
(lambda (tvar)
|
||||
(recur loop ([c (tvar-class tvar)])
|
||||
(assert (or (Tvar-class? (Tvar-class-parent c))
|
||||
(eq? #f (Tvar-class-parent c))))
|
||||
(if (Tvar-class-parent c)
|
||||
(loop (Tvar-class-parent c))
|
||||
c)))]
|
||||
[_ (for-each
|
||||
(lambda (b)
|
||||
(for-each
|
||||
(lambda (a)
|
||||
(when (live-tvar? a)
|
||||
(match (get-class a)
|
||||
[(and cl-a
|
||||
($ Tvar-class _ L-unif-a U-unif-a kids-a))
|
||||
(assert (eq? (Tvar-class-parent cl-a) #f)
|
||||
(Tvar-class-parent cl-a))
|
||||
(match (get-class b)
|
||||
[(and cl-b
|
||||
($ Tvar-class _ L-unif-b U-unif-b kids-b))
|
||||
(pretty-debug-few
|
||||
`(epsilon ,(Tvar-name a)
|
||||
,(Tvar-name b)
|
||||
,L-unif-a
|
||||
,L-unif-b
|
||||
,U-unif-a
|
||||
,U-unif-b))
|
||||
(when (or L-unif-a U-unif-b)
|
||||
;; Unify
|
||||
(let ([nu-cl
|
||||
(make-Tvar-class #f
|
||||
(and L-unif-a L-unif-b)
|
||||
(and U-unif-a U-unif-b)
|
||||
(cons kids-a kids-b))])
|
||||
|
||||
(assert (eq? (Tvar-class-parent cl-a) #f) 2)
|
||||
(assert (eq? (Tvar-class-parent cl-b) #f))
|
||||
(set-Tvar-class-parent! cl-a nu-cl)
|
||||
(set-Tvar-class-parent! cl-b nu-cl)
|
||||
(assert (eq? (get-class a) (get-class b)))
|
||||
))])])))
|
||||
(Tvar-edgefrom b)))
|
||||
live-tvars)]
|
||||
[_ (t 4.5)]
|
||||
)
|
||||
;; --- Have equiv classes, now copy
|
||||
;; --- return arguments for copy-constraints-equiv!
|
||||
(values
|
||||
(append lower upper live-tvars)
|
||||
live-tvar?
|
||||
live-nts
|
||||
(lambda (tvar)
|
||||
(recur loop ([k (Tvar-class-children (get-class tvar))][a '()])
|
||||
(if (Tvar? k)
|
||||
(cons k a)
|
||||
(loop (car k) (loop (cdr k) a)))))
|
||||
(lambda (AV) (list AV))))))
|
||||
|
||||
;; ======================================================================
|
||||
|
@ -0,0 +1,490 @@
|
||||
; ======================================================================
|
||||
; minimize-constraints-dfa-min-fast
|
||||
;
|
||||
; Input: lower : list Tvar
|
||||
; upper : list Tvar
|
||||
;
|
||||
; see practical.tex
|
||||
; ======================================================================
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (minimize-constraints-dfa-min-fast
|
||||
lower upper
|
||||
helper-fn)
|
||||
|
||||
(pretty-debug-dfa-min
|
||||
`(minimize-constraints-dfa-min-fast
|
||||
lower ,(map Tvar-name lower)
|
||||
upper ,(map Tvar-name upper)))
|
||||
|
||||
(let*-vals
|
||||
([t (lambda (s)
|
||||
(when timing-min
|
||||
(min-record-progress
|
||||
(cons 'minimize-constraints-dfa-min-fast s))))]
|
||||
[_ (t 0)]
|
||||
|
||||
[(live-tvars live-tvar? live-nts tvar->equiv AV->equiv)
|
||||
((copy-live-constraints-few-e #t #t) lower upper)]
|
||||
[_ (t 1)]
|
||||
|
||||
;; Figure out representative elements for Tvars,
|
||||
;; and live AV
|
||||
[(tvar->rep set-tvar-rep!) (alloc-Tvar-field)]
|
||||
[(is-rep? add-rep! get-list-rep) (field->set alloc-Tvar-field)]
|
||||
[(live-AV? set-live-AV! get-live-AVs) (field->set alloc-AV-field)]
|
||||
[_ (for-each
|
||||
(lambda (tvar)
|
||||
(for-each set-live-AV! (get-Tvar-objs tvar))
|
||||
(unless (tvar->rep tvar)
|
||||
(add-rep! tvar)
|
||||
(for-each
|
||||
(lambda (eq) (set-tvar-rep! eq tvar))
|
||||
(tvar->equiv tvar))
|
||||
(assert (tvar->rep tvar))))
|
||||
live-tvars)]
|
||||
[live-AVs (get-live-AVs)]
|
||||
[rep-tvars (get-list-rep)]
|
||||
[_ (t 2)]
|
||||
|
||||
;; states = rep-tvars + live-AVs + dummy-tvar
|
||||
[dummy-tvar (mk-Tvar 'Grammar-dummy)]
|
||||
[all-states (append rep-tvars (list dummy-tvar) live-AVs)]
|
||||
[state->sym (lambda (state)
|
||||
(cond
|
||||
[(Tvar? state) (Tvar-name state)]
|
||||
[(AV? state) (AV->rep state)]
|
||||
[else (error 'state->sym "Bad state ~s" state)]))]
|
||||
|
||||
[grsym-eq?
|
||||
(lambda (g1 g2)
|
||||
;; (andmap eq? g1 g2)
|
||||
(recur loop ([g1 g1][g2 g2])
|
||||
(if (null? g1)
|
||||
(null? g2)
|
||||
(if (null? g2)
|
||||
#f
|
||||
(and (eq? (car g1) (car g2))
|
||||
(loop (cdr g1) (cdr g2)))))))]
|
||||
|
||||
;; mapping from grsyms to numbers
|
||||
[num-grsym 0]
|
||||
[grsym-table '()]
|
||||
[grsym->number
|
||||
(lambda (g1)
|
||||
(or
|
||||
(ormap
|
||||
(match-lambda
|
||||
[(n . g2) (and (grsym-eq? g1 g2) n)]
|
||||
[_ #f])
|
||||
grsym-table)
|
||||
(begin
|
||||
(set! grsym-table (cons (cons num-grsym g1) grsym-table))
|
||||
(begin0
|
||||
num-grsym
|
||||
(set! num-grsym (add1 num-grsym))))))]
|
||||
|
||||
[(tvar-EF-epsilon set-tvar-EF-epsilon!)
|
||||
(alloc-Tvar-field (lambda () '()))]
|
||||
[(tvar-EF set-tvar-EF!)
|
||||
(alloc-Tvar-field (lambda () '()))]
|
||||
[(AV-EF-epsilon set-AV-EF-epsilon!)
|
||||
(alloc-AV-field (lambda () '()))]
|
||||
[(AV-EF set-AV-EF!)
|
||||
(alloc-AV-field (lambda () '()))]
|
||||
|
||||
[add-tvar-EF!
|
||||
(lambda (tvar g1 s1)
|
||||
(let* ( [tvar (tvar->rep tvar)]
|
||||
[n1 (grsym->number g1)]
|
||||
[x (tvar-EF tvar)])
|
||||
(unless (ormap
|
||||
(match-lambda [(n2 . s2) (and (= n1 n2) (eq? s1 s2))])
|
||||
x)
|
||||
(set-tvar-EF! tvar (cons (cons n1 s1) x)))))]
|
||||
[add-AV-EF!
|
||||
(lambda (AV g1 s1)
|
||||
(let ( [x (AV-EF AV)]
|
||||
[n1 (grsym->number g1)])
|
||||
(unless (ormap
|
||||
(match-lambda [(n2 . s2) (and (= n1 n1) (eq? s1 s2))])
|
||||
x)
|
||||
(set-AV-EF! AV (cons (cons n1 s1) x)))))]
|
||||
[add-tvar-EF-epsilon!
|
||||
(lambda (tvar s1)
|
||||
(let* ( [tvar (tvar->rep tvar)]
|
||||
[x (tvar-EF-epsilon tvar)])
|
||||
(unless (memq s1 x)
|
||||
(set-tvar-EF-epsilon! tvar (cons s1 x)))))]
|
||||
[add-AV-EF-epsilon!
|
||||
(lambda (AV s1)
|
||||
(let ([x (AV-EF-epsilon AV)])
|
||||
(unless (memq s1 x)
|
||||
(set-AV-EF-epsilon! AV (cons s1 x)))))]
|
||||
[state-EF-epsilon
|
||||
(lambda (state)
|
||||
(if (AV? state)
|
||||
(AV-EF-epsilon state)
|
||||
(tvar-EF-epsilon state)))]
|
||||
[state-EF
|
||||
(lambda (state)
|
||||
(if (AV? state)
|
||||
(AV-EF state)
|
||||
(tvar-EF state)))]
|
||||
[_ (t 2.1)]
|
||||
|
||||
;; helper-fn sets things up for inv-delta-traversal
|
||||
;; Sets U field of each state to:
|
||||
;; (listof (cons (listof any) state))
|
||||
|
||||
[extra-seperate (helper-fn live-tvars live-tvar? tvar->rep live-AVs
|
||||
add-tvar-EF! add-tvar-EF-epsilon!
|
||||
add-AV-EF! add-AV-EF-epsilon!)]
|
||||
[_ (t 3)]
|
||||
|
||||
;; Show productions
|
||||
[_ (pretty-debug-dfa-min
|
||||
`(productions
|
||||
,(map
|
||||
(lambda (state)
|
||||
(list (state->sym state)
|
||||
(map state->sym (state-EF-epsilon state))
|
||||
(map
|
||||
(match-lambda [(g . s) (cons g (state->sym s))])
|
||||
(state-EF state))))
|
||||
all-states)))]
|
||||
|
||||
;; Vector of buckets for productions
|
||||
[buckets (make-vector num-grsym '())]
|
||||
[_ (min-record-progress (cons 'num-buckets num-grsym))]
|
||||
|
||||
;; inv-delta-traversal:
|
||||
;; P(states) x (P(states) -> void) -> void
|
||||
;; inv-delta-traversal(X, split)
|
||||
;; => no equiv class partially in X
|
||||
;; => Call split with each "partition of equiv classes" ...
|
||||
;; For effeciency, we call split with a "generator" for the set C_a
|
||||
;; The generator is passed a function add-split!, and then
|
||||
;; calls add-split! on each state in C_a
|
||||
|
||||
;; --- Set things up for Hopcrofts Algorithm
|
||||
|
||||
;; Condition 1, thms hopcroft lub and glb
|
||||
;; Also, to make up for grammar being "incomplete",
|
||||
;; seperate states into equiv classes so states in same equiv class
|
||||
;; have productions on same grammar symbols
|
||||
|
||||
[seperate-grsyms (make-vector num-grsym '())]
|
||||
[seperate-epsilon '()]
|
||||
[_ (for-each
|
||||
(lambda (state)
|
||||
(when (not (null? (state-EF-epsilon state)))
|
||||
(set! seperate-epsilon (cons state seperate-epsilon)))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(g . s)
|
||||
(vector-set! seperate-grsyms g
|
||||
(cons s (vector-ref seperate-grsyms g)))])
|
||||
(state-EF state)))
|
||||
all-states)]
|
||||
[_ (pretty-debug-dfa-min
|
||||
`(seperate-epsilon ,(map state->sym seperate-epsilon)))]
|
||||
[_ (pretty-debug-dfa-min
|
||||
`(seperate-grsyms
|
||||
,(map
|
||||
(lambda (s) (map state->sym s))
|
||||
(vector->list seperate-grsyms))))]
|
||||
[seperate (append
|
||||
(list rep-tvars)
|
||||
(list live-AVs)
|
||||
extra-seperate
|
||||
;(map list lower)
|
||||
;(map list upper)
|
||||
(list seperate-epsilon)
|
||||
(vector->list seperate-grsyms))]
|
||||
[seperate (filter
|
||||
(lambda (l) (not (null? l)))
|
||||
seperate)]
|
||||
[_ (pretty-debug-dfa-min
|
||||
`(seperate ,(map (lambda (s) (map state->sym s)) seperate)))]
|
||||
[_ (t 4)]
|
||||
|
||||
[inv-delta-traversal
|
||||
(lambda (states split)
|
||||
(pretty-debug-dfa-min
|
||||
`(inv-delta-trav
|
||||
,(map (lambda (state)
|
||||
`(,(state->sym state)
|
||||
(epsilon
|
||||
,(map state->sym (state-EF-epsilon state)))
|
||||
,(map
|
||||
(match-lambda [(g . s) (cons g (state->sym s))])
|
||||
(state-EF state))))
|
||||
states)))
|
||||
;; Do epsilons
|
||||
(split
|
||||
(lambda (add-split!)
|
||||
(for-each
|
||||
(lambda (state)
|
||||
(for-each
|
||||
add-split!
|
||||
(state-EF-epsilon state)))
|
||||
states)))
|
||||
|
||||
;; Put rest into buckets
|
||||
(let ([bucket-ndxs '()])
|
||||
(for-each
|
||||
(lambda (state)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(n . s)
|
||||
(let ([old (vector-ref buckets n)])
|
||||
(vector-set! buckets n (cons s old))
|
||||
(when (null? old)
|
||||
(set! bucket-ndxs (cons n bucket-ndxs))))])
|
||||
(state-EF state)))
|
||||
states)
|
||||
;; Run thru buckets ...
|
||||
(for-each
|
||||
(lambda (i)
|
||||
(let ([s* (vector-ref buckets i)])
|
||||
(split (lambda (add-split!) (for-each add-split! s*)))
|
||||
(vector-set! buckets i '())))
|
||||
bucket-ndxs)))]
|
||||
|
||||
[(state-aux set-state-aux!) (alloc-NT-field)]
|
||||
[(state->rep state->equiv equiv-state? list-rep-states)
|
||||
(Hopcroft-calc-equivalences
|
||||
all-states
|
||||
seperate
|
||||
inv-delta-traversal
|
||||
state-aux set-state-aux! state->sym)]
|
||||
[_ (t 5)]
|
||||
|
||||
[_ (begin
|
||||
(pretty-debug-dfa-min
|
||||
`(list-rep-state ,(map state->sym list-rep-states)))
|
||||
(pretty-debug-dfa-min
|
||||
`(state->equiv
|
||||
,(map (lambda (state)
|
||||
(map state->sym (state->equiv state)))
|
||||
list-rep-states))))]
|
||||
|
||||
;; ----------------------------------------
|
||||
;; Have equivalence relation on states
|
||||
;; Combine w/ previous relation on Tvars
|
||||
;; Convert to equivalence relation on Tvars
|
||||
|
||||
[tvar->equiv
|
||||
(lambda (tvar)
|
||||
(let ([r (apply append (map tvar->equiv (state->equiv tvar)))])
|
||||
(pretty-debug-dfa-min
|
||||
`(tvar->equiv ,(state->sym tvar) = ,(map state->sym r)))
|
||||
r))]
|
||||
|
||||
[AV->equiv
|
||||
(lambda (x)
|
||||
(pretty-debug-dfa-min `(AV->equiv ,(state->sym x)))
|
||||
(let ([e (state->equiv x)])
|
||||
(pretty-debug-dfa-min
|
||||
`(AV->equiv ,(state->sym x) = ,(map state->sym e)))
|
||||
e))]
|
||||
[_ (t 6)])
|
||||
|
||||
(copy-constraints-equiv!
|
||||
live-tvars
|
||||
live-tvar?
|
||||
live-nts
|
||||
tvar->equiv
|
||||
AV->equiv)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (minimize-constraints-dfa-min-lub lower upper)
|
||||
(minimize-constraints-dfa-min-fast lower upper
|
||||
|
||||
;; helper-fn
|
||||
;; helper-fn sets things up for inv-delta-traversal
|
||||
;; Sets U field of each state to:
|
||||
;; (listof (cons (listof any) state))
|
||||
|
||||
(lambda (live-tvars live-tvar? tvar->rep live-AVs
|
||||
add-tvar-EF! add-tvar-EF-epsilon!
|
||||
add-AV-EF! add-AV-EF-epsilon!)
|
||||
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
|
||||
;; --- Condition 2
|
||||
;; If [a <= b] => forall a'~a exists b'~b st [a' <= b']
|
||||
(for-each
|
||||
(lambda (from)
|
||||
(when (live-tvar? from)
|
||||
(add-tvar-EF-epsilon! tvar (tvar->rep from))))
|
||||
(Tvar-edgefrom tvar))
|
||||
(for-each
|
||||
(lambda (AV) (add-tvar-EF-epsilon! tvar AV))
|
||||
(get-Tvar-objs tvar))
|
||||
|
||||
;; --- Conditions 4 and 5
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ template field alpha sign)
|
||||
(when (live-tvar? alpha)
|
||||
(if sign
|
||||
;; [rng(tvar) <= alpha]
|
||||
(add-tvar-EF! alpha
|
||||
(list 'R4 template field) (tvar->rep tvar))
|
||||
(when #t ;; (follow-antimono-fields template)
|
||||
;; Condition 5
|
||||
;; At bottom we put beta (or tvar) in own equiv class
|
||||
;; [alpha <= dom(tvar)]
|
||||
(add-tvar-EF! tvar
|
||||
(list 'R5 template field) (tvar->rep alpha)))))]
|
||||
[_ (void)])
|
||||
(Tvar-constraints tvar)))
|
||||
live-tvars)
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template _ fields+ fields-))
|
||||
;; --- Condition 3
|
||||
(for i 0 (vector-length fields+)
|
||||
(let ([field (vector-ref fields+ i)])
|
||||
(when (live-tvar? field)
|
||||
(add-AV-EF! AV
|
||||
(list 'R3 template i) (tvar->rep field)))))])
|
||||
live-AVs)
|
||||
|
||||
;; extra partitions
|
||||
(append
|
||||
;; Put each beta st [alpha <= dom(beta)] in separate equiv class
|
||||
(map list
|
||||
(map tvar->rep
|
||||
(filter
|
||||
(lambda (tvar)
|
||||
(ormap
|
||||
(match-lambda
|
||||
[($ con _ template field alpha #f)
|
||||
(live-tvar? alpha)]
|
||||
[_ #f])
|
||||
(Tvar-constraints tvar)))
|
||||
live-tvars)))
|
||||
|
||||
;; put AVs into equiv class according to templates
|
||||
;; h maps templates to list of AVs
|
||||
(let ([h (make-hash-table)])
|
||||
(for-each
|
||||
(lambda (AV)
|
||||
(let ([t (AV-template AV)])
|
||||
(hash-table-put! h t
|
||||
(cons AV (hash-table-get h t (lambda () ()))))))
|
||||
live-AVs)
|
||||
(hash-table-map h
|
||||
(lambda (t AVs) AVs))))
|
||||
|
||||
)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (minimize-constraints-dfa-min-glb lower upper)
|
||||
(minimize-constraints-dfa-min-fast lower upper
|
||||
|
||||
;; helper-fn
|
||||
;; helper-fn sets things up for inv-delta-traversal
|
||||
;; Sets U field of each state to:
|
||||
;; (listof (cons (listof any) state))
|
||||
|
||||
(lambda (live-tvars live-tvar? tvar->rep live-AVs
|
||||
add-tvar-EF! add-tvar-EF-epsilon!
|
||||
add-AV-EF! add-AV-EF-epsilon!)
|
||||
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
|
||||
;; --- Condition 2
|
||||
;; If [a <= b] => forall b'~b exists a'~a st [a' <= b']
|
||||
(for-each
|
||||
(lambda (from)
|
||||
(when (live-tvar? from)
|
||||
(add-tvar-EF-epsilon! from (tvar->rep tvar))))
|
||||
(Tvar-edgefrom tvar))
|
||||
(for-each
|
||||
(lambda (AV) (add-AV-EF-epsilon! AV (tvar->rep tvar)))
|
||||
(get-Tvar-objs tvar))
|
||||
|
||||
;; --- Condition 4
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ template field alpha #t)
|
||||
(when (live-tvar? alpha)
|
||||
;; [rng(tvar) <= alpha]
|
||||
(add-tvar-EF! tvar
|
||||
(list 'R4 template field) (tvar->rep alpha)))]
|
||||
[_ (void)])
|
||||
(Tvar-constraints tvar)))
|
||||
live-tvars)
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template _ fields+ fields-))
|
||||
;; --- Condition 3
|
||||
(for i 0 (vector-length fields+)
|
||||
(let ([field (vector-ref fields+ i)])
|
||||
(when (live-tvar? field)
|
||||
(add-tvar-EF! field (list 'R3 template i) AV))))
|
||||
;; --- Condition 5
|
||||
(when (follow-antimono-fields template)
|
||||
(for i 0 (vector-length fields-)
|
||||
(let ([field (vector-ref fields- i)])
|
||||
(when (live-tvar? field)
|
||||
;; [dom(AV) <= field]
|
||||
;; At bottom we put AV in own equiv class
|
||||
(add-AV-EF! AV
|
||||
(list 'R5 template i) (tvar->rep field))))))])
|
||||
live-AVs)
|
||||
|
||||
;; Conditions 5,6, thm 1.2
|
||||
;; extra partitioning
|
||||
(append
|
||||
;; Conditions 5, thm 1.2
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template _ _ fields-))
|
||||
(and
|
||||
(follow-antimono-fields template)
|
||||
(> (vector-length fields-) 0)
|
||||
(list AV))])
|
||||
live-AVs)
|
||||
;; Conditions 6, thm 1.2
|
||||
(let ([h (make-hash-table)])
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template))
|
||||
(hash-table-put! h template
|
||||
(cons AV
|
||||
(hash-table-get h template (lambda () '()))))])
|
||||
live-AVs)
|
||||
(hash-table-map h
|
||||
(lambda (template AVs) AVs)))))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,580 @@
|
||||
; ======================================================================
|
||||
; copy-live-constraints
|
||||
;
|
||||
; Input: lower : list Tvar
|
||||
; upper : list Tvar
|
||||
;
|
||||
; Copies live constraints
|
||||
; returns list-nu Tvar->nu
|
||||
; ======================================================================
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (copy-live-constraints lower upper)
|
||||
|
||||
(pretty-debug-min
|
||||
`(copy-live-constraints ,(map Tvar-name lower) ,(map Tvar-name upper)))
|
||||
|
||||
(let*-vals
|
||||
( [(live-nts live-nt? live-tvars live-tvar? _ _ _)
|
||||
(calc-live-tvars-nts lower upper #f)])
|
||||
|
||||
(copy-constraints-equiv!
|
||||
(append lower upper live-tvars)
|
||||
live-tvar? live-nts
|
||||
(lambda (tvar) (list tvar))
|
||||
(lambda (AV) (list AV)))))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define (copy-live-constraints-noe lower upper)
|
||||
|
||||
(pretty-debug-min
|
||||
`(copy-live-constraints-noe
|
||||
,(map Tvar-name lower) ,(map Tvar-name upper)))
|
||||
|
||||
(let*-vals
|
||||
( [(live-nts live-nt? live-tvars live-tvar? _ _ _)
|
||||
(calc-live-tvars-nts lower upper #t)]
|
||||
[(get-nu-Tvar set-nu-Tvar!) (alloc-Tvar-field)]
|
||||
[list-nuTvar
|
||||
(map (lambda (Tvar)
|
||||
(let ([nu (mk-Tvar 'min-live)])
|
||||
(set-nu-Tvar! Tvar nu)
|
||||
nu))
|
||||
live-tvars)]
|
||||
[dummy-tvars
|
||||
(copy-constraints-noe! live-tvar? live-nts get-nu-Tvar lower)])
|
||||
|
||||
(values
|
||||
(append dummy-tvars list-nuTvar)
|
||||
get-nu-Tvar)))
|
||||
|
||||
;; ======================================================================
|
||||
; calc-live-tvars-nts
|
||||
;
|
||||
; Calculates live Tvars and NTs
|
||||
; Input: lower : list Tvar
|
||||
; upper : list Tvar
|
||||
;
|
||||
; Uses find-nonempty-nts-rhs-nts to find nonempty nts and sources
|
||||
; Walk "forward" in grammar using rhs-nts from crossover and AV-w/-const
|
||||
; to calculate live
|
||||
;
|
||||
; Returns (values live-nts live-nt? live-tvars live-tvar?
|
||||
; AV-w/-const crossover rhs-nts)
|
||||
|
||||
(define (calc-live-tvars-nts lower upper inline-epsilon)
|
||||
|
||||
(pretty-debug-min
|
||||
`(calc-live-tvars-nts ,inline-epsilon
|
||||
,(map Tvar-name lower) ,(map Tvar-name upper)))
|
||||
|
||||
(let*-vals
|
||||
( [t (lambda (s)
|
||||
(when timing-min
|
||||
(min-record-progress (cons 'calc-live-tvars-nts s))))]
|
||||
[_ (t 0)]
|
||||
[(rhs-nts crossover AV-w/-const)
|
||||
(find-nonempty-nts-rhs-nts lower upper inline-epsilon)]
|
||||
[_ (t 1)]
|
||||
[(live-nt? set-live-nt! get-live-nts) (field->set alloc-NT-field)]
|
||||
[_ (t 2)]
|
||||
|
||||
;; --------------------------------------------------
|
||||
;; Walk forward from crossover and AV-w/-const, recording nts
|
||||
|
||||
[_ (letrec ([mark-live
|
||||
(lambda (nt)
|
||||
(unless (eq? nt #t)
|
||||
;;(pretty-print `(mark-live ,(nt->sym nt)))
|
||||
(unless (live-nt? nt)
|
||||
(set-live-nt! nt)
|
||||
(when (rhs-nts nt)
|
||||
(for-each mark-live (rhs-nts nt))))))])
|
||||
|
||||
(for-each
|
||||
(lambda (Tvar)
|
||||
(mark-live (Tvar-U Tvar))
|
||||
(mark-live (Tvar-L Tvar)))
|
||||
crossover)
|
||||
|
||||
(for-each
|
||||
(lambda (AV) (mark-live (AV-U AV)))
|
||||
AV-w/-const)
|
||||
|
||||
(pretty-debug-min `(live-nt ,(map nt->sym (get-live-nts)))))]
|
||||
[_ (t 3)]
|
||||
|
||||
;; --------------------------------------------------
|
||||
;; Have in (get-live-nts) all nts that are reached and non-empty
|
||||
;; Calc live Tvar
|
||||
|
||||
[(live-tvar? set-live-tvar! get-live-tvars)
|
||||
(field->set alloc-Tvar-field)]
|
||||
[_ (t 4)]
|
||||
[_ (begin
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ NT tvar) (when (Tvar? tvar) (set-live-tvar! tvar))])
|
||||
(get-live-nts))
|
||||
(for-each set-live-tvar! lower)
|
||||
(for-each set-live-tvar! upper))]
|
||||
[_ (t 5)]
|
||||
[_ (pretty-debug-min `(live-Tvar ,(map Tvar-name (get-live-tvars))))])
|
||||
|
||||
(pretty-debug-min
|
||||
`(calc-live-tvars-nts-results
|
||||
,(map (lambda (nt)
|
||||
`(nt-rhs ,(nt->sym nt)
|
||||
,(map (lambda (nt) (or (eq? nt #t) (nt->sym nt)))
|
||||
(rhs-nts nt))))
|
||||
(get-live-nts))))
|
||||
|
||||
(values
|
||||
(get-live-nts) live-nt?
|
||||
(get-live-tvars) live-tvar?
|
||||
AV-w/-const
|
||||
crossover
|
||||
rhs-nts
|
||||
)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (follow-antimono-fields template)
|
||||
(or
|
||||
(eq? template template-lam)
|
||||
(eq? template template-unit)
|
||||
(eq? template template-internal-class)
|
||||
(st:minimize-respect-assignable-part-of-fields)))
|
||||
|
||||
;; ======================================================================
|
||||
; find-nonempty-nts-rhs-nts
|
||||
;
|
||||
; Calculates non-empty Tvars, NTs.
|
||||
; For each non-empty NT, finds all rhs-nts NT' such that NT -> x.NT'
|
||||
|
||||
; Input: lower : (listof Tvar)
|
||||
; upper : (listof Tvar)
|
||||
;
|
||||
; Returns (values rhs-nts crossover-tvars AV-w/-const)
|
||||
;
|
||||
; Walks "backwards" in grammer to find nonempty NTs
|
||||
; Keeps track of rhs-nts on the way
|
||||
;
|
||||
; crossover is the set of Tvars tvar such that
|
||||
; both L(tvar_L) and L(tvar_U) are nonempty
|
||||
|
||||
;; #### Always looks at assignable fields ...
|
||||
|
||||
(define (find-nonempty-nts-rhs-nts lower upper inline-epsilon)
|
||||
(pretty-debug-min
|
||||
`(find-nonempty-tvars-nts-rhs-nts ,inline-epsilon
|
||||
,(map Tvar-name lower) ,(map Tvar-name upper)))
|
||||
|
||||
(let*-vals ( [(reached-tvar? set-reached-tvar!) (alloc-Tvar-field)]
|
||||
[(reached-AV? set-reached-AV!) (alloc-AV-field)]
|
||||
[(rhs-nts set-rhs-nts!) (alloc-NT-field)]
|
||||
[add-rhs-nt!
|
||||
(lambda (nt src) (set-rhs-nts! nt (cons src (rhs-nts nt))))]
|
||||
[crossover '()]
|
||||
;; crossover is set of tvars with tvar_L and tvar_U nonempty
|
||||
[AV-w/-const '()]
|
||||
)
|
||||
(letrec
|
||||
( [add-crossover!
|
||||
(lambda (tvar)
|
||||
(set! crossover (cons tvar crossover)))]
|
||||
[walk-AV
|
||||
(lambda (AV src)
|
||||
(pretty-debug-min `(walk-AV ,(AV-num AV) ,(nt->sym src)))
|
||||
(if (reached-AV? AV)
|
||||
(add-rhs-nt! (AV-U AV) src)
|
||||
;; Walk it
|
||||
(begin
|
||||
(set-reached-AV! AV #t)
|
||||
(mk-AV-NTs! AV)
|
||||
(let ([nt (AV-U AV)])
|
||||
(set-rhs-nts! nt (list src))
|
||||
(match AV
|
||||
[($ AV _ (and template ($ template _ _ _ ref))
|
||||
misc fields+ fields-)
|
||||
(when (or
|
||||
(zero? (vector-length ref))
|
||||
;; the following are lazy
|
||||
;; ie (box empty) = empty
|
||||
;; but (empty -> empty) != empty
|
||||
(eq? template template-lam)
|
||||
(eq? template template-unit)
|
||||
(eq? template template-internal-class)
|
||||
(eq? template template-ivarset)
|
||||
)
|
||||
(set! AV-w/-const (cons AV AV-w/-const)))
|
||||
(vector-for-each
|
||||
(lambda (f) (walk-U f nt))
|
||||
fields+)
|
||||
(when (follow-antimono-fields template)
|
||||
(pretty-debug-min
|
||||
`(walking-U
|
||||
,(eq? template template-lam)
|
||||
,(st:minimize-respect-assignable-part-of-fields)))
|
||||
(vector-for-each
|
||||
(lambda (f) (walk-L f nt))
|
||||
fields-))])))))]
|
||||
[reach-tvar
|
||||
(lambda (tvar)
|
||||
(unless (reached-tvar? tvar)
|
||||
(set-reached-tvar! tvar #t)
|
||||
(mk-Tvar-NTs! tvar)))]
|
||||
[walk-U
|
||||
(lambda (tvar src)
|
||||
(let
|
||||
([f
|
||||
(lambda (tvar)
|
||||
(reach-tvar tvar)
|
||||
(pretty-debug-min `(walk-U ,(Tvar-name tvar) ,(nt->sym src)))
|
||||
(let ([nt (Tvar-U tvar)])
|
||||
(if (rhs-nts nt)
|
||||
(add-rhs-nt! nt src)
|
||||
;; Walk it
|
||||
(begin
|
||||
(set-rhs-nts! nt (list src))
|
||||
(when (rhs-nts (Tvar-L tvar)) (add-crossover! tvar))
|
||||
(pretty-debug-min `(walk-U ,(Tvar-name tvar)))
|
||||
(for-each
|
||||
(lambda (AV) (walk-AV AV nt))
|
||||
(get-Tvar-objs tvar))
|
||||
'(unless inline-epsilon
|
||||
(for-each
|
||||
(lambda (from)
|
||||
(walk-U from nt))
|
||||
(Tvar-edgefrom tvar)))))))])
|
||||
|
||||
'(if inline-epsilon
|
||||
;; really want to walk all tvar2 st tvar2_U -> tvar_U
|
||||
(for-each f (Tvar-transitive-edgefrom tvar))
|
||||
(f tvar))
|
||||
(f tvar)))]
|
||||
|
||||
[walk-L
|
||||
(lambda (tvar src)
|
||||
(let
|
||||
([f (lambda (tvar)
|
||||
(reach-tvar tvar)
|
||||
(pretty-debug-min
|
||||
`(walk-L ,(Tvar-name tvar) ,(nt->sym src)))
|
||||
(let ([nt (Tvar-L tvar)])
|
||||
(if (rhs-nts nt)
|
||||
(add-rhs-nt! nt src)
|
||||
;; Walk it
|
||||
(begin
|
||||
(set-rhs-nts! nt (list src))
|
||||
(when (rhs-nts (Tvar-U tvar)) (add-crossover! tvar))
|
||||
(pretty-debug-min `(walk-L ,(Tvar-name tvar)))
|
||||
|
||||
(unless inline-epsilon
|
||||
(for-each
|
||||
(lambda (to)
|
||||
;; Have to_L -> tvar_L
|
||||
(walk-L to nt))
|
||||
(Tvar-edgeto tvar)))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ _ field-no tvar2 sign misc)
|
||||
;; Have tvar2_L -> rng(tvar_L)
|
||||
;; or tvar2_U -> dom(tvar_L)
|
||||
(if sign
|
||||
(walk-L tvar2 nt)
|
||||
(walk-U tvar2 nt))]
|
||||
[($ con-filter _ filter tvar2)
|
||||
;; Have tvar2_L -> tvar_L
|
||||
(unless inline-epsilon (walk-L tvar2 nt))])
|
||||
(Tvar-constraints tvar))))))])
|
||||
'(if inline-epsilon
|
||||
;; really want to walk all tvar2 st tvar2_L -> tvar_L
|
||||
(for-each f (Tvar-transitive-edgeto tvar))
|
||||
(f tvar))
|
||||
(f tvar)))])
|
||||
|
||||
(for-each (lambda (tvar) (walk-U tvar #t)) upper)
|
||||
(for-each (lambda (tvar) (walk-L tvar #t)) lower)
|
||||
|
||||
(min-record-progress 'find-nonempty-nts-rhs-nts-done)
|
||||
(: rhs-nts (NT -> (union NT true)))
|
||||
|
||||
(pretty-debug-min
|
||||
`(find-nonempty-nts-rhs-nts-returns
|
||||
,(map AV-num AV-w/-const)
|
||||
,(map Tvar-name crossover)))
|
||||
|
||||
(values
|
||||
(lambda (nt)
|
||||
(let ([r (rhs-nts nt)])
|
||||
(pretty-debug-min
|
||||
`(rhs-nts ,(nt->sym nt)
|
||||
,(map (lambda (nt) (or (eq? nt #t) (nt->sym nt))) r)))
|
||||
r))
|
||||
crossover
|
||||
AV-w/-const))))
|
||||
|
||||
;; ======================================================================
|
||||
; copy-constraints!
|
||||
;
|
||||
; tvar->equiv and AV->equiv describe an equivalence relation on tvars and AVs
|
||||
;
|
||||
; Copies the contents of a set of Tvars
|
||||
; Takes care not to duplicate AVs
|
||||
; returns (values nu-tvars tvar->nu-tvar)
|
||||
; live-tvars should include lower and upper, and may contain duplicates
|
||||
|
||||
(define (copy-constraints-equiv!
|
||||
live-tvars live-tvar? live-nts
|
||||
tvar->equiv AV->equiv)
|
||||
|
||||
(pretty-debug-min `(copy-constraints-equiv! ,(map nt->sym live-nts)))
|
||||
(let*-vals
|
||||
( [t (lambda (s)
|
||||
(when timing-min
|
||||
(min-record-progress (cons 'copy-constraint-equivs! s))))]
|
||||
[_ (t 0)]
|
||||
|
||||
;; --- Allocate new tvar
|
||||
[(Tvar-nuTvar set-Tvar-nuTvar!) (alloc-Tvar-field)]
|
||||
[list-nu-tvars '()]
|
||||
[_ (for-each
|
||||
(lambda (tvar)
|
||||
(unless (Tvar-nuTvar tvar)
|
||||
(let ([nu (mk-Tvar 'copy-constraints!)])
|
||||
(set! list-nu-tvars (cons nu list-nu-tvars))
|
||||
(for-each
|
||||
(lambda (tvar2) (set-Tvar-nuTvar! tvar2 nu))
|
||||
(tvar->equiv tvar)))))
|
||||
live-tvars)]
|
||||
[_ (t 1)]
|
||||
|
||||
[Tvar->nuTvar
|
||||
(lambda (Tvar)
|
||||
(if (live-tvar? Tvar)
|
||||
(let ([nu (Tvar-nuTvar Tvar)])
|
||||
(assert (Tvar? nu) 'Tvar->nuTvar
|
||||
nu (live-tvar? Tvar) (memq Tvar live-tvars))
|
||||
nu)
|
||||
(let ([dummy (mk-Tvar 'dummy)])
|
||||
(set! list-nu-tvars (cons dummy list-nu-tvars))
|
||||
dummy)))]
|
||||
|
||||
[(AV-nuAV set-AV-nuAV!) (alloc-AV-field)]
|
||||
[copy-AV
|
||||
(lambda (AV)
|
||||
(or
|
||||
(AV-nuAV AV)
|
||||
(match AV
|
||||
[(and AV ($ AV _ template misc fields+ fields-))
|
||||
(let*
|
||||
( [nu-fields+ (vector-map Tvar->nuTvar fields+)]
|
||||
[nu-fields- (vector-map Tvar->nuTvar fields-)]
|
||||
[nu-AV (create-AV template misc nu-fields+ nu-fields-)])
|
||||
(set-AV-nuAV! AV nu-AV)
|
||||
(for-each
|
||||
(lambda (eq-AV)
|
||||
(when (and
|
||||
(not (AV-nuAV eq-AV))
|
||||
(eq? (AV-template eq-AV) template)
|
||||
(vector-andmap2 eq? nu-fields+
|
||||
(vector-map Tvar->nuTvar (AV-fields+ eq-AV)))
|
||||
'(vector-andmap2 eq? nu-fields-
|
||||
(vector-map Tvar->nuTvar (AV-fields- eq-AV))))
|
||||
(set-AV-nuAV! eq-AV nu-AV)))
|
||||
(AV->equiv AV))
|
||||
nu-AV)])))]
|
||||
[_ (t 1.1)])
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ NT source LU)
|
||||
(when (Tvar? source)
|
||||
(let ([dest (Tvar->nuTvar source)])
|
||||
(case LU
|
||||
[(U)
|
||||
;; --- AVs
|
||||
(for-each (lambda (AV) (new-AV! dest (copy-AV AV)))
|
||||
(Tvar-objs source))]
|
||||
[(L)
|
||||
;; --- Constraints
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ template field-no Tvar sign)
|
||||
(when (live-tvar? Tvar)
|
||||
(new-con! dest
|
||||
(create-con template field-no
|
||||
(Tvar->nuTvar Tvar) sign)))]
|
||||
[($ con-filter _ filter Tvar)
|
||||
(when (live-tvar? Tvar)
|
||||
;; (new-con! dest
|
||||
;; (create-con-filter filter (Tvar->nuTvar Tvar))
|
||||
(new-edge! dest (Tvar->nuTvar Tvar)))])
|
||||
(Tvar-constraints source))
|
||||
|
||||
;; --- Edges
|
||||
(for-each
|
||||
(lambda (Tvar2)
|
||||
(when (live-tvar? Tvar2)
|
||||
(let ([nu (Tvar->nuTvar Tvar2)])
|
||||
(unless (eq? dest nu)
|
||||
(new-edge! dest nu)))))
|
||||
(Tvar-edgeto source))])))])
|
||||
live-nts)
|
||||
(t 2)
|
||||
|
||||
(pretty-debug-min
|
||||
`(copy-constraints-equiv!
|
||||
old->new
|
||||
,(map
|
||||
(lambda (tvar)
|
||||
(list (Tvar-name tvar) (Tvar-name (Tvar-nuTvar tvar))))
|
||||
live-tvars)))
|
||||
|
||||
|
||||
(values list-nu-tvars Tvar-nuTvar)))
|
||||
|
||||
;; ======================================================================
|
||||
; copy-constraints-noe!
|
||||
;
|
||||
; Copies the contents of a set of Tvars
|
||||
; Does closure under epsilon
|
||||
; Takes care not to add duplicate AVs
|
||||
; But may make many copies of the same AV in different Tvar
|
||||
|
||||
(define (copy-constraints-noe! live-tvar? live-nts Tvar-nuTvar lower)
|
||||
(pretty-debug-min
|
||||
`(copy-constraints-noe!
|
||||
live-nts
|
||||
,(map nt->sym live-nts)
|
||||
lower
|
||||
,(map Tvar-name lower)
|
||||
conversion
|
||||
,(map
|
||||
(lambda (tvar)
|
||||
(list (Tvar-name tvar) (Tvar-name (Tvar-nuTvar tvar))))
|
||||
(filter Tvar? (map NT-tvar live-nts)))))
|
||||
'(let*-vals
|
||||
( [(AV-nuAV set-AV-nuAV!) (alloc-AV-field)]
|
||||
[dummy-tvars '()]
|
||||
[mk-dummy-tvar
|
||||
(lambda ()
|
||||
(let ([dummy (mk-Tvar 'dummy)])
|
||||
(set! dummy-tvars (cons dummy dummy-tvars))
|
||||
dummy))]
|
||||
[Tvar->nuTvar
|
||||
(lambda (Tvar)
|
||||
(if (live-tvar? Tvar)
|
||||
(Tvar-nuTvar Tvar)
|
||||
(mk-dummy-tvar)))]
|
||||
[table '()]
|
||||
[Tvar*->nuTvar
|
||||
(lambda (Tvar*)
|
||||
(let* ( [Tvar* (if (Tvar? Tvar*) (list Tvar*) Tvar*)]
|
||||
[nu-Tvar*
|
||||
(list->set
|
||||
(filter-map
|
||||
(lambda (Tvar)
|
||||
(if (live-tvar? Tvar) (Tvar->nuTvar Tvar) #f))
|
||||
Tvar*))])
|
||||
(match nu-Tvar*
|
||||
[() (mk-dummy-tvar)]
|
||||
[(Tvar) Tvar]
|
||||
[_ (or (ormap
|
||||
(match-lambda
|
||||
[(Tvar2* . nu)
|
||||
(if (set-eq? Tvar2* nu-Tvar*) nu #f)])
|
||||
table)
|
||||
(let ([nu (mk-Tvar 'multiple)])
|
||||
(set! table (cons (cons nu-Tvar* nu) table))
|
||||
(for-each (lambda (to) (new-edge! nu to)) nu-Tvar*)
|
||||
nu))])))]
|
||||
[tag-reached-AV (gensym)])
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ NT source LU)
|
||||
(when (Tvar? source)
|
||||
(pretty-debug-min `(copying ,(Tvar-name source)))
|
||||
(let ([dest (Tvar->nuTvar source)])
|
||||
(case LU
|
||||
[(U)
|
||||
;; --- AVs
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV
|
||||
($ AV _
|
||||
(and template ($ template _ signs)) misc fields))
|
||||
|
||||
(pretty-debug-min `(AV ,(Tvar-name dest)
|
||||
,(vector-map Tvar-name fields)))
|
||||
|
||||
(new-AV! dest
|
||||
(or (AV-nuAV AV)
|
||||
(let* ([nu-fields
|
||||
(vector-map
|
||||
(lambda (sign field)
|
||||
(if sign
|
||||
(Tvar->nuTvar field)
|
||||
(Tvar*->nuTvar
|
||||
(Tvar-transitive-edgeto field))))
|
||||
signs fields)]
|
||||
[nu-AV (create-AV template misc nu-fields)])
|
||||
(set-AV-nuAV! AV nu-AV)
|
||||
nu-AV)))])
|
||||
(Tvar-objs source))]
|
||||
|
||||
[(L)
|
||||
;; --- Constraints
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ template field-no Tvar)
|
||||
(for-each
|
||||
(lambda (Tvar)
|
||||
(when (live-tvar? Tvar)
|
||||
(new-con! dest
|
||||
(create-con template field-no
|
||||
(Tvar->nuTvar Tvar)))))
|
||||
(if (vector-ref (template-signs template) field-no)
|
||||
(Tvar-transitive-edgeto Tvar)
|
||||
(list Tvar)
|
||||
;;(Tvar-transitive-edgefrom Tvar)
|
||||
))]
|
||||
[($ con-filter _ filter Tvar)
|
||||
;; Was treated as edge
|
||||
(void)])
|
||||
(Tvar-constraints source))])))])
|
||||
live-nts)
|
||||
|
||||
(for-each
|
||||
(lambda (L)
|
||||
(let ([nu-L (Tvar->nuTvar L)])
|
||||
(for-each
|
||||
(lambda (to)
|
||||
(when (live-tvar? to)
|
||||
(let ([nu-to (Tvar->nuTvar to)])
|
||||
(unless (eq? nu-L nu-to)
|
||||
(new-edge! nu-L nu-to)))))
|
||||
(Tvar-transitive-edgeto L))))
|
||||
lower)
|
||||
|
||||
(append dummy-tvars (map cdr table))))
|
||||
|
||||
;; ======================================================================
|
@ -0,0 +1,236 @@
|
||||
; min.ss
|
||||
; Purpose: Minimize a set of constraints.
|
||||
; ======================================================================
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
; minimize-constraints-&-compare
|
||||
; minimizes a constraint system
|
||||
; Input: which : 'live or 'dfa-min
|
||||
; lower : list Tvar
|
||||
; upper : list Tvar
|
||||
; l1 ... l2 : ftypes in uncompresssed set of constraints
|
||||
|
||||
; Returns (list-ftype Tvar->nuTvar)
|
||||
;; ----------------------------------------
|
||||
|
||||
(define global-lower (void))
|
||||
(define global-upper (void))
|
||||
(define global-all-which (void))
|
||||
|
||||
(define (minimize-constraints-&-compare all-which lower upper l1 l2)
|
||||
(set! global-lower lower)
|
||||
(set! global-upper upper)
|
||||
(set! global-all-which all-which)
|
||||
(when (st:compare-min-algs)
|
||||
;; Compare algorithms
|
||||
(let* ( [alg-width 32]
|
||||
[calc-sizes
|
||||
(lambda (rep)
|
||||
(pretty-debug-min2 `(calc-sizes ,(map Tvar-name rep)))
|
||||
(let*-vals
|
||||
( [n-f (length rep)]
|
||||
[AV-added (apply append (map get-Tvar-objs rep))]
|
||||
[n-AV-added (length AV-added)]
|
||||
[n-AV (length (list->set AV-added))]
|
||||
[n-edge (length (apply append (map Tvar-edgeto rep)))]
|
||||
[n-con (length (apply append (map Tvar-constraints rep)))]
|
||||
[size (+ n-edge n-con n-AV-added)])
|
||||
(list size n-f n-AV n-AV-added n-edge n-con)))]
|
||||
[show-sizes
|
||||
(lambda (alg orig-size t size n-f n-AV n-AV-added n-edge n-con)
|
||||
(if (zero? size)
|
||||
(error 'minimize-constraints-&-compare
|
||||
"Algorithm ~s returns empty constraint system~n" alg)
|
||||
(printf
|
||||
"~a: ~a ~a ~a ~a ~a ~a ~a ~a~n"
|
||||
(padr alg alg-width)
|
||||
(padl
|
||||
(/ (round (* (exact->inexact (/ orig-size size)) 10)) 10)
|
||||
6)
|
||||
(padl size 5)
|
||||
(padl n-f 5)
|
||||
(padl n-AV 3)
|
||||
(padl n-AV-added 5)
|
||||
(padl n-edge 5)
|
||||
(padl n-con 4)
|
||||
(padl t 5))))]
|
||||
[orig-sizes (calc-sizes (filter Tvar? (get-prefix l1 l2)))]
|
||||
[orig-size (car orig-sizes)])
|
||||
'(pretty-debug `(minimize-constraints-&-compare
|
||||
,(map Tvar-name lower) ,(map Tvar-name upper)))
|
||||
(printf "~n~a: factor size Tvar AV AV-a edge con time~n"
|
||||
(padr "Algorithm" alg-width))
|
||||
(apply show-sizes "" orig-size 0 orig-sizes)
|
||||
(for-each
|
||||
(lambda (p)
|
||||
(let*-vals
|
||||
( [thunk
|
||||
(lambda ()
|
||||
(let-values
|
||||
([(rep _)
|
||||
(minimize-constraints p lower upper l1 l2)])
|
||||
rep))]
|
||||
[(rep t real-t) (time-apply thunk)]
|
||||
[sizes (calc-sizes rep)])
|
||||
(apply show-sizes p orig-size t sizes)))
|
||||
min-algs-to-compare)))
|
||||
|
||||
(minimize-constraints all-which lower upper l1 l2))
|
||||
|
||||
;; ----------
|
||||
|
||||
(define min-algs-to-compare
|
||||
'( ;(none)
|
||||
(nonempty)
|
||||
(nonempty live)
|
||||
(live)
|
||||
;(live-no-epsilon)
|
||||
(live-few-e)
|
||||
;(live-few-e-L)
|
||||
;(live-few-e-U)
|
||||
;(live-no-epsilon dfa-min)
|
||||
;(live-no-epsilon dfa-min-inv)
|
||||
;(live-few-e dfa-min)
|
||||
;(live-few-e dfa-min-inv)
|
||||
;(live-few-e dfa-min-inv dfa-min)
|
||||
;(live-few-e dfa-min dfa-min-inv)
|
||||
|
||||
;(live-no-epsilon dfa-min-1)
|
||||
;(live-no-epsilon dfa-min-2)
|
||||
|
||||
;(live-few-e dfa-min-1)
|
||||
;(live-few-e dfa-min-2)
|
||||
;(live-few-e dfa-min-1 live-few-e dfa-min-2)
|
||||
;(live-few-e dfa-min-2 live-few-e dfa-min-1)
|
||||
|
||||
(dfa-min-lub)
|
||||
(dfa-min-glb)
|
||||
(dfa-min-lub dfa-min-glb)
|
||||
(dfa-min-glb dfa-min-lub)
|
||||
(dfa-min-lub dfa-min-glb dfa-min-lub)
|
||||
(dfa-min-glb dfa-min-lub dfa-min-glb)
|
||||
;(live-few-e dfa-min-1 live-no-epsilon dfa-min-2 live-no-epsilon dfa-min-1)
|
||||
;(live-few-e dfa-min-2 live-no-epsilon dfa-min-1 live-no-epsilon dfa-min-2)
|
||||
;(live-no-epsilon min-table)
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define min-time-base 0)
|
||||
(define min-time-record '())
|
||||
(define (min-record-progress what)
|
||||
(set! min-time-record
|
||||
(cons (cons what (current-process-milliseconds)) min-time-record)))
|
||||
(define (show-record-progress)
|
||||
(pretty-debug
|
||||
(map (match-lambda
|
||||
[(what . when) (list what (- when min-time-base))])
|
||||
(reverse min-time-record))))
|
||||
;; ----------
|
||||
|
||||
(define (minimize-constraints all-which lower upper l1 l2)
|
||||
(pretty-debug-min2
|
||||
`(input
|
||||
all-which ,all-which
|
||||
lower ,(map Tvar-name lower)
|
||||
upper ,(map Tvar-name upper)))
|
||||
|
||||
(set! min-time-record '())
|
||||
(set! min-time-base (current-process-milliseconds))
|
||||
(recur loop ( [which all-which]
|
||||
[lower lower]
|
||||
[upper upper]
|
||||
[Tvar->nuTvar (lambda (x) x)])
|
||||
(match which
|
||||
[(which . (and rest (_ . _)))
|
||||
(let*-vals
|
||||
([(rep-Tvar1 Tvar->nuTvar1)
|
||||
(minimize-constraints-nocount which lower upper l1 l2)])
|
||||
(loop rest
|
||||
(map Tvar->nuTvar1 lower)
|
||||
(map Tvar->nuTvar1 upper)
|
||||
(lambda (Tvar) (Tvar->nuTvar1 (Tvar->nuTvar Tvar)))))]
|
||||
[(or (which) (? symbol? which))
|
||||
(let*-vals
|
||||
([(rep-Tvar Tvar-nuTvar1)
|
||||
(minimize-constraints-nocount which lower upper l1 l2)])
|
||||
|
||||
(when timing-min (show-record-progress))
|
||||
|
||||
(pretty-debug-min2
|
||||
`(output lower ,(map Tvar-name (map Tvar-nuTvar1 lower))
|
||||
upper ,(map Tvar-name (map Tvar-nuTvar1 upper))))
|
||||
|
||||
(values
|
||||
rep-Tvar
|
||||
(lambda (Tvar) (Tvar-nuTvar1 (Tvar->nuTvar Tvar)))))])))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (minimize-constraints-nocount which lower upper l1 l2)
|
||||
(pretty-debug-min
|
||||
`(minimize-constraints-nocount which ,which
|
||||
lower ,(map Tvar-name lower)
|
||||
upper ,(map Tvar-name upper)))
|
||||
(check-kernel-ok)
|
||||
(pretty-debug-min `(minimize-constraints-nocount kernel-ok))
|
||||
(let*-values
|
||||
([(A B)
|
||||
(case which
|
||||
[(none) (values
|
||||
(filter Tvar? (get-prefix l1 l2))
|
||||
(lambda (Tvar) Tvar))]
|
||||
[(nonempty) (let*-vals
|
||||
([(live-tvars _ _)
|
||||
(find-nonempty-tvars lower upper)])
|
||||
(values
|
||||
live-tvars
|
||||
(lambda (tvar) tvar)))]
|
||||
[(nonempty-copy) (copy-nonempty-tvars lower upper)]
|
||||
[(live) (copy-live-constraints lower upper)]
|
||||
[(live-no-epsilon) (copy-live-constraints-noe lower upper)]
|
||||
|
||||
[(live-few-e)
|
||||
(call-with-values
|
||||
(lambda () ((copy-live-constraints-few-e #t #t) lower upper))
|
||||
copy-constraints-equiv!)]
|
||||
[(live-few-e-L)
|
||||
(call-with-values
|
||||
(lambda () ((copy-live-constraints-few-e #t #f) lower upper))
|
||||
copy-constraints-equiv!)]
|
||||
[(live-few-e-U)
|
||||
(call-with-values
|
||||
(lambda () ((copy-live-constraints-few-e #f #t) lower upper))
|
||||
copy-constraints-equiv!)]
|
||||
;[dfa-min (minimize-constraints-dfa-min lower upper)]
|
||||
;[dfa-min-inv (minimize-constraints-dfa-min-inv lower upper)]
|
||||
;[dfa-min-1 (minimize-constraints-dfa-min-1 lower upper)]
|
||||
;[dfa-min-2 (minimize-constraints-dfa-min-2 lower upper)]
|
||||
[(dfa-min-lub) (minimize-constraints-dfa-min-lub lower upper)]
|
||||
[(dfa-min-glb) (minimize-constraints-dfa-min-glb lower upper)]
|
||||
;[min-table (min-table lower upper)]
|
||||
[else (error 'minimize-constraints-nocount "Bad which ~s" which)])])
|
||||
(check-kernel-ok)
|
||||
(pretty-debug-min `(minimize-constraints-nocount kernel-ok2))
|
||||
(min-record-progress 'minimize-constraints-nocount-returning)
|
||||
(values A B)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,105 @@
|
||||
; ======================================================================
|
||||
; find-nonempty-tvars
|
||||
;
|
||||
; Input: lower : (listof Tvar) with non-empty Tvar_L
|
||||
; upper : (listof Tvar) with non-empty Tvar_U
|
||||
;
|
||||
; Finds non-empty non-terminals
|
||||
; returns (listof Tvar)
|
||||
; ======================================================================
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (find-nonempty-tvars lower upper)
|
||||
(pretty-debug-min
|
||||
`(find-nonempty-tvars ,(map Tvar-name lower) ,(map Tvar-name upper)))
|
||||
|
||||
(let*-vals ( [(reached-U? set-reached-U!) (alloc-Tvar-field)]
|
||||
[(reached-L? set-reached-L!) (alloc-Tvar-field)]
|
||||
[(reached-AV set-reached-AV!) (alloc-AV-field)]
|
||||
[num-AV 0]
|
||||
[list-tvar '()])
|
||||
(letrec
|
||||
( [add-Tvar!
|
||||
(lambda (tvar)
|
||||
(set! list-tvar (cons tvar list-tvar)))]
|
||||
[walk-AV
|
||||
(lambda (AV)
|
||||
(unless (reached-AV AV)
|
||||
;; Walk it
|
||||
(set-reached-AV! AV #t)
|
||||
(match AV
|
||||
[($ AV _ template _ fields+ fields-)
|
||||
(vector-for-each walk-U fields+)
|
||||
(when (follow-antimono-fields template)
|
||||
(pretty-debug-min
|
||||
`(walking-U
|
||||
,(eq? template template-lam)
|
||||
,(st:minimize-respect-assignable-part-of-fields)))
|
||||
(vector-for-each walk-U fields-))])))]
|
||||
[walk-U
|
||||
(lambda (tvar)
|
||||
(unless (reached-U? tvar)
|
||||
(unless (reached-L? tvar) (add-Tvar! tvar))
|
||||
(set-reached-U! tvar #t)
|
||||
(pretty-debug-min `(walk-U ,(Tvar-name tvar)))
|
||||
(for-each walk-AV (get-Tvar-objs tvar))
|
||||
(for-each walk-U (Tvar-edgefrom tvar))))]
|
||||
[walk-L
|
||||
(lambda (tvar)
|
||||
(unless (reached-L? tvar)
|
||||
(unless (reached-U? tvar) (add-Tvar! tvar))
|
||||
(set-reached-L! tvar #t)
|
||||
(pretty-debug-min `(walk-L ,(Tvar-name tvar)))
|
||||
;; Have to_L -> tvar_L
|
||||
(for-each walk-L (Tvar-edgeto tvar))
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ con _ _ field-no tvar2 sign misc)
|
||||
;; Have tvar2_L -> rng(tvar_L)
|
||||
;; or tvar2_U -> dom(tvar_L)
|
||||
(if sign
|
||||
(walk-L tvar2)
|
||||
(walk-U tvar2))]
|
||||
[($ con-filter _ filter tvar2)
|
||||
;; Have tvar2_L -> tvar_L
|
||||
(walk-L tvar2)])
|
||||
(Tvar-constraints tvar))))])
|
||||
(for-each walk-U upper)
|
||||
(for-each walk-L lower)
|
||||
'(printf "walk-reachable-constraints allocated ~s tvar, ~s AV~n"
|
||||
(length list-tvar) num-AV)
|
||||
|
||||
(values list-tvar reached-L? reached-U?))))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define (copy-nonempty-tvars lower upper)
|
||||
(let*-vals
|
||||
( [(live-tvars _ _) (find-nonempty-tvars lower upper)]
|
||||
[(tvar-live? set-tvar-live!) (alloc-Tvar-field)])
|
||||
(for-each mk-Tvar-NTs! live-tvars)
|
||||
(for-each (lambda (tvar) (set-tvar-live! tvar #t)) live-tvars)
|
||||
(copy-constraints-equiv!
|
||||
(append lower upper live-tvars)
|
||||
tvar-live?
|
||||
(append
|
||||
(map Tvar-L live-tvars)
|
||||
(map Tvar-U live-tvars))
|
||||
(lambda (tvar) (list tvar))
|
||||
(lambda (AV) (list AV)))))
|
@ -0,0 +1,46 @@
|
||||
(let ([gen:477:join-env (void)]
|
||||
[gen:473:extend-env* (void)]
|
||||
[gen:476:extend-env (void)]
|
||||
[gen:474:lookup (void)]
|
||||
[gen:475:empty-env (void)])
|
||||
(begin (set! gen:475:empty-env '())
|
||||
(begin (set! gen:474:lookup
|
||||
(lambda (gen:493:env gen:492:x)
|
||||
(let ([gen:494:r (assq gen:492:x gen:493:env)])
|
||||
(if (eq? gen:494:r '#f)
|
||||
(error 'lookup '"no binding for ~a" gen:492:x)
|
||||
(cdr gen:494:r)))))
|
||||
(begin (set! gen:476:extend-env
|
||||
(lambda (gen:491:env gen:489:x gen:490:v)
|
||||
(cons (cons gen:489:x gen:490:v) gen:491:env)))
|
||||
(begin (set! gen:473:extend-env*
|
||||
(lambda (gen:488:env gen:486:xs gen:487:vs)
|
||||
(append (map2 cons gen:486:xs gen:487:vs) gen:488:env)))
|
||||
(begin (set! gen:477:join-env
|
||||
(lambda (gen:485:env gen:484:newenv)
|
||||
(append gen:484:newenv gen:485:env)))
|
||||
(make-rs:module
|
||||
(lambda (gen:478:msg)
|
||||
(let ([gen:479:%%tmp gen:478:msg])
|
||||
(if (memv gen:479:%%tmp '(empty-env))
|
||||
gen:475:empty-env
|
||||
(let ([gen:480:%%tmp gen:478:msg])
|
||||
(if (memv gen:480:%%tmp '(lookup))
|
||||
gen:474:lookup
|
||||
(let ([gen:481:%%tmp gen:478:msg])
|
||||
(if (memv gen:481:%%tmp '(extend-env))
|
||||
gen:476:extend-env
|
||||
(let ([gen:482:%%tmp gen:478:msg])
|
||||
(if (memv gen:482:%%tmp '(extend-env*))
|
||||
gen:473:extend-env*
|
||||
(let ([gen:483:%%tmp gen:478:msg])
|
||||
(if (memv gen:483:%%tmp '(join-env))
|
||||
gen:477:join-env
|
||||
(error 'import
|
||||
'"attempting to import ~s~n from module with signature ~s"
|
||||
gen:478:msg
|
||||
'(empty-env
|
||||
lookup
|
||||
extend-env
|
||||
extend-env*
|
||||
join-env))))))))))))))))))))
|
@ -0,0 +1,59 @@
|
||||
; ======================================================================
|
||||
;; NFA->DFA
|
||||
;; roots: (list nt)
|
||||
;; final: (list nt)
|
||||
;; returns (list (list AVS) (list AVS))
|
||||
|
||||
(define (NFA->DFA for-each-prod roots final)
|
||||
;; n is an old nt
|
||||
;; d is new nt
|
||||
(letrec
|
||||
([n*->d '()] ; Maps set of NFA nts to a DFA nt
|
||||
[n*<=
|
||||
(lambda (n1* n2*)
|
||||
(andmap (lambda (n1) (mem-nt? n1 n2*)) n1*))]
|
||||
[n*=
|
||||
(lambda (n1* n2*)
|
||||
(and (n*<= n1* n2*) (n*<= n2* n1*)))]
|
||||
[lookup
|
||||
(lambda (n*)
|
||||
(recur loop ([l n*->d])
|
||||
(cond
|
||||
[(null? l) #f]
|
||||
[(n*= n* (caar l)) (cdar l)]
|
||||
[else (loop (cdr l))])))]
|
||||
[traverse
|
||||
(lambda (n*)
|
||||
(or (lookup n*)
|
||||
;; Need to traverse
|
||||
;; think about epsilon-closure
|
||||
(let* ([rhs* '()]
|
||||
[_ (for-each
|
||||
(lambda (n)
|
||||
(for-each-prod
|
||||
(lambda (rhs) (set! rhs* (cons rhs rhs*)))
|
||||
n))
|
||||
n*)]
|
||||
[d (mk-AVS-nolist 'dfa)])
|
||||
(set! n*->d (cons (cons n* d) n*->d))
|
||||
(recur loop ([rhs* rhs*])
|
||||
(match rhs*
|
||||
[() (void)]
|
||||
[(($ rhs grsym nt) . _)
|
||||
;; Merge all with same grsym
|
||||
(match-let*
|
||||
([(nt* . rest)
|
||||
(filter-map-split
|
||||
(match-lambda
|
||||
[($ rhs grsym2 nt2)
|
||||
(if (grsym-eq? grsym grsym2)
|
||||
nt2
|
||||
#f)])
|
||||
rhs*)])
|
||||
(add-prod! d (make-rhs grsym (traverse nt*)))
|
||||
(loop rest))]))
|
||||
d)))])
|
||||
(traverse (list AVS))
|
||||
(list (map (lambda (r) (lookup (list r))) roots)
|
||||
(map (lambda (r) (lookup (list r))) final))))
|
||||
|
@ -0,0 +1,489 @@
|
||||
;; parser.ss
|
||||
;;
|
||||
;; Takes a zodiac:sexp, and an env: sym -> zodiac:bound,
|
||||
;; and produces a zodiac:ast and a list of unbound zodiac:bounds
|
||||
;; Only handles R4RS primitive syntax
|
||||
;; ======================================================================
|
||||
|
||||
(define keywords
|
||||
'(begin cond delay if set! set!-values quote begin lambda case-lambda
|
||||
poly
|
||||
let-values letrec*-values
|
||||
unit compound-unit invoke-unit
|
||||
: type:-quote
|
||||
cache-exp-quote cache-inv-quote
|
||||
struct typed-structure const-typed-structure
|
||||
))
|
||||
|
||||
(define define-keywords
|
||||
'(define-values
|
||||
define-type
|
||||
define-constructor
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (top-level-parse-defs defs)
|
||||
(set! unbound-env '())
|
||||
(let-values ([(defs nuenv) (parse-defs defs empty-env)])
|
||||
(values defs (map cdr unbound-env))))
|
||||
|
||||
(define (top-level-parse-exp exp)
|
||||
(set! unbound-env '())
|
||||
(let ([ast (parse exp empty-env)])
|
||||
(values ast (map cdr unbound-env))))
|
||||
|
||||
(define unbound-env '())
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define syntax-error
|
||||
(case-lambda
|
||||
[(exp) (syntax-error exp "Bad syntax")]
|
||||
[(exp s)
|
||||
(mrspidey:error
|
||||
(format "File ~s, Line ~s: ~a ~s"
|
||||
(file-name-from-path
|
||||
(zodiac:location-file (zodiac:zodiac-start exp)))
|
||||
(zodiac:location-line (zodiac:zodiac-start exp))
|
||||
s (zodiac:stripper exp)))]))
|
||||
|
||||
(define syntax-error-no-exp
|
||||
(case-lambda
|
||||
[(exp) (syntax-error-no-exp exp "Bad syntax")]
|
||||
[(exp s)
|
||||
(mrspidey:error
|
||||
(format "File ~s, Line ~s: ~as"
|
||||
(file-name-from-path
|
||||
(zodiac:location-file (zodiac:zodiac-start exp)))
|
||||
(zodiac:location-line (zodiac:zodiac-start exp))
|
||||
s))]))
|
||||
|
||||
(define assert-syn
|
||||
(case-lambda
|
||||
[(exp x) (assert-syn exp x "Bad syntax")]
|
||||
[(exp x s) (unless x (syntax-error exp s))]))
|
||||
|
||||
(define parse-body
|
||||
(lambda (o s f body env)
|
||||
(assert (list? body))
|
||||
(recur loop ([rest body])
|
||||
(match rest
|
||||
[(exp) (parse exp env)]
|
||||
[(exp . rest)
|
||||
(zodiac:make-begin-form o s f (box 0)
|
||||
(parse exp env)
|
||||
(loop rest))]))))
|
||||
|
||||
(define do-bindings
|
||||
(lambda (env syms)
|
||||
(assert (list? syms))
|
||||
(let* ([bindings
|
||||
(map
|
||||
(match-lambda
|
||||
[($ zodiac:symbol o s f sym)
|
||||
(let ([bound (zodiac:make-bound o s f (box 0) sym sym)])
|
||||
(cons sym bound))]
|
||||
[exp (syntax-error exp "Bad binding syntax")])
|
||||
syms)]
|
||||
[syms (map car bindings)]
|
||||
[bounds (map cdr bindings)]
|
||||
[nuenv (extend-env* env syms bounds)])
|
||||
(values bounds nuenv))))
|
||||
|
||||
(define do-bindingss
|
||||
(lambda (env symss)
|
||||
(recur loop ([env env][symss symss][boundss '()])
|
||||
(if (null? symss)
|
||||
(values (reverse boundss) env)
|
||||
(let-values
|
||||
([(bounds env) (do-bindings env (car symss))])
|
||||
(loop env (cdr symss) (cons bounds boundss)))))))
|
||||
|
||||
(define parse
|
||||
;; parses an expression
|
||||
(lambda (exp env)
|
||||
(pretty-debug-front `(parse ,(zodiac:stripper exp)))
|
||||
(letrec ([lookup-sym
|
||||
(lambda (sym s f env)
|
||||
(let ([bound
|
||||
(or (lookup-or-#f env sym)
|
||||
(lookup-or-#f unbound-env sym)
|
||||
;; Add to unbound-env
|
||||
(let ([n (zodiac:my-create-bound sym s f)])
|
||||
(set! unbound-env (cons (cons sym n) unbound-env))
|
||||
n))])
|
||||
;;(set-bound-refs! bound (add1 (bound-refs bound)))
|
||||
bound))]
|
||||
[parse-sym-env
|
||||
(lambda (env)
|
||||
(match-lambda
|
||||
[($ zodiac:symbol o s f sym)
|
||||
;;(printf "ref sym ~s~n" sym)
|
||||
(zodiac:make-lexical-varref o s f (box 0)
|
||||
sym (lookup-sym sym s f env))]
|
||||
[exp (syntax-error exp "Expected a variable:")]))]
|
||||
[parse-sym (parse-sym-env env)]
|
||||
[call-void
|
||||
(lambda (o s f)
|
||||
(zodiac:make-app
|
||||
o s f (box 0)
|
||||
(zodiac:make-lexical-varref o s f (box 0)
|
||||
'void (lookup-sym 'void s f '()))
|
||||
'()))]
|
||||
[parse-exps
|
||||
(lambda (exps env)
|
||||
(map (lambda (e) (parse e env)) exps))]
|
||||
[handle-args
|
||||
(lambda (args env)
|
||||
(match args
|
||||
[($ zodiac:list _ _ _ args) (do-bindings env args)]
|
||||
[($ zodiac:symbol)
|
||||
(let-values
|
||||
([(bounds nuenv) (do-bindings env (list args))])
|
||||
(values (car bounds) nuenv))]
|
||||
[($ zodiac:improper-list _ _ _ l)
|
||||
(recur loop ([args '()][l l])
|
||||
(match l
|
||||
[(arg)
|
||||
(let-values
|
||||
([(bounds nuenv)
|
||||
(do-bindings env (cons arg args))])
|
||||
(values (append (reverse (cdr bounds)) (car bounds))
|
||||
nuenv))]
|
||||
[(arg . rest) (loop (cons arg args) rest)]))]))])
|
||||
|
||||
(pretty-debug-front `(parse ,(zodiac:stripper exp)))
|
||||
(match exp
|
||||
;; Identifiers
|
||||
[($ zodiac:symbol o s f sym) (parse-sym exp)]
|
||||
|
||||
;; Scalars, vectors
|
||||
[(or ($ zodiac:scalar o s f) ($ zodiac:vector o s f))
|
||||
(zodiac:make-quote-form o s f (box 0) exp)]
|
||||
|
||||
;; Special forms
|
||||
[($ zodiac:list o s f
|
||||
(and l (($ zodiac:symbol _ _ _ sym) . body)))
|
||||
(=> fail)
|
||||
(let ([sym (strip-hash-percent sym)])
|
||||
(cond
|
||||
[(memq sym keywords)
|
||||
(match (cons sym body)
|
||||
[('cond)
|
||||
(call-void o s f)]
|
||||
[('delay exp)
|
||||
(zodiac:make-delay-form o s f (box 0) (parse exp env))]
|
||||
[('if test then else)
|
||||
(zodiac:make-if-form o s f (box 0)
|
||||
(parse test env)
|
||||
(parse then env)
|
||||
(parse else env))]
|
||||
[('if test then)
|
||||
(zodiac:make-if-form o s f (box 0)
|
||||
(parse test env)
|
||||
(parse then env)
|
||||
(call-void o s f))]
|
||||
[(or
|
||||
('set! var exp)
|
||||
('set!-values ($ zodiac:list _ _ _ (var)) exp))
|
||||
|
||||
(let ([var (parse-sym var)])
|
||||
(when (zodiac:lexical-varref? var)
|
||||
(zodiac:set-bound-mutated!
|
||||
(zodiac:lexical-varref-binding var)
|
||||
#t))
|
||||
(zodiac:make-set!-form o s f (box 0)
|
||||
var (parse exp env)))]
|
||||
[('quote sexp)
|
||||
(assert-syn exp (= (length body) 1))
|
||||
(zodiac:make-quote-form o s f (box 0) sexp)]
|
||||
[('begin . exps)
|
||||
(recur loop ([exps exps])
|
||||
(match exps
|
||||
[() (call-void o s f)]
|
||||
[(exp) (parse exp env)]
|
||||
[(exp . exps)
|
||||
(zodiac:make-begin-form o s f (box 0)
|
||||
(parse exp env)
|
||||
(loop exps))]))]
|
||||
[('lambda args . bodies)
|
||||
(let-values
|
||||
([(bounds nuenv) (handle-args args env)])
|
||||
(zodiac:make-lambda-form o s f (box 0)
|
||||
bounds
|
||||
(parse-body o s f bodies nuenv)))]
|
||||
[('case-lambda . cases)
|
||||
(zodiac:make-case-lambda-form
|
||||
o s f (box 0)
|
||||
(mapLR
|
||||
(match-lambda
|
||||
[($ zodiac:list _ _ _ (args . body))
|
||||
(let-values
|
||||
([(bounds nuenv) (handle-args args env)])
|
||||
(cons bounds (parse-body o s f body nuenv)))]
|
||||
[_ (syntax-error-no-exp exp "Bad case lambda")])
|
||||
cases))]
|
||||
|
||||
[('let-values
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:list _ _ _
|
||||
(($ zodiac:list _ _ _ varss)
|
||||
exps))
|
||||
...))
|
||||
. bodies)
|
||||
(let-values
|
||||
([(boundss nuenv) (do-bindingss env varss)])
|
||||
(zodiac:make-let-values-form
|
||||
o s f (box 0)
|
||||
boundss
|
||||
(parse-exps exps env)
|
||||
(parse-body o s f bodies nuenv)))]
|
||||
|
||||
[('letrec*-values
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:list _ _ _
|
||||
(($ zodiac:list _ _ _ varss)
|
||||
exps))
|
||||
...))
|
||||
. bodies)
|
||||
(let-values
|
||||
([(boundss nuenv) (do-bindingss env varss)])
|
||||
(for-each
|
||||
(lambda (name) (zodiac:set-bound-mutated! name #t))
|
||||
(apply append boundss))
|
||||
(zodiac:make-letrec-values-form
|
||||
o s f (box 0)
|
||||
boundss
|
||||
(parse-exps exps nuenv)
|
||||
(parse-body o s f bodies nuenv)))]
|
||||
|
||||
;; ---------------------------------------------------------
|
||||
;; MzScheme specific code
|
||||
|
||||
;; --- units ---
|
||||
[('unit ($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ 'import)
|
||||
i-ids ...))
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ 'export)
|
||||
(or ($ zodiac:list _ _ _
|
||||
(i-eids
|
||||
($ zodiac:symbol _ _ _ e-eids)))
|
||||
(and i-eids
|
||||
($ zodiac:symbol _ _ _ e-eids)))
|
||||
...))
|
||||
. body)
|
||||
(let*-vals ([(i-names env1) (do-bindings env i-ids)]
|
||||
[(defs env2) (parse-defs body env1)]
|
||||
[e-vars
|
||||
(map (parse-sym-env env2) i-eids)]
|
||||
[exports (map cons e-vars e-eids)])
|
||||
(zodiac:make-unit-form o s f (box 0)
|
||||
i-names exports defs))]
|
||||
|
||||
;; --- compound-units ---
|
||||
[('compound-unit
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ 'import)
|
||||
($ zodiac:symbol _ _ _ imports) ...))
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ 'link) . links))
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ 'export) . exports)))
|
||||
(let*-vals
|
||||
([links
|
||||
(map
|
||||
(match-lambda
|
||||
[($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ tag)
|
||||
($ zodiac:list _ _ _ (exp . imports))))
|
||||
(list tag
|
||||
(parse exp env)
|
||||
(apply append
|
||||
(map
|
||||
(match-lambda
|
||||
[($ zodiac:symbol _ _ _ sym)
|
||||
(list (cons #f sym))]
|
||||
[($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ tag)
|
||||
($ zodiac:symbol _ _ _ syms)
|
||||
...))
|
||||
(map (lambda (sym) (cons tag sym))
|
||||
syms)]
|
||||
[_ (syntax-error exp "Bad link imp")])
|
||||
imports)))]
|
||||
[_ (syntax-error exp "Bad link")])
|
||||
links)]
|
||||
[exports
|
||||
(apply
|
||||
append
|
||||
(map
|
||||
(match-lambda
|
||||
[($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ tag)
|
||||
(or ($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ i-eids)
|
||||
($ zodiac:symbol _ _ _ e-eids)))
|
||||
(and ($ zodiac:symbol _ _ _ i-eids)
|
||||
($ zodiac:symbol _ _ _ e-eids))) ...))
|
||||
(map
|
||||
(lambda (i-eid e-eid) (list tag i-eid e-eid))
|
||||
i-eids e-eids)]
|
||||
[_ (syntax-error exp "Bad link export")])
|
||||
exports))])
|
||||
(zodiac:make-compound-unit-form
|
||||
o s f (box 0) imports links exports))]
|
||||
|
||||
;; --- invoke-unit ---
|
||||
[('invoke-unit exp . ((and vars ($ zodiac:symbol)) ...))
|
||||
(zodiac:make-invoke-unit-form
|
||||
o s f (box 0)
|
||||
(parse exp env)
|
||||
(map (lambda (var) (parse-sym var env)) vars))]
|
||||
|
||||
;; --- structures ---
|
||||
[((or 'struct 'typed-structure 'const-typed-structure)
|
||||
first
|
||||
($ zodiac:list _ _ _ fields))
|
||||
(let*-vals
|
||||
([(tag parent)
|
||||
(match first
|
||||
[($ zodiac:symbol _ _ _ tag) (values tag #f)]
|
||||
[($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ tag) parent))
|
||||
(values tag (parse parent env))])]
|
||||
[fields (map zodiac:stripper fields)])
|
||||
(zodiac:make-struct-form
|
||||
o s f (box 0)
|
||||
tag (eq? sym 'const-typed-structure) parent fields))]
|
||||
|
||||
;; -------------------------------------------------------
|
||||
;; MrSpidey specific code
|
||||
|
||||
[('poly exp)
|
||||
(zodiac:make-poly-form
|
||||
o s f (box 0) (parse exp env))]
|
||||
[(': exp type)
|
||||
(zodiac:make-:-form o s f (box 0)
|
||||
(parse exp env)
|
||||
(zodiac:stripper type))]
|
||||
|
||||
[('type:-quote
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ (or 'quote '#%quote))
|
||||
($ zodiac:list _ _ _ (type . attrs)))))
|
||||
(zodiac:make-type:-form o s f (box 0)
|
||||
(zodiac:stripper type)
|
||||
(map zodiac:stripper attrs))]
|
||||
|
||||
[('st:control para val)
|
||||
(zodiac:make-st:control-form o s f (box 0)
|
||||
(zodiac:stripper para)
|
||||
(zodiac:stripper val))]
|
||||
|
||||
[((or 'cache-exp-quote 'cache-inv-quote)
|
||||
($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ (or 'quote '#%quote)) exp))
|
||||
($ zodiac:string _ _ _ za))
|
||||
(when (string=? za (regexp-replace ".za$" za ""))
|
||||
(syntax-error exp "Cache filename must end in .za"))
|
||||
(zodiac:make-cache-form
|
||||
o s f (box 0) exp
|
||||
(normalize-path za)
|
||||
(case sym
|
||||
[cache-exp-quote 'exp]
|
||||
[cache-inv-quote 'inv]
|
||||
[else
|
||||
(mrspidey:internal-error 'parser "Bad sym ~s" sym)])
|
||||
(current-directory))]
|
||||
|
||||
;; -------------------------------------------------------
|
||||
[else (syntax-error exp)])]
|
||||
[(memq sym define-keywords)
|
||||
(syntax-error-no-exp exp "Defines not allowed")]
|
||||
[else (fail)]))]
|
||||
|
||||
;; Don't handle vectors or improper lists
|
||||
;; Applications
|
||||
|
||||
[($ zodiac:list o s f (and l (fn . exps)))
|
||||
(zodiac:make-app o s f (box 0)
|
||||
(parse fn env)
|
||||
(parse-exps exps env))]
|
||||
[($ zodiac:list o s f ())
|
||||
(zodiac:make-quote-form o s f (box 0) '())]
|
||||
[_ (syntax-error exp)]))))
|
||||
|
||||
|
||||
|
||||
|
||||
(define (parse-defs defs env)
|
||||
(let*-vals
|
||||
([varss (mapLR
|
||||
(match-lambda
|
||||
[($ zodiac:list _ _ _
|
||||
(($ zodiac:symbol _ _ _ '#%define-values)
|
||||
($ zodiac:list _ _ _ vars)
|
||||
exp))
|
||||
vars]
|
||||
[_ '()])
|
||||
defs)]
|
||||
[(boundss nuenv) (do-bindingss env varss)]
|
||||
[_ (for-each
|
||||
(lambda (name) (zodiac:set-bound-mutated! name #t))
|
||||
(apply append boundss))]
|
||||
[defs
|
||||
(map
|
||||
(lambda (def bounds)
|
||||
(pretty-debug-front `(parse-def ,(zodiac:stripper def)))
|
||||
(mrspidey:zprogress "Parsing" (zodiac:zodiac-start def))
|
||||
(match def
|
||||
;; Special forms
|
||||
[($ zodiac:list o s f
|
||||
(and l (($ zodiac:symbol _ _ _ sym) . body)))
|
||||
(=> fail)
|
||||
(let ([sym (strip-hash-percent sym)])
|
||||
(cond
|
||||
[(not (memq sym define-keywords)) (fail)]
|
||||
[else
|
||||
(match (cons sym body)
|
||||
|
||||
[('define-values ($ zodiac:list _ _ _ vars) exp)
|
||||
(zodiac:make-define-values-form
|
||||
o s f (box 0)
|
||||
(map
|
||||
(match-lambda
|
||||
[(and bound ($ zodiac:bound o s f _ sym))
|
||||
(zodiac:make-lexical-varref o s f (box 0)
|
||||
sym bound)])
|
||||
bounds)
|
||||
(parse exp nuenv))]
|
||||
|
||||
;; ----------------------------------------------------
|
||||
;; MrSpidey specific code
|
||||
|
||||
[('define-type ($ zodiac:symbol _ _ _ sym) type)
|
||||
(zodiac:make-define-type-form
|
||||
o s f (box 0)
|
||||
sym (zodiac:stripper type))]
|
||||
|
||||
[('define-constructor ($ zodiac:symbol _ _ _ sym)
|
||||
. modes)
|
||||
(let ([modes (map zodiac:stripper modes)])
|
||||
(assert-syn def (andmap boolean? modes))
|
||||
(zodiac:make-define-constructor-form o s f (box 0)
|
||||
sym modes))]
|
||||
|
||||
;; ----------------------------------------------------
|
||||
[else (fail)])]))]
|
||||
|
||||
[exp (parse exp nuenv)]))
|
||||
defs boundss)])
|
||||
(unless (null? defs)
|
||||
(mrspidey:zprogress "Parsing" (zodiac:zodiac-finish (rac defs))))
|
||||
(values defs nuenv)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
@ -0,0 +1,626 @@
|
||||
;; poly.ss
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Preprocesses the program
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define debugging-topo #f)
|
||||
(defmacro pretty-debug-topo args
|
||||
`(when debugging-topo (pretty-print ,@args)))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define (st:poly file)
|
||||
(st: (topo-file file)))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define-struct def-info (def out in to from color))
|
||||
|
||||
(define (topo-file file)
|
||||
(let ([file (normalize-path file)])
|
||||
(let*-vals
|
||||
( [sexps (zodiac:read* (open-code-file file) file)]
|
||||
[(defs free-names)
|
||||
(dynamic-let ([current-directory (path-only file)])
|
||||
(top-level-parse-defs sexps))]
|
||||
[prims-refd (map zodiac:bound-var free-names)]
|
||||
[_ (pretty-debug-topo `(prims-refd ,prims-refd))]
|
||||
[prim-sexps
|
||||
(filter-map
|
||||
(lambda (name)
|
||||
(or
|
||||
(ormap
|
||||
(match-lambda
|
||||
[(and d ('define (? (lambda (n) (eq? n name))) _))
|
||||
(let* ( [p (open-output-string)]
|
||||
[_ (pretty-print d p)]
|
||||
[_ (close-output-port p)]
|
||||
[p (open-input-string (get-output-string p))]
|
||||
[p (system-expand-if-necy p)]
|
||||
[d (zodiac:read p
|
||||
(zodiac:make-location 1 1 0 "prim-file"))])
|
||||
(d))]
|
||||
[_ #f])
|
||||
r4rs-prims)
|
||||
(begin
|
||||
(unless (memq name real-primitives)
|
||||
(printf "Warning: Bad primitive ~s~n" name))
|
||||
#f)))
|
||||
prims-refd)]
|
||||
[_ (pretty-debug-topo `(prim-sexps ,(map zodiac:stripper prim-sexps)))]
|
||||
[all-sexps (append prim-sexps sexps)]
|
||||
[(defs free-names)
|
||||
(dynamic-let ([current-directory (path-only file)])
|
||||
(top-level-parse-defs all-sexps))]
|
||||
[def->di
|
||||
(lambda (def)
|
||||
(let ([di (make-def-info def '() '() '() '() #f)])
|
||||
(match def
|
||||
[($ zodiac:define-values-form _ _ _ _ lvrs exp)
|
||||
(set-def-info-out! di
|
||||
(map zodiac:lexical-varref-binding lvrs))
|
||||
(set-def-info-in! di (zodiac:free-refs exp))]
|
||||
[exp (set-def-info-in! di (zodiac:free-refs exp))])
|
||||
di))]
|
||||
[di* (mapLR def->di defs)]
|
||||
[_ (for-each
|
||||
(lambda (di)
|
||||
(pretty-debug-topo
|
||||
`(DEF ,(zodiac:stripper (def-info-def di))
|
||||
,(map zodiac:bound-var (def-info-out di))
|
||||
,(map zodiac:bound-var (def-info-in di)))))
|
||||
di*)]
|
||||
|
||||
[_ (for-each
|
||||
(lambda (di1)
|
||||
(for-each
|
||||
(lambda (sym)
|
||||
(for-each
|
||||
(lambda (di2)
|
||||
(when (memq sym (def-info-out di2))
|
||||
(set-def-info-to! di1
|
||||
(cons di2 (def-info-to di1)))
|
||||
(set-def-info-from! di2
|
||||
(cons di1 (def-info-from di2)))))
|
||||
di*))
|
||||
(def-info-in di1)))
|
||||
di*)]
|
||||
[_ (pretty-debug-topo "to/from fields filled")]
|
||||
|
||||
[dfs (lambda (di* field-sel)
|
||||
(for-each (lambda (di) (set-def-info-color! di 'white)) di*)
|
||||
(let ([done '()])
|
||||
(letrec ([visit
|
||||
(lambda (di)
|
||||
(when (eq? (def-info-color di) 'white)
|
||||
(set-def-info-color! di 'black)
|
||||
(for-each visit (field-sel di))
|
||||
(set! done (cons di done))))])
|
||||
(for-each visit di*)
|
||||
done)))]
|
||||
|
||||
;; do topological sort. See "Intro to Algs", p. 489
|
||||
|
||||
[di*1 (dfs di* def-info-to)]
|
||||
;; di*1 contains definitions before references
|
||||
[show-di
|
||||
(lambda (di)
|
||||
`(DEF
|
||||
,(map zodiac:bound-var (def-info-out di))
|
||||
,(map zodiac:bound-var (def-info-in di))))]
|
||||
[show (lambda (str di*)
|
||||
(pretty-debug-topo str)
|
||||
(pretty-debug-topo (map show-di di*)))]
|
||||
[_ (show "di*1" di*1)]
|
||||
[di*2 (dfs di*1 def-info-from)]
|
||||
[_ (show "di*2" di*2)]
|
||||
|
||||
;; Calculate list of strongly connected components
|
||||
|
||||
[_ (for-each (lambda (di) (set-def-info-color! di 'white)) di*)]
|
||||
[sccs
|
||||
(mapLR
|
||||
(lambda (di)
|
||||
(let ([scc '()])
|
||||
(recur loop ([di di])
|
||||
(when (eq? (def-info-color di) 'white)
|
||||
(set-def-info-color! di 'black)
|
||||
(set! scc (cons di scc))
|
||||
(for-each loop (def-info-to di))))
|
||||
scc))
|
||||
di*2)]
|
||||
[sccs (filter (lambda (x) (not (null? x))) sccs)]
|
||||
|
||||
[_ (begin
|
||||
(pretty-debug-topo 'SCCS)
|
||||
(for-each (lambda (scc) (show "scc" scc)) sccs))]
|
||||
|
||||
[my-begin
|
||||
(lambda (first rest)
|
||||
(make-zodiac:begin-form
|
||||
first rest
|
||||
(zodiac:no-location)(zodiac:no-location) (box #f)))]
|
||||
|
||||
[value-def?
|
||||
(match-lambda
|
||||
[($ zodiac:define-values-form _ _ _ _ _ exp)
|
||||
(zodiac:value? exp)]
|
||||
[_ #f])]
|
||||
|
||||
;; --- Figure out which are polymorphic
|
||||
;; Go from end up to know if multiple refs for each var
|
||||
;; A ref inside a polymorphic def counts as multiple refs
|
||||
|
||||
[vars-single-ref '()]
|
||||
[vars-multi-ref '()]
|
||||
[add-multi-ref!
|
||||
(lambda (var)
|
||||
(set! vars-multi-ref (set-add var vars-multi-ref)))]
|
||||
[add-single-ref!
|
||||
(lambda (var)
|
||||
(if (element-of? var vars-single-ref)
|
||||
(add-multi-ref! var)
|
||||
(set! vars-single-ref (set-add var vars-single-ref))))]
|
||||
|
||||
[sccs2 ;; include polymorphism flag
|
||||
(mapRL
|
||||
(lambda (scc)
|
||||
(let* ( [values?
|
||||
(andmap
|
||||
(match-lambda
|
||||
[($ def-info def out) (value-def? def)])
|
||||
scc)]
|
||||
[mutable?
|
||||
'(ormap
|
||||
(match-lambda
|
||||
[($ def-info def out)
|
||||
(ormap (lambda (o) (memq o mutable-syms)) out)])
|
||||
scc)]
|
||||
[mutable? #f]
|
||||
[defs (apply append (map def-info-out scc))]
|
||||
[refs (apply append (map def-info-in scc))]
|
||||
[multi-refs
|
||||
(match defs
|
||||
[(def) (element-of? def vars-multi-ref)]
|
||||
[() #f]
|
||||
[defs #t])]
|
||||
[poly-flag
|
||||
(if (and values? (not mutable?))
|
||||
(if multi-refs 'poly 'poly1ref)
|
||||
#f)])
|
||||
|
||||
(pretty-debug-topo
|
||||
`( defs ,(map zodiac:bound-var defs)
|
||||
refs ,(map zodiac:bound-var refs)
|
||||
values? ,values? mutable? ,mutable?
|
||||
multi-refs ,multi-refs poly-flag ,poly-flag))
|
||||
|
||||
(if (eq? poly-flag 'poly)
|
||||
(for-each add-multi-ref! refs)
|
||||
(for-each add-single-ref! refs))
|
||||
|
||||
(cons poly-flag scc)))
|
||||
sccs)]
|
||||
|
||||
[_ (pretty-print
|
||||
`(SCCS
|
||||
,(map
|
||||
(match-lambda
|
||||
[(poly . di*)
|
||||
(let* ( [o (apply append (map def-info-out di*))]
|
||||
[ov (map zodiac:bound-var o)])
|
||||
(case poly
|
||||
[poly (cons '-->POLY ov)]
|
||||
[poly1ref (cons '-->POLY1REF ov)]
|
||||
[#f ov]))])
|
||||
sccs2)))]
|
||||
|
||||
[nu-program
|
||||
;; Return new program
|
||||
(apply append
|
||||
(map
|
||||
(match-lambda
|
||||
[('poly .
|
||||
(($ def-info ($ zodiac:define-values-form _ _ _ _
|
||||
(lvrs) exps))
|
||||
...))
|
||||
(let ([syms
|
||||
(map (lambda (lvr)
|
||||
(zodiac:bound-var
|
||||
(zodiac:lexical-varref-binding lvr)))
|
||||
lvrs)])
|
||||
(if (= (length syms) 1)
|
||||
`((define ,(car syms)
|
||||
(poly (letrec
|
||||
([,(car syms) ,(zodiac:stripper (car exps))])
|
||||
,(car syms)))))
|
||||
`((define-values ,syms
|
||||
(poly (letrec*-values
|
||||
([,syms
|
||||
(values
|
||||
,@(map zodiac:stripper exps))])
|
||||
(values ,@syms)))))))]
|
||||
[(_ . di*)
|
||||
(map zodiac:stripper (map def-info-def di*))])
|
||||
sccs2))]
|
||||
|
||||
[outfile (regexp-replace ".ss$" file ".poly.ss")]
|
||||
[_ (when (eq? outfile file)
|
||||
(error 'topo-file "Bad suffix on ~s" file))]
|
||||
[_ (delete-file outfile)]
|
||||
[p3 (open-output-file outfile)])
|
||||
|
||||
(printf "----------PROGRAM----------~n")
|
||||
(for-each
|
||||
(lambda (def)
|
||||
(pretty-debug-topo def)
|
||||
(pretty-print def p3))
|
||||
nu-program)
|
||||
|
||||
(close-output-port p3)
|
||||
outfile)))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define zodiac:value?
|
||||
(match-lambda
|
||||
[(or
|
||||
($ zodiac:quote-form)
|
||||
($ zodiac:lambda-form)
|
||||
($ zodiac:case-lambda-form)
|
||||
($ zodiac:lexical-varref)) #t]
|
||||
[($ zodiac:letrec-values-form
|
||||
_ _ _ _ vars
|
||||
((? zodiac:value?) ...)
|
||||
(? zodiac:value?)) #t]
|
||||
[_ #f]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define r4rs-prims
|
||||
`((define caar (lambda (x) (car (car x))))
|
||||
(define cadr (lambda (x) (car (cdr x))))
|
||||
(define cdar (lambda (x) (cdr (car x))))
|
||||
(define cddr (lambda (x) (cdr (cdr x))))
|
||||
(define caaar (lambda (x) (car (car (car x)))))
|
||||
(define caadr (lambda (x) (car (car (cdr x)))))
|
||||
(define cadar (lambda (x) (car (cdr (car x)))))
|
||||
(define caddr (lambda (x) (car (cdr (cdr x)))))
|
||||
(define cdaar (lambda (x) (cdr (car (car x)))))
|
||||
(define cdadr (lambda (x) (cdr (car (cdr x)))))
|
||||
(define cddar (lambda (x) (cdr (cdr (car x)))))
|
||||
(define cdddr (lambda (x) (cdr (cdr (cdr x)))))
|
||||
(define caaaar (lambda (x) (car (car (car (car x))))))
|
||||
(define caaadr (lambda (x) (car (car (car (cdr x))))))
|
||||
(define caadar (lambda (x) (car (car (cdr (car x))))))
|
||||
(define caaddr (lambda (x) (car (car (cdr (cdr x))))))
|
||||
(define cadaar (lambda (x) (car (cdr (car (car x))))))
|
||||
(define cadadr (lambda (x) (car (cdr (car (cdr x))))))
|
||||
(define caddar (lambda (x) (car (cdr (cdr (car x))))))
|
||||
(define cadddr (lambda (x) (car (cdr (cdr (cdr x))))))
|
||||
(define cdaaar (lambda (x) (cdr (car (car (car x))))))
|
||||
(define cdaadr (lambda (x) (cdr (car (car (cdr x))))))
|
||||
(define cdadar (lambda (x) (cdr (car (cdr (car x))))))
|
||||
(define cdaddr (lambda (x) (cdr (car (cdr (cdr x))))))
|
||||
(define cddaar (lambda (x) (cdr (cdr (car (car x))))))
|
||||
(define cddadr (lambda (x) (cdr (cdr (car (cdr x))))))
|
||||
(define cdddar (lambda (x) (cdr (cdr (cdr (car x))))))
|
||||
(define cddddr (lambda (x) (cdr (cdr (cdr (cdr x))))))
|
||||
(define list (lambda a a))
|
||||
(define length
|
||||
(lambda (a)
|
||||
(recur loop ((a a) (len 0))
|
||||
(if (null? a)
|
||||
len
|
||||
(loop (cdr a) (+ 1 len))))))
|
||||
(define append
|
||||
(lambda a
|
||||
(letrec ((app2 (lambda (a b)
|
||||
(if (null? a)
|
||||
b
|
||||
(cons (car a) (app2 (cdr a) b))))))
|
||||
(recur loop ((a a))
|
||||
(cond ((null? a) '())
|
||||
((null? (cdr a)) (car a))
|
||||
(else (app2 (car a) (loop (cdr a)))))))))
|
||||
(define reverse
|
||||
(lambda (a)
|
||||
(recur loop ((a a) (acc '()))
|
||||
(if (null? a)
|
||||
acc
|
||||
(loop (cdr a) (cons (car a) acc))))))
|
||||
(define list-tail
|
||||
(lambda (a n)
|
||||
(if (zero? n)
|
||||
a
|
||||
(list-tail (cdr a) (- n 1)))))
|
||||
(define list-ref
|
||||
(lambda (a n)
|
||||
(if (zero? n)
|
||||
(car a)
|
||||
(list-ref (cdr a) (- n 1)))))
|
||||
(define memq
|
||||
(lambda (x a)
|
||||
(cond ((null? a) #f)
|
||||
((eq? x (car a)) a)
|
||||
(else (memq x (cdr a))))))
|
||||
(define memv
|
||||
(lambda (x a)
|
||||
(cond ((null? a) #f)
|
||||
((eqv? x (car a)) a)
|
||||
(else (memv x (cdr a))))))
|
||||
(define member
|
||||
(lambda (x a)
|
||||
(cond ((null? a) #f)
|
||||
((equal? x (car a)) a)
|
||||
(else (member x (cdr a))))))
|
||||
(define assq
|
||||
(lambda (x a)
|
||||
(cond ((null? a) #f)
|
||||
((eq? x (car (car a))) (car a))
|
||||
(else (assq x (cdr a))))))
|
||||
(define assv
|
||||
(lambda (x a)
|
||||
(cond ((null? a) #f)
|
||||
((eqv? x (car (car a))) (car a))
|
||||
(else (assv x (cdr a))))))
|
||||
(define assoc
|
||||
(lambda (x a)
|
||||
(cond ((null? a) #f)
|
||||
((equal? x (car (car a))) (car a))
|
||||
(else (assoc x (cdr a))))))
|
||||
(define string->list
|
||||
(lambda (s)
|
||||
(recur loop ((n (- (string-length s) 1)) (acc '()))
|
||||
(if (negative? n)
|
||||
acc
|
||||
(loop (- n 1) (cons (string-ref s n) acc))))))
|
||||
; (define list->string
|
||||
; (lambda (a)
|
||||
; (apply string a)))
|
||||
(define list->string
|
||||
(lambda (a)
|
||||
(letrec ([length
|
||||
(lambda (a)
|
||||
(recur loop ((a a) (len 0))
|
||||
(if (null? a)
|
||||
len
|
||||
(loop (cdr a) (+ 1 len)))))])
|
||||
(let ((s (make-string (length a))))
|
||||
(recur loop ((i 0) (a a))
|
||||
(if (null? a)
|
||||
s
|
||||
(begin
|
||||
(string-set! s i (car a))
|
||||
(loop (+ 1 i) (cdr a)))))))))
|
||||
(define vector->list
|
||||
(lambda (v)
|
||||
(recur loop ((n (- (vector-length v) 1)) (acc '()))
|
||||
(if (negative? n)
|
||||
acc
|
||||
(loop (- n 1) (cons (vector-ref v n) acc))))))
|
||||
; (define list->vector
|
||||
; (lambda (a)
|
||||
; (apply vector a)))
|
||||
(define list->vector
|
||||
(lambda (a)
|
||||
(letrec ([length
|
||||
(lambda (a)
|
||||
(recur loop ((a a) (len 0))
|
||||
(if (null? a)
|
||||
len
|
||||
(loop (cdr a) (+ 1 len)))))])
|
||||
(if (null? a)
|
||||
(vector)
|
||||
(let ((v (make-vector (length a) (car a))))
|
||||
(recur loop ((i 1) (a (cdr a)))
|
||||
(if (null? a)
|
||||
v
|
||||
(begin
|
||||
(vector-set! v i (car a))
|
||||
(loop (+ 1 i) (cdr a))))))))))
|
||||
(define map
|
||||
(lambda (f a . args)
|
||||
(letrec ((map1 (lambda (f l)
|
||||
(if (null? l)
|
||||
'()
|
||||
(cons (f (car l))
|
||||
(map1 f (cdr l))))))
|
||||
(map2 (lambda (f l1 l2)
|
||||
(cond ((null? l1)
|
||||
'())
|
||||
((null? l2)
|
||||
(error 'map "lists differ in length"))
|
||||
(else
|
||||
(cons (f (car l1) (car l2))
|
||||
(map2 f (cdr l1) (cdr l2)))))))
|
||||
(map* (lambda (f l*)
|
||||
(if (null? (car l*))
|
||||
'()
|
||||
(cons (let ((l (map1 car l*)))
|
||||
(if (null? l)
|
||||
(f)
|
||||
(apply f l)))
|
||||
(map* f (map1 cdr l*)))))))
|
||||
(cond ((null? args)
|
||||
(map1 f a))
|
||||
((null? (cdr args))
|
||||
(map2 f a (car args)))
|
||||
(else
|
||||
(map* f (cons a args)))))))
|
||||
(define for-each
|
||||
(lambda (f a . args)
|
||||
(letrec ((map (lambda (f l)
|
||||
(if (null? l)
|
||||
'()
|
||||
(cons (f (car l))
|
||||
(map f (cdr l)))))))
|
||||
(letrec ((for-each1 (lambda (f l)
|
||||
(if (null? l)
|
||||
(void)
|
||||
(begin
|
||||
(f (car l))
|
||||
(for-each1 f (cdr l))))))
|
||||
(for-each2 (lambda (f l1 l2)
|
||||
(cond ((null? l1)
|
||||
(void))
|
||||
((null? l2)
|
||||
(error 'for-each "lists differ in length"))
|
||||
(else
|
||||
(f (car l1) (car l2))
|
||||
(for-each2 f (cdr l1) (cdr l2))))))
|
||||
(for-each* (lambda (f l*)
|
||||
(if (null? (car l*))
|
||||
(void)
|
||||
(begin
|
||||
(let ((l (map car l*)))
|
||||
(if (null? l)
|
||||
(f)
|
||||
(apply f l)))
|
||||
(for-each* f (map cdr l*)))))))
|
||||
(cond ((null? args)
|
||||
(for-each1 f a))
|
||||
((null? (cdr args))
|
||||
(for-each2 f a (car args)))
|
||||
(else
|
||||
(for-each* f (cons a args))))))))
|
||||
(define call-with-input-file
|
||||
(lambda (s f)
|
||||
(let* ((p (open-input-file s))
|
||||
(v (f p)))
|
||||
(close-input-port p)
|
||||
v)))
|
||||
(define call-with-output-file
|
||||
(lambda (s f)
|
||||
(let* ((p (open-output-file s))
|
||||
(v (f p)))
|
||||
(close-output-port p)
|
||||
v)))
|
||||
(define with-input-from-file
|
||||
(lambda (s f)
|
||||
; no way to switch current input in R4RS Scheme
|
||||
(error 'with-input-from-file "not supported")
|
||||
(f)))
|
||||
(define with-output-to-file
|
||||
(lambda (s f)
|
||||
; no way to switch current output in R4RS Scheme
|
||||
(error 'with-output-to-file "not supported")
|
||||
(f)))
|
||||
|
||||
(define make-promise
|
||||
(lambda (thunk)
|
||||
(let ([first #t]
|
||||
[val #f])
|
||||
(lambda ()
|
||||
(cond
|
||||
[(eq? first 'forcing)
|
||||
(error 'force "recursive force")]
|
||||
[(eq? first #t)
|
||||
(set! first 'forcing)
|
||||
(set! val (thunk))
|
||||
(set! first #f)
|
||||
val]
|
||||
[else val])))))
|
||||
(define force (lambda (promise) (promise)))
|
||||
(define make-list
|
||||
(lambda (n val)
|
||||
(recur loop ((n n))
|
||||
(if (< n 1)
|
||||
'()
|
||||
(cons val (loop (- n 1)))))))
|
||||
(define andmap
|
||||
(lambda (f list0 . lists)
|
||||
(if (null? list0)
|
||||
(and)
|
||||
(recur loop ((lists (cons list0 lists)))
|
||||
(if (null? (cdr (car lists)))
|
||||
(apply f (map car lists))
|
||||
(and (apply f (map car lists))
|
||||
(loop (map cdr lists))))))))
|
||||
(define ormap
|
||||
(lambda (f list0 . lists)
|
||||
(if (null? list0)
|
||||
(or)
|
||||
(recur loop ((lists (cons list0 lists)))
|
||||
(if (null? (cdr (car lists)))
|
||||
(apply f (map car lists))
|
||||
(or (apply f (map car lists))
|
||||
(loop (map cdr lists))))))))
|
||||
(define dynamic-wind
|
||||
(lambda (in doit out)
|
||||
(let* ([a (in)]
|
||||
[b (doit)]
|
||||
[c (out)])
|
||||
b)))
|
||||
(define not (lambda (x) (if x #f #t)))
|
||||
(define add1 (lambda (x) (+ x 1)))
|
||||
(define sub1 (lambda (x) (- x 1)))
|
||||
(define equal?
|
||||
(lambda (x y)
|
||||
(or (eqv? x y)
|
||||
(and (pair? x) (pair? y)
|
||||
(equal? (car x) (car y))
|
||||
(equal? (cdr x) (cdr y)))
|
||||
(and (vector? x) (vector? y)
|
||||
(= (vector-length x) (vector-length y))
|
||||
(recur loop ([i (vector-length x)])
|
||||
(or (zero? i)
|
||||
(let ([i (- i 1)])
|
||||
(and (equal? (vector-ref x i) (vector-ref y i))
|
||||
(loop i)))))))))
|
||||
(define negative? (lambda (x) (< x 0)))
|
||||
(define list? (lambda (x) (or (null? x)
|
||||
(and (pair? x) (list? (cdr x))))))
|
||||
(define reverse!
|
||||
(lambda (x)
|
||||
(recur loop ([x x][p '()])
|
||||
(let ([q (cdr x)])
|
||||
(set-cdr! x p)
|
||||
(if (null? q)
|
||||
x
|
||||
(loop q x))))))
|
||||
(define even? (lambda (x) (or (zero? x) (odd? (sub1 x)))))
|
||||
(define odd? (lambda (x) (even? (sub1 x))))
|
||||
))
|
||||
|
||||
(define real-primitives
|
||||
'(car cdr zero? null? nil null + - * / apply
|
||||
number? cons pair?
|
||||
< > <= >= = <>
|
||||
vector make-vector vector-length vector-ref vector-set!
|
||||
void error display newline remainder quotient modulo abs expt min
|
||||
real-part even sqrt cos integer? exact?
|
||||
eq? eqv?
|
||||
call-with-values
|
||||
boolean? procedure? symbol? gensym
|
||||
set-cdr! set-car! printf random
|
||||
string-ref symbol->string number->string symbol? char=?
|
||||
char? string? vector?
|
||||
#%eqv #%void
|
||||
string->symbol string-append string<? #%global-defined-value
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (do-topo-files files)
|
||||
(let* ([file-thunk* (files->file-thunk* files)]
|
||||
[defs1 (load-parse-expand file-thunk*)]
|
||||
[_ (set! defs-expanded defs1)]
|
||||
[defs2 (map bind-def defs1)]
|
||||
[_ (set! defs-bind defs2)]
|
||||
[def (topological-sort defs2)])
|
||||
(zodiac:expr-stripper def)))
|
||||
|
||||
(define (test-topo files out)
|
||||
(when (file-exists? out) (delete-file out))
|
||||
(let* ([file-thunk* (files->file-thunk* files)]
|
||||
[defs1 (load-parse-expand file-thunk*)]
|
||||
[_ (set! defs-expanded defs1)]
|
||||
[defs2 (map bind-def defs1)]
|
||||
[_ (set! defs-bind defs2)]
|
||||
[def (topological-sort defs2)])
|
||||
(pretty-print (zodiac:expr-stripper def))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
@ -0,0 +1,127 @@
|
||||
;; program.ss
|
||||
;; Handles cormac's program first-order structure for units
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; Global environment stuff
|
||||
|
||||
(define global-def-env '())
|
||||
(define global-result (void))
|
||||
(define global-defs-parsed (void))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (analyze-program file)
|
||||
;; file should be normalized
|
||||
(let ([file (normalize-path file)])
|
||||
(pretty-debug `(analyze-program ,file , (path-only (normalize-path file))))
|
||||
(init-constructor-env!)
|
||||
(initialize-language!)
|
||||
(init-expand!)
|
||||
(clear-file-time-cache!)
|
||||
(let*-vals
|
||||
( [sexps (zodiac:read* (open-code-file file) file)]
|
||||
[_ (when debugging-front
|
||||
(printf "~n--Loaded program------------------~n")
|
||||
(for-each
|
||||
(lambda (sexp) (pretty-print-debug (zodiac:stripper sexp)))
|
||||
sexps)
|
||||
(printf "----------------------------------~n"))]
|
||||
[(defs free-names)
|
||||
(parameterize ([current-load-relative-directory (path-only file)])
|
||||
(my-scheme-expand-program sexps))]
|
||||
[_ (set! global-defs-parsed defs)]
|
||||
[_ (when debugging-front
|
||||
(printf "~n--Parsed program------------------~n")
|
||||
(for-each
|
||||
(lambda (def) (pretty-print-debug (zodiac:stripper def)))
|
||||
defs)
|
||||
(printf "----------------------------------~n"))]
|
||||
[init-env (get-default-bindings free-names)])
|
||||
|
||||
(pretty-debug `(init-env ,(atenv->pretty init-env)))
|
||||
;; Now do analyis
|
||||
|
||||
(let-values ([(env refs result) (top-level-traverse-defs defs init-env)])
|
||||
|
||||
(pretty-debug '(fixing up envs))
|
||||
(set! global-def-env env)
|
||||
(set! global-result result)
|
||||
;;(assert (null? refs) refs (map zodiac:binding-var (map car refs)))
|
||||
'(for-each
|
||||
(lambda (ref)
|
||||
(mrspidey:warning
|
||||
(format "Unbound variable ~s" (zodiac:binding-var (car ref)))))
|
||||
refs)
|
||||
|
||||
;; --- Fix up type variables
|
||||
;;(set! global-def-env (append global-def-env global-tdef-env))
|
||||
(report-duplicate-defs global-tdef-env)
|
||||
(report-unbound-vars
|
||||
(connect-refs-defs global-tref-env global-tdef-env))
|
||||
(connect-bangs-defs global-tbang-env global-tdef-env)
|
||||
|
||||
(when (not (st:whole-program))
|
||||
(put-context-top-s defs env result))
|
||||
|
||||
;;(show-stat-small)
|
||||
|
||||
defs))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (put-context-top-s defs env result)
|
||||
(mrspidey:progress "Partial program analysis")
|
||||
;;(show-stat-small)
|
||||
(when result (new-leq-top-s! (FlowType->Tvar result)))
|
||||
(when (and defs env)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ zodiac:define-values-form _ _ _ _ refs)
|
||||
(for-each
|
||||
(lambda (ref)
|
||||
(new-leq-top-s!
|
||||
(FlowType->Tvar
|
||||
(atenv:lookup env (zodiac:varref-binding ref)))))
|
||||
refs)]
|
||||
[_ (void)])
|
||||
defs)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; initialize-analysis!
|
||||
|
||||
(define (initialize-analysis!)
|
||||
(pretty-debug '(initialize-analysis!))
|
||||
(init-constructor-env!)
|
||||
(let ([old-kernel (save-kernel-state)])
|
||||
(init-kernel!)
|
||||
;; First free old stuff
|
||||
(when (st:zero-old-constraint-sets) (free-kernel-state! old-kernel)))
|
||||
(init-global-tenv! '() '() '())
|
||||
(init-common-AV!)
|
||||
(pretty-debug '(analysis-initialized)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (show-global)
|
||||
(list 'DEF (atenv->pretty global-def-env)
|
||||
;;'TDEF (atenv->pretty global-tdef-env)
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -0,0 +1,289 @@
|
||||
; results.ss
|
||||
; Shows results of set-based analysis
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
; Configuration
|
||||
|
||||
(define show-val-args #t)
|
||||
(define show-elements #t)
|
||||
(define show-AV #t)
|
||||
(define show-edgeto #t)
|
||||
(define show-constraint #t)
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
; Showing results
|
||||
|
||||
(define st:show (lambda l (for-each show-ftype (apply select l))))
|
||||
|
||||
(define show-ftype
|
||||
; Show value of ftype
|
||||
(lambda (ftype)
|
||||
(let* ([num (FlowType-num ftype)]
|
||||
[arrowto (FlowType-arrowto ftype)]
|
||||
[arrowfrom (FlowType-arrowfrom ftype)]
|
||||
[var (FlowType-name ftype)]
|
||||
[done #f]
|
||||
[makespaces
|
||||
(lambda (s)
|
||||
(if done
|
||||
(printf "~a [~a]" (padr "" 20) s)
|
||||
(begin
|
||||
(set! done #t)
|
||||
(printf
|
||||
"~a [~a]"
|
||||
(padr (symbol->string var) 20)
|
||||
s))))])
|
||||
(when (not (null? arrowto))
|
||||
(makespaces "arrowto")
|
||||
(for-each
|
||||
(lambda (to) (printf "| ~a " (FlowType-name to)))
|
||||
arrowto)
|
||||
(newline))
|
||||
(when (not (null? arrowfrom))
|
||||
(makespaces "arrowfrom")
|
||||
(for-each
|
||||
(lambda (from) (printf "| ~a " (FlowType-name from)))
|
||||
arrowfrom)
|
||||
(newline))
|
||||
(when (FlowType-type-annotation ftype)
|
||||
(makespaces "visable")
|
||||
(if (string? (FlowType-type-annotation ftype))
|
||||
(display (FlowType-type-annotation ftype)))
|
||||
(newline))
|
||||
(when (FlowType-values-ftype ftype)
|
||||
(makespaces "values-type")
|
||||
(printf "~s~n" (FlowType-name (FlowType-values-ftype ftype))))
|
||||
|
||||
(if (Tvar? ftype)
|
||||
(let* ( [Tvar ftype]
|
||||
[objs (Tvar-objs Tvar)]
|
||||
[constraints (Tvar-constraints Tvar)]
|
||||
[edgeto (Tvar-edgeto Tvar)]
|
||||
[edgefrom (Tvar-edgefrom Tvar)])
|
||||
|
||||
(if (and show-AV (not (null? (get-Tvar-objs Tvar))))
|
||||
(begin
|
||||
(makespaces "AV ")
|
||||
(begin0
|
||||
(show-sba-objs (get-Tvar-objs Tvar))
|
||||
(newline)))
|
||||
'())
|
||||
(if (and show-AV (not (null? (Tvar-orig-objs Tvar))))
|
||||
(begin
|
||||
(makespaces "origAV")
|
||||
(begin0
|
||||
(show-sba-objs (Tvar-orig-objs Tvar))
|
||||
(newline)))
|
||||
'())
|
||||
(if #t
|
||||
(begin
|
||||
(makespaces "num ")
|
||||
(printf "~s~n" (FlowType-num Tvar)))
|
||||
'())
|
||||
(if (and show-constraint (not (null? (Tvar-constraints Tvar))))
|
||||
(begin
|
||||
(makespaces "constr")
|
||||
;; Show each constraint
|
||||
(map
|
||||
(match-lambda
|
||||
[($ con num template field-no Tvar sign)
|
||||
(printf "[~s ~s ~s -> ~s] "
|
||||
(if (template? template)
|
||||
(template-type template)
|
||||
template)
|
||||
field-no sign
|
||||
(Tvar-name Tvar))]
|
||||
[($ con-filter num ($ filter bool templates) Tvar)
|
||||
(printf "[filter ~s ~s -> ~s] "
|
||||
(map template-type templates)
|
||||
bool (Tvar-name Tvar))]
|
||||
[($ con-top-s)
|
||||
(printf "[top-s] ")])
|
||||
(Tvar-constraints Tvar))
|
||||
(newline)
|
||||
'())
|
||||
'())
|
||||
|
||||
(if (and show-edgeto (not (null? edgeto)))
|
||||
(begin
|
||||
(makespaces "edgeto")
|
||||
(map (lambda (to)
|
||||
(printf "| ~a " (Tvar-name to)))
|
||||
edgeto)
|
||||
(newline)
|
||||
edgeto)
|
||||
'())
|
||||
(if (and show-edgeto (not (null? edgefrom)))
|
||||
(begin
|
||||
(makespaces "edgefr")
|
||||
(map (lambda (from)
|
||||
(printf "| ~a " (Tvar-name from)))
|
||||
edgefrom)
|
||||
(newline)
|
||||
edgefrom)
|
||||
'())
|
||||
(for-each
|
||||
(lambda (name get-nt)
|
||||
(if (and (get-nt Tvar)
|
||||
(not (null? (get-nt Tvar)))
|
||||
(not (null? (NT-rhs* (get-nt Tvar)))))
|
||||
(begin
|
||||
(makespaces name)
|
||||
(for-each (match-lambda
|
||||
[($ rhs grsym nt)
|
||||
(printf "| ~a ~a "
|
||||
(grsym->rep grsym)
|
||||
(if (null? nt)
|
||||
'()
|
||||
(nt->sym nt)))])
|
||||
(NT-rhs* (get-nt Tvar)))
|
||||
(newline))
|
||||
'()))
|
||||
(list "L " "U " "PL " "PU "
|
||||
)
|
||||
(list Tvar-L Tvar-U Tvar-PL Tvar-PU
|
||||
)))
|
||||
|
||||
(begin
|
||||
(makespaces "fo-Atype")
|
||||
(printf "~s~n" (FlowType->pretty ftype)))))))
|
||||
|
||||
(define show-sba-objs
|
||||
(lambda (objs)
|
||||
(recur loop2 ([objs objs][dep '()])
|
||||
(match objs
|
||||
[() dep]
|
||||
[(AV . rest)
|
||||
(match-let
|
||||
([(print-representation . new-dep)
|
||||
(print-rep-AV AV)])
|
||||
(printf "| ~s ~a " (AV-num AV) print-representation)
|
||||
(loop2 rest (append new-dep dep)))]))))
|
||||
|
||||
(define print-rep-AV
|
||||
(match-lambda
|
||||
[($ AV _ template misc fields+ fields-)
|
||||
(cons
|
||||
(list
|
||||
(template-type template)
|
||||
misc
|
||||
(map Tvar-name (vector->list fields+))
|
||||
(map Tvar-name (vector->list fields-)))
|
||||
'())]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define select
|
||||
(lambda l
|
||||
(if (null? l)
|
||||
list-ftype
|
||||
;; list of names and nums
|
||||
(apply append
|
||||
(map
|
||||
(lambda (v)
|
||||
(filter-map
|
||||
(lambda (Tvar)
|
||||
(if (or (and (number? v)
|
||||
(= (FlowType-num Tvar) v)))
|
||||
Tvar
|
||||
#f))
|
||||
list-ftype))
|
||||
l)))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (prods-NT nt)
|
||||
(let ([named #f])
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ rhs* grsym nt)
|
||||
(printf "~a -> ~a ~s~n"
|
||||
(padr (if named
|
||||
""
|
||||
(begin
|
||||
(set! named #t)
|
||||
(symbol->string (nt->sym nt))))
|
||||
20)
|
||||
(padr (grsym->rep grsym) 25)
|
||||
(nt->sym nt))])
|
||||
(NT-rhs* nt))))
|
||||
|
||||
(define (prods-Tvar Tvar)
|
||||
;;(printf "Tvar: ~s~n" (Tvar-name Tvar))
|
||||
(for-each
|
||||
(lambda (nt)
|
||||
(if (NT? nt)
|
||||
(prods-NT nt)
|
||||
(unless (null? nt)
|
||||
(printf "Warning: Bad nt ~s~n" nt))))
|
||||
(list (Tvar-L Tvar) (Tvar-LI Tvar) (Tvar-U Tvar) (Tvar-UI AVS))))
|
||||
|
||||
(define (st:prods . l) (for-each prods-Tvar (apply select l)))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define show-stat
|
||||
(lambda ()
|
||||
(printf "STATISTICS:~n")
|
||||
(let*
|
||||
( [list-ftype (filter Tvar? list-ftype)]
|
||||
[numTvar (length list-ftype)]
|
||||
[avg (lambda (x) (/ (truncate (* (/ x numTvar) 100)) 100.0))]
|
||||
[show (lambda (name f)
|
||||
(let* ([l (map f list-ftype)]
|
||||
[num (apply + l)]
|
||||
[avg (avg num)]
|
||||
[min (apply min l)]
|
||||
[max (apply max l)])
|
||||
(printf " ~a: Total ~s Avg ~s min ~s max ~s~n"
|
||||
name num avg min max)))])
|
||||
(show "edgeto " (lambda (Tvar) (length (Tvar-edgeto Tvar))))
|
||||
;;(show "edgefrom" (lambda (Tvar) (length (Tvar-edgefrom Tvar))))
|
||||
(show "con " (lambda (Tvar) (length (Tvar-constraints Tvar))))
|
||||
(show "AV "
|
||||
(lambda (Tvar)
|
||||
(let ([objs (Tvar-objs Tvar)])
|
||||
(if (Tvar? objs) 0 (length (Tvar-objs Tvar))))))
|
||||
(printf "num-AV : ~s~n" num-AV)
|
||||
(printf "num-Tvar : ~s~n" num-ftype)
|
||||
(printf "num-AV-a: ~s~n" num-AV-in-Tvar)
|
||||
;;(printf "Tvar-tmp : ~s~n" counter-Tvar-tmp)
|
||||
(match (hash-table-info)
|
||||
[(size entries clashes)
|
||||
(printf "Hashtbl : size ~s entries ~s clashes ~s~n"
|
||||
size entries clashes)])
|
||||
)))
|
||||
|
||||
(define show-stat-small
|
||||
(lambda ()
|
||||
(printf
|
||||
"STATS: Size ~s HWM ~s num-Tvar ~s num-AV ~s num-con ~s num-edge ~s num-AV-a ~s~n"
|
||||
(constraint-system-size)
|
||||
max-constraint-system-size
|
||||
num-ftype num-AV num-con
|
||||
num-edge num-AV-in-Tvar)
|
||||
(constraint-system-size)))
|
||||
|
||||
(define (empty-vars)
|
||||
(filter
|
||||
(lambda (Tvar)
|
||||
(if (null? (get-Tvar-objs Tvar))
|
||||
(Tvar-name Tvar)
|
||||
#f))
|
||||
list-ftype))
|
@ -0,0 +1,804 @@
|
||||
;; sdl.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
; ======================================================================
|
||||
; Tvar->SDL compresses, calcs prods and creates sdl
|
||||
|
||||
;(define Tvar 'dummy-Tvar)
|
||||
|
||||
(define sdl-tvar (void))
|
||||
|
||||
(define (Tvar->SDL Tvar)
|
||||
(set! sdl-tvar Tvar)
|
||||
(pretty-debug-sdl2 `(Tvar->SDL ,(Tvar-name Tvar)))
|
||||
(let*-vals
|
||||
( [(Tvar approximated)
|
||||
(if (eq? (st:sdl-fo) 'basic-types)
|
||||
(copy-constraint-fo-w/-limits Tvar)
|
||||
(values Tvar #f))]
|
||||
[_ (pretty-debug-sdl2 `(Tvar->SDL copied ,(Tvar-name Tvar)))]
|
||||
[nuTvar
|
||||
(let*-vals
|
||||
([(live-Tvar cvt)
|
||||
(dynamic-let
|
||||
([st:minimize-respect-assignable-part-of-fields
|
||||
(st:show-assignable-part-of-fields)])
|
||||
(pretty-debug-sdl2
|
||||
`(st:minimize-respect-assignable-part-of-fields
|
||||
,(st:minimize-respect-assignable-part-of-fields)))
|
||||
(minimize-constraints
|
||||
(st:sdl-constraint-simplification)
|
||||
'() (list Tvar)
|
||||
list-ftype '()))]
|
||||
[nuTvar (cvt Tvar)])
|
||||
(pretty-debug-sdl2 `(nuTvar ,(Tvar-name nuTvar)))
|
||||
nuTvar)]
|
||||
[sdl (raw-Tvar->SDL nuTvar #f)])
|
||||
(if approximated
|
||||
`(approx ,sdl)
|
||||
sdl)))
|
||||
|
||||
;; (define (Tvar->SDL tvar) (Tvar-name tvar))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (copy-constraint-fo-w/-limits tvar)
|
||||
|
||||
(let*-vals
|
||||
( [mk-tvar-dots
|
||||
(lambda ()
|
||||
(mk-Tvar-init-AV 'dots
|
||||
(create-AV template-dots '() mt-vector mt-vector)))]
|
||||
[tvar-L-dots (mk-tvar-dots)]
|
||||
[tvar-U-dots (mk-tvar-dots)]
|
||||
[approximated #f]
|
||||
[ref-tvar-L-dots (lambda () (set! approximated #t) tvar-L-dots)]
|
||||
[ref-tvar-U-dots (lambda () tvar-U-dots)]
|
||||
[(tvar-reached? tvar-reached! list-tvar-reached)
|
||||
(field->set alloc-Tvar-field)]
|
||||
[(AV-reached? AV-reached! list-AV-reached)
|
||||
(field->set alloc-AV-field)]
|
||||
[(tvar-nu tvar-nu!) (alloc-Tvar-field)]
|
||||
[(AV-nu AV-nu!) (alloc-AV-field)]
|
||||
[stack (list tvar)]
|
||||
)
|
||||
|
||||
;; doesn't do st:sdl-fo-depth-limit or st:sdl-fo-size-limit
|
||||
|
||||
(recur reach ([tvar tvar])
|
||||
(unless (tvar-reached? tvar)
|
||||
(tvar-reached! tvar)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template _ fields+ fields-))
|
||||
(unless (AV-reached? AV)
|
||||
(AV-reached! AV)
|
||||
(unless
|
||||
(or
|
||||
(and
|
||||
(not (st:sdl-fo-ivars))
|
||||
(memq template-all-ivars
|
||||
(template-super-templates template)))
|
||||
(and
|
||||
(not (st:sdl-fo-struct-fields))
|
||||
(memq template-structure
|
||||
(template-super-templates template))))
|
||||
(vector-for-each reach fields+)
|
||||
(when (eq? template template-lam)
|
||||
(vector-for-each reach fields-))))])
|
||||
(get-Tvar-objs tvar))))
|
||||
|
||||
(for-each
|
||||
(lambda (tvar) (tvar-nu! tvar (mk-Tvar 'copy-constraint-fo-w/-limits)))
|
||||
(list-tvar-reached))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ (? (eqc? template-lam)) misc #(rng) #(dom)))
|
||||
(AV-nu! AV
|
||||
(create-AV template-lam++ misc
|
||||
(vector-map
|
||||
(lambda (tvar)
|
||||
(if (tvar-reached? tvar) (tvar-nu tvar) (ref-tvar-L-dots)))
|
||||
(vector dom rng))
|
||||
(vector)))]
|
||||
[(and AV ($ AV _ template misc fields+ fields-))
|
||||
(AV-nu! AV
|
||||
(create-AV template misc
|
||||
(vector-map
|
||||
(lambda (tvar)
|
||||
(if (tvar-reached? tvar) (tvar-nu tvar) (ref-tvar-L-dots)))
|
||||
fields+)
|
||||
(vector-map
|
||||
(lambda (_) (ref-tvar-U-dots))
|
||||
fields-)))])
|
||||
(list-AV-reached))
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(let ([nu (tvar-nu tvar)])
|
||||
(for-each
|
||||
(lambda (AV)
|
||||
(new-AV! nu (AV-nu AV)))
|
||||
(get-Tvar-objs tvar))))
|
||||
(list-tvar-reached))
|
||||
(assert (tvar-reached? tvar) 'copy-sdl-size-k)
|
||||
(pretty-debug-sdl2
|
||||
`(copy-constraint-fo-w/-limits
|
||||
src ,(Tvar-name tvar)
|
||||
result ,(Tvar-name (tvar-nu tvar))
|
||||
size ,(length (list-AV-reached)) ,(length (list-tvar-reached))))
|
||||
(values
|
||||
(tvar-nu tvar)
|
||||
approximated)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
; raw-Tvar->SDL calcs prods and creates sdl
|
||||
;
|
||||
; We use that Tvar-L, Tvar-U and AV-U fields for eq?-ness.
|
||||
; But by Tvar-L, we really mean prefixes of Tvar-L, etc.
|
||||
|
||||
(define (raw-Tvar->SDL tvar mono)
|
||||
;; All reachable tvars are shown
|
||||
(pretty-debug-sdl2 `(raw-Tvar->SDL ,(Tvar-name tvar)))
|
||||
;;(find-nonempty-tvars '() (list tvar))
|
||||
(let*-vals
|
||||
( [mono-convert
|
||||
(if mono
|
||||
(match-lambda
|
||||
[($ NT tvar 'L) (chk-Tvar-U tvar)]
|
||||
[nt nt])
|
||||
(lambda (nt) nt))]
|
||||
[(env-crossover env-named-lfp)
|
||||
(choose-named-nts (chk-Tvar-U tvar) mono-convert)])
|
||||
(letrec
|
||||
([sdl-ref
|
||||
(lambda (nt)
|
||||
(let ([nt (mono-convert nt)])
|
||||
(or (ormap
|
||||
(match-lambda [(z . Y) (and (eq? nt z) Y)])
|
||||
env-named-lfp)
|
||||
(mk-sdl nt))))]
|
||||
[mk-sdl
|
||||
(lambda (nt)
|
||||
(let ([sdl (NT->SDL nt sdl-ref #t)])
|
||||
(if (bound-in-env? env-crossover (NT-tvar nt))
|
||||
((if (eq? (NT-type nt) 'U) absunion absintersect)
|
||||
sdl
|
||||
(lookup env-crossover (NT-tvar nt)))
|
||||
sdl)))])
|
||||
(let* ([binds
|
||||
(map
|
||||
(match-lambda
|
||||
[(y . name) (list name (mk-sdl y))])
|
||||
env-named-lfp)]
|
||||
[body (sdl-ref (chk-Tvar-U tvar))]
|
||||
[result (expand-output-type `(rec ,binds ,body))])
|
||||
result))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define choose-named-nts
|
||||
;; Returns (values env-crossover env-named-lfp)
|
||||
;; env-crossover maps Tvar to Xn
|
||||
;; env-named-lfp maps NT to Yn
|
||||
|
||||
(lambda (nt mono-convert)
|
||||
(let* ( [traversed '()]
|
||||
[named-lfp '()]
|
||||
[stack '()])
|
||||
|
||||
(letrec
|
||||
( [traverse-convert
|
||||
(lambda (nt)
|
||||
(let* ( [nt (mono-convert nt)])
|
||||
(unless (memq nt named-lfp)
|
||||
(let* ( [children '()]
|
||||
[ref (lambda (nt)
|
||||
(set! children (cons nt children))
|
||||
'blah)])
|
||||
(NT->SDL nt ref #f)
|
||||
(pretty-debug-sdl
|
||||
`(traversing ,(nt->sym nt)
|
||||
children ,(map nt->sym children)
|
||||
traversed ,(map nt->sym traversed)
|
||||
stack ,(map nt->sym stack)
|
||||
))
|
||||
|
||||
(let ([trivial
|
||||
(or (null? children)
|
||||
(match nt
|
||||
[($ NT tvar 'U)
|
||||
(and (Tvar? tvar)
|
||||
(match (Tvar-objs tvar)
|
||||
[() #t]
|
||||
[(($ AV _ _ _ fields+))
|
||||
(zero? (vector-length fields+))]
|
||||
[_ #f]))]
|
||||
[_ #f]))])
|
||||
(pretty-debug `(trivial ,(nt->sym nt) ,trivial))
|
||||
(when (case (st:naming-strategy)
|
||||
[(recursive) (memq nt stack)]
|
||||
[(multiple) (and (memq nt traversed)
|
||||
(not trivial))]
|
||||
[(nontrivial) (not trivial)]
|
||||
[(all) #t])
|
||||
;; Name this element
|
||||
(pretty-debug-sdl
|
||||
`(naming ,(nt->sym nt)
|
||||
,(if (memq nt traversed) #t #f)
|
||||
children ,(map nt->sym children)
|
||||
,trivial))
|
||||
(set! named-lfp (cons nt named-lfp))))
|
||||
(unless (memq nt traversed)
|
||||
(set! traversed (cons nt traversed))
|
||||
;;(pretty-print '(traversing children))
|
||||
(let ([oldstk stack])
|
||||
(set! stack (cons nt stack))
|
||||
(for-each
|
||||
traverse-convert
|
||||
children)
|
||||
(set! stack oldstk)))))))])
|
||||
(traverse-convert nt)
|
||||
(pretty-debug-sdl '(Traversed))
|
||||
|
||||
(let* ([crossover
|
||||
(intersect (select-L traversed) (select-U traversed))]
|
||||
[env-crossover
|
||||
(map-with-n
|
||||
(lambda (y n) (cons y (symbol-append 'X (add1 n))))
|
||||
(reverse crossover))]
|
||||
[env-named-lfp
|
||||
(map-with-n
|
||||
(lambda (y n)
|
||||
(cons y (symbol-append 'Y (add1 n) ;;(nt->sym y)
|
||||
)))
|
||||
named-lfp)])
|
||||
|
||||
(pretty-debug-sdl
|
||||
`(choose-named-nts
|
||||
select-L ,(map Tvar-name (select-L traversed))
|
||||
select-U ,(map (lambda (x) (and (Tvar? x) (Tvar-name x)))
|
||||
(select-U traversed))
|
||||
crossover ,(map Tvar-name crossover)
|
||||
named-lfp ,(map nt->sym named-lfp)
|
||||
traversed ,(map nt->sym traversed)))
|
||||
|
||||
(values env-crossover env-named-lfp))))))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define (NT->SDL nt ref-nt show?)
|
||||
(pretty-debug-sdl `(NT->SDL ,(nt->sym nt) ,show?))
|
||||
(let ([r
|
||||
(match nt
|
||||
[($ NT (? Tvar? tvar) 'U)
|
||||
(when (st:listify-etc)
|
||||
(listify-Tvar! tvar)
|
||||
(boolify-Tvar! tvar)
|
||||
(atomify-Tvar! tvar)
|
||||
(sexpify-Tvar! tvar)
|
||||
(classify-objectify-Tvar! tvar))
|
||||
(absUnion
|
||||
(map
|
||||
(lambda (AV) (ref-nt (chk-AV-U AV)))
|
||||
(get-Tvar-objs tvar)))]
|
||||
[($ NT (? Tvar? tvar) 'L)
|
||||
(absintersect
|
||||
(absIntersect
|
||||
(recur loop ([con* (filter con? (Tvar-constraints tvar))])
|
||||
(match con*
|
||||
[() '()]
|
||||
[(($ con _ (and template ($ template _ _ _ ref assign))
|
||||
_ _ sign)
|
||||
. _)
|
||||
(let*-vals
|
||||
([ (i-s-tvar* rest)
|
||||
(filter-map-split
|
||||
(match-lambda
|
||||
[($ con _
|
||||
(? (lambda (t) (eq? t template)))
|
||||
f tvar s)
|
||||
(cons (cons f s) tvar)]
|
||||
[_ #f])
|
||||
con*)]
|
||||
[ref-i+
|
||||
(lambda (i)
|
||||
(absIntersect
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[(j-s . tvar2)
|
||||
(and
|
||||
(equal? (car j-s) i)
|
||||
(cdr j-s)
|
||||
(ref-nt (chk-Tvar-L tvar2)))])
|
||||
i-s-tvar*)))]
|
||||
[ref-i-
|
||||
(lambda (i)
|
||||
(absUnion
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[(j-s . tvar2)
|
||||
(and
|
||||
(equal? (car j-s) i)
|
||||
(cdr j-s)
|
||||
(ref-nt (chk-Tvar-U tvar2)))])
|
||||
i-s-tvar*)))]
|
||||
[this
|
||||
|
||||
(cond
|
||||
[(eq? template template-lam)
|
||||
(list (ref-i- 0) '*->* (ref-i+ 1))]
|
||||
[(eq? template template-lam++)
|
||||
(list (ref-i+ 0) '*->* (ref-i+ 1))]
|
||||
[(st:show-assignable-part-of-fields)
|
||||
(list
|
||||
(template-type template)
|
||||
(map ref-i+
|
||||
(filter number? (vector->list ref)))
|
||||
(map ref-i-
|
||||
(filter number? (vector->list assign))))]
|
||||
[(and
|
||||
(eq? (vector-length ref) 1)
|
||||
(not (vector-ref ref 0)))
|
||||
;; Show single antimono field
|
||||
(list (template-type template) (ref-i- 0))]
|
||||
[else
|
||||
;; Only show ref'able fields
|
||||
(cons
|
||||
(template-type template)
|
||||
(map ref-i+
|
||||
(filter number? (vector->list ref))))])])
|
||||
|
||||
(cons this (loop rest)))])))
|
||||
(absIntersect
|
||||
(filter-map
|
||||
(match-lambda
|
||||
[($ con-filter _ _ tvar2)
|
||||
(ref-nt (chk-Tvar-L tvar2))]
|
||||
[_ #f])
|
||||
(Tvar-constraints tvar)))
|
||||
(absIntersect
|
||||
(map
|
||||
(lambda (tvar2) (ref-nt (chk-Tvar-L tvar2)))
|
||||
(Tvar-edgeto tvar))))]
|
||||
|
||||
[($ NT
|
||||
(and AV ($ AV _ (and template ($ template _ _ _ ref assign))
|
||||
misc fields+ fields-))
|
||||
'U)
|
||||
(let ([ref-i+
|
||||
(lambda (i)
|
||||
(ref-nt (chk-Tvar-U (vector-ref fields+ i))))]
|
||||
[ref-i-
|
||||
(lambda (i)
|
||||
(ref-nt (chk-Tvar-L (vector-ref fields- i))))])
|
||||
|
||||
(cond
|
||||
[(or
|
||||
(eq? template template-lam)
|
||||
(eq? template template-lam++))
|
||||
|
||||
(if (and
|
||||
(atprim? misc)
|
||||
(not (eq? (st:primitive-types) 'inferred)))
|
||||
|
||||
;; Is a primitive
|
||||
(when show?
|
||||
(case (st:primitive-types)
|
||||
[(prim) `(prim ,(atprim-sym misc))]
|
||||
[(given) (atprim-orig-type misc)]))
|
||||
|
||||
;; Print as lambda
|
||||
(let*-vals ( [(dom rng)
|
||||
(if (eq? template template-lam)
|
||||
(values (ref-i- 0) (ref-i+ 0))
|
||||
(values (ref-i+ 0) (ref-i+ 1)))])
|
||||
(when show?
|
||||
(match
|
||||
(match misc
|
||||
[('lam-info nargs restarg)
|
||||
(pretty-domain-list dom nargs restarg)]
|
||||
[_ (pretty-domain-list dom 0 #t)])
|
||||
[(args ())
|
||||
(append args (list '->* rng))]
|
||||
[(args restarg)
|
||||
(append args (list restarg '*->* rng))]))))]
|
||||
|
||||
;; Not a lambda
|
||||
[(memq (template-type template) '(object class))
|
||||
(cons
|
||||
(template-type template)
|
||||
(map-with-n
|
||||
(lambda (ivar-sym n) (list ivar-sym (ref-i+ n)))
|
||||
misc))]
|
||||
|
||||
[(st:show-assignable-part-of-fields)
|
||||
(list
|
||||
(template-type template)
|
||||
(map ref-i+ (filter number? (vector->list ref)))
|
||||
(map ref-i- (filter number? (vector->list assign))))]
|
||||
[(and
|
||||
(eq? (vector-length ref) 1)
|
||||
(not (vector-ref ref 0)))
|
||||
(list (template-type template) (ref-i- 0))]
|
||||
[(and
|
||||
(eq? (vector-length ref) 0)
|
||||
(eq? (vector-length assign) 0)
|
||||
(st:constants)
|
||||
(or (number? misc) (symbol? misc) (char? misc)))
|
||||
(if (symbol? misc) (list 'quote misc) misc)]
|
||||
[else
|
||||
(cons
|
||||
(template-type template)
|
||||
(map ref-i+ (filter number? (vector->list ref))))]))])])
|
||||
|
||||
(pretty-debug-sdl `(NT->SDL ,(nt->sym nt) = ,r))
|
||||
r))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (pretty-domain-list dom nargs restarg)
|
||||
(recur loop ([args '()][dom dom][nargs nargs])
|
||||
(match dom
|
||||
[('cons arg restarg)
|
||||
(loop (cons arg args) restarg (sub1 nargs))]
|
||||
[('nil)
|
||||
(list (reverse args) '())]
|
||||
['_
|
||||
(cond
|
||||
[(> nargs 0)
|
||||
(loop (cons '_ args) '_ (sub1 nargs))]
|
||||
[restarg
|
||||
(list (reverse args) '_)]
|
||||
[else
|
||||
(list (reverse args) '())])]
|
||||
[dom (list (reverse args) dom)])))
|
||||
|
||||
(define (pretty-range-list rng nrngs)
|
||||
(list '() rng))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define template-listof (constructor->template 'listof #f))
|
||||
|
||||
(define template-bool (constructor->template 'bool))
|
||||
|
||||
(define template-atom (constructor->template 'atom))
|
||||
|
||||
(define template-sexp (constructor->template 'sexp))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (listify-Tvar! tvar)
|
||||
;; If Tvar contains (union nil (cons x tvar))
|
||||
;; then replace by (list x)
|
||||
;;(pretty-print (get-Tvar-objs tvar))
|
||||
;; (show-sba-Tvar tvar)
|
||||
(match (get-Tvar-objs tvar)
|
||||
[(or
|
||||
( ($ AV _ (? (is-template? 'nil)))
|
||||
($ AV _ (? (is-template? 'cons)) _
|
||||
#(a (? (lambda (d) (eq? d tvar))))))
|
||||
( ($ AV _ (? (is-template? 'cons)) _
|
||||
#(a (? (lambda (d) (eq? d tvar)))))
|
||||
($ AV _ (? (is-template? 'nil)))))
|
||||
(set-Tvar-objs! tvar '())
|
||||
(new-AV! tvar (create-AV template-listof '() (vector a) (vector)))]
|
||||
[_ (void)]))
|
||||
|
||||
(define (boolify-Tvar! tvar)
|
||||
;; If Tvar contains (union true false)
|
||||
;; then replace those by bool
|
||||
(let* ([bool-things '(true false)])
|
||||
(when
|
||||
(andmap
|
||||
(lambda (bool-thing)
|
||||
(ormap
|
||||
(lambda (AV) (eq? (template-type (AV-template AV)) bool-thing))
|
||||
(get-Tvar-objs tvar)))
|
||||
bool-things)
|
||||
;; Do substitution
|
||||
(set-Tvar-objs! tvar
|
||||
(filter
|
||||
(lambda (AV)
|
||||
(not (memq (template-type (AV-template AV)) bool-things)))
|
||||
(get-Tvar-objs tvar)))
|
||||
(new-AV! tvar (create-AV template-bool '() (vector) (vector))))))
|
||||
|
||||
(define (atomify-Tvar! tvar)
|
||||
;; If Tvar contains (union nil num sym str char bool)
|
||||
;; then replace those by atom
|
||||
(let* ([atom-things '(nil num sym str char bool)])
|
||||
(when
|
||||
(andmap
|
||||
(lambda (atom-thing)
|
||||
(ormap
|
||||
(lambda (AV) (eq? (template-type (AV-template AV)) atom-thing))
|
||||
(get-Tvar-objs tvar)))
|
||||
atom-things)
|
||||
;; Do substitution
|
||||
(set-Tvar-objs! tvar
|
||||
(filter
|
||||
(lambda (AV)
|
||||
(not (memq (template-type (AV-template AV)) atom-things)))
|
||||
(get-Tvar-objs tvar)))
|
||||
(new-AV! tvar (create-AV template-atom '() (vector) (vector))))))
|
||||
|
||||
(define (sexpify-Tvar! tvar)
|
||||
;; If Tvar l contains (union atom (box l) (vec l) (cons l l)),
|
||||
;; then replace those by sexp
|
||||
(let* ([sexp-things '(atom box cons vec)])
|
||||
(when
|
||||
(andmap
|
||||
(lambda (sexp-thing)
|
||||
(ormap
|
||||
(match-lambda
|
||||
[($ AV _ ($ template type _ ref) _ fields+)
|
||||
(and (eq? type sexp-thing)
|
||||
(or (zero? (vector-length fields+))
|
||||
(eq? (vector-ref fields+ 0) tvar)))])
|
||||
(get-Tvar-objs tvar)))
|
||||
sexp-things)
|
||||
;; Do substitution
|
||||
(printf "Do substitution")
|
||||
(set-Tvar-objs! tvar
|
||||
(filter
|
||||
(lambda (AV)
|
||||
(not (memq (template-type (AV-template AV)) sexp-things)))
|
||||
(get-Tvar-objs tvar)))
|
||||
(new-AV! tvar (create-AV template-sexp '() (vector) (vector))))))
|
||||
|
||||
(define (classify-objectify-Tvar! tvar)
|
||||
;; For each ivarset in tvar,
|
||||
;; build an object AV
|
||||
|
||||
(pretty-debug-sdl `(classify-objectify-Tvar! ,(FlowType-name tvar)))
|
||||
|
||||
(letrec
|
||||
([make-thingy
|
||||
(lambda (tvar-get-ivars tvar-put-thingy name
|
||||
ivar-syms parent-ivars)
|
||||
(recur loop ([ivar-syms ivar-syms][parent-ivars parent-ivars])
|
||||
;; to ivar parents
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _
|
||||
(? (lambda (t) (eq? t template-ivarset)))
|
||||
ivar-extra-syms
|
||||
#(parent-parent-ivars))
|
||||
(loop
|
||||
(append ivar-syms ivar-extra-syms)
|
||||
parent-parent-ivars)]
|
||||
[_ (void)])
|
||||
(Tvar-objs parent-ivars))
|
||||
;; make thingy for this
|
||||
(when (or
|
||||
(null? (Tvar-objs parent-ivars))
|
||||
(ormap
|
||||
(lambda (AV)
|
||||
(not (eq? (AV-template AV) template-ivarset)))
|
||||
(Tvar-objs parent-ivars)))
|
||||
(pretty-debug-sdl2 `(all-ivars ,name ,ivar-syms))
|
||||
(let*
|
||||
( [ivar-syms (list->set ivar-syms)]
|
||||
[ivar-syms
|
||||
(sort
|
||||
(lambda (s1 s2)
|
||||
(string<?
|
||||
(symbol->string s1)
|
||||
(symbol->string s2)))
|
||||
ivar-syms)]
|
||||
[n+ (length ivar-syms)]
|
||||
[template-thingy
|
||||
(make-template
|
||||
name n+ 0
|
||||
(list->vector
|
||||
(recur loop ([n 0])
|
||||
(if (= n n+) '() (cons n (loop (add1 n))))))
|
||||
(vector)
|
||||
'()
|
||||
eq?)]
|
||||
[fields+
|
||||
(list->vector
|
||||
(map
|
||||
(lambda (ivar-sym)
|
||||
(let ([tvar-field (mk-Tvar 'object-field)])
|
||||
(new-con! tvar-get-ivars
|
||||
(create-con
|
||||
(get-ivar-template ivar-sym)
|
||||
0 tvar-field #t))
|
||||
tvar-field))
|
||||
ivar-syms))])
|
||||
(pretty-debug-sdl2 `(ivarset ,ivar-syms))
|
||||
(new-AV! tvar-put-thingy
|
||||
(create-AV template-thingy
|
||||
ivar-syms fields+ (vector)))))))])
|
||||
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AV _
|
||||
(? (lambda (t) (eq? t template-internal-class)))
|
||||
misc
|
||||
#(_ alpha_o _ _ alpha_v))
|
||||
|
||||
(make-thingy alpha_o tvar 'class '() alpha_v)]
|
||||
|
||||
[($ AV _
|
||||
(? (lambda (t) (eq? t template-ivarset)))
|
||||
ivar-syms
|
||||
#(parent-ivars))
|
||||
|
||||
(make-thingy tvar tvar 'object ivar-syms parent-ivars)]
|
||||
|
||||
[_ (void)])
|
||||
(Tvar-objs tvar))
|
||||
|
||||
;; Now drop any ivar, ivarset and class from the tvar
|
||||
(set-Tvar-objs! tvar
|
||||
(filter
|
||||
(lambda (AV)
|
||||
(let ([t (AV-template AV)])
|
||||
(not
|
||||
(or
|
||||
(memq template-all-ivars (template-super-templates t))
|
||||
(eq? t template-ivarset)
|
||||
(eq? t template-internal-class)))))
|
||||
(Tvar-objs tvar)))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
'(define (copy-depth-k tvar k)
|
||||
(let*-vals
|
||||
( [tvar-dots
|
||||
(mk-Tvar-init-AV 'dots
|
||||
(create-AV template-dots '() mt-vector mt-vector))]
|
||||
[tvar-empty
|
||||
(mk-Tvar 'depth-k-empty)]
|
||||
[(tvar-reached? tvar-reached! list-tvar-reached)
|
||||
(field->set alloc-Tvar-field)]
|
||||
[(AV-reached? AV-reached! list-AV-reached)
|
||||
(field->set alloc-AV-field)]
|
||||
[(tvar-nu tvar-nu!) (alloc-Tvar-field)]
|
||||
[(AV-nu AV-nu!) (alloc-AV-field)]
|
||||
)
|
||||
|
||||
(recur loop ([tvar tvar][k k])
|
||||
(when
|
||||
(and
|
||||
(not (zero? k))
|
||||
(not (tvar-reached? tvar)))
|
||||
(tvar-reached! tvar)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ _ _ fields+))
|
||||
(AV-reached! AV)
|
||||
(vector-for-each
|
||||
(lambda (tvar2) (loop tvar2 (sub1 k)))
|
||||
fields+)])
|
||||
(get-Tvar-objs tvar))))
|
||||
|
||||
(for-each
|
||||
(lambda (tvar) (tvar-nu! tvar (mk-Tvar 'copy-depth-k)))
|
||||
(list-tvar-reached))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template misc fields+ fields-))
|
||||
(AV-nu! AV
|
||||
(create-AV template misc
|
||||
(vector-map
|
||||
(lambda (tvar)
|
||||
(if (tvar-reached? tvar) (tvar-nu tvar) tvar-dots))
|
||||
fields+)
|
||||
(vector-map
|
||||
(lambda (_) tvar-empty)
|
||||
fields-)))])
|
||||
(list-AV-reached))
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(let ([nu (tvar-nu tvar)])
|
||||
(for-each
|
||||
(lambda (AV)
|
||||
(new-AV! nu (AV-nu AV)))
|
||||
(get-Tvar-objs tvar))))
|
||||
(list-tvar-reached))
|
||||
(pretty-debug-sdl2
|
||||
`(copy-depth-k
|
||||
src ,(Tvar-name tvar)
|
||||
depth ,k
|
||||
result ,(Tvar-name (tvar-nu tvar))
|
||||
size ,(length (list-AV-reached)) ,(length (list-tvar-reached))))
|
||||
(tvar-nu tvar)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define (copy-sdl-size-k tvar k)
|
||||
|
||||
(let*-vals
|
||||
( [tvar-dots
|
||||
(mk-Tvar-init-AV 'dots
|
||||
(create-AV template-dots '() mt-vector mt-vector))]
|
||||
[tvar-empty
|
||||
(mk-Tvar 'depth-k-empty)]
|
||||
[(tvar-reached? tvar-reached! list-tvar-reached)
|
||||
(field->set alloc-Tvar-field)]
|
||||
[(AV-reached? AV-reached! list-AV-reached)
|
||||
(field->set alloc-AV-field)]
|
||||
[(tvar-nu tvar-nu!) (alloc-Tvar-field)]
|
||||
[(AV-nu AV-nu!) (alloc-AV-field)]
|
||||
[stack (list tvar)]
|
||||
)
|
||||
|
||||
(recur loop ()
|
||||
(unless (>= 0 k)
|
||||
(match stack
|
||||
[(tvar . rest)
|
||||
(set! stack rest)
|
||||
(if (tvar-reached? tvar)
|
||||
(loop)
|
||||
(begin
|
||||
(set! k (sub1 k))
|
||||
(tvar-reached! tvar)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ _ _ fields+))
|
||||
(unless (AV-reached? AV)
|
||||
(set! k (sub1 k))
|
||||
(AV-reached! AV)
|
||||
(set! stack
|
||||
(append stack (reverse (vector->list fields+)))))])
|
||||
(get-Tvar-objs tvar))
|
||||
(loop)))]
|
||||
[() (void)])))
|
||||
|
||||
(for-each
|
||||
(lambda (tvar) (tvar-nu! tvar (mk-Tvar 'copy-depth-k)))
|
||||
(list-tvar-reached))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV _ template misc fields+ fields-))
|
||||
(AV-nu! AV
|
||||
(create-AV template misc
|
||||
(vector-map
|
||||
(lambda (tvar)
|
||||
(if (tvar-reached? tvar) (tvar-nu tvar) tvar-dots))
|
||||
fields+)
|
||||
(vector-map
|
||||
(lambda (_) tvar-empty)
|
||||
fields-)))])
|
||||
(list-AV-reached))
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(let ([nu (tvar-nu tvar)])
|
||||
(for-each
|
||||
(lambda (AV)
|
||||
(new-AV! nu (AV-nu AV)))
|
||||
(get-Tvar-objs tvar))))
|
||||
(list-tvar-reached))
|
||||
(assert (tvar-reached? tvar) 'copy-sdl-size-k k)
|
||||
(pretty-debug-sdl2
|
||||
`(copy-depth-k
|
||||
src ,(Tvar-name tvar)
|
||||
depth ,k
|
||||
result ,(Tvar-name (tvar-nu tvar))
|
||||
size ,(length (list-AV-reached)) ,(length (list-tvar-reached))))
|
||||
(tvar-nu tvar)))
|
||||
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -0,0 +1,110 @@
|
||||
;; seperate.ss
|
||||
;; Handles seperate compilation part
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (seperately-analyze-file file-thunk* out-file)
|
||||
;; Prepare language
|
||||
(when (eq? (select-language) 'none) (mrspidey:error "No language selected"))
|
||||
(init-input-type-expander!)
|
||||
(init-current-constructor-env!)
|
||||
|
||||
(match-let*
|
||||
([defs1 (load-parse-expand file-thunk*)]
|
||||
[_ (set! defs-expanded defs1)]
|
||||
[_ (init-kernel!)]
|
||||
[_ (init-misc-analysis)]
|
||||
[((out-env* in-env*) ...)
|
||||
(map-with-n
|
||||
(lambda (def n)
|
||||
(mrspidey:progress 'analyze (/ (add1 n) (length defs1)))
|
||||
(traverse-def def))
|
||||
defs1)]
|
||||
[instantiate-env*
|
||||
(lambda (env*)
|
||||
(apply append
|
||||
(map (lambda (env)
|
||||
(map
|
||||
(match-lambda
|
||||
[(and b (_ . (? AVS? AVS))) b]
|
||||
[(sym . (? procedure? thunk)) (cons sym (thunk))])
|
||||
env))
|
||||
env*)))]
|
||||
[out-env (instantiate-env* out-env*)]
|
||||
[in-env (instantiate-env* in-env*)]
|
||||
[extract-AVS (lambda (env) (map cdr env))]
|
||||
[AVS-out (extract-AVS out-env)]
|
||||
[AVS-in (extract-AVS in-env)]
|
||||
[(AVS-live AVS->nu) (minimize-constraints AVS-out AVS-in)]
|
||||
[convert-env
|
||||
(lambda (env)
|
||||
(map
|
||||
(match-lambda
|
||||
[(sym . AVS) (cons sym (AVS->nu AVS))])
|
||||
env))]
|
||||
[out-env (convert-env out-env)]
|
||||
[in-env (convert-env in-env)])
|
||||
|
||||
(write-constraint-set out-file AVS-live out-env in-env)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (write-constraint-set file AVS-live out-env in-env)
|
||||
(let* ([p (open-output-port file)]
|
||||
[disp (lambda (x) (display x p) (newline p))]
|
||||
[tag (gensym)]
|
||||
[rep-constraint
|
||||
(match-lambda
|
||||
[($ con _ ($ template type) field-no ($ AVS num))
|
||||
(list 'con type field-no num)]
|
||||
[($ con-filter _ ($ filter sign (($ template types) ...))
|
||||
($ AVS num))
|
||||
(list 'con-filter sign types num)])])
|
||||
|
||||
;; --- write AV and AVS's
|
||||
(disp num-AVS)
|
||||
(disp num-AV)
|
||||
;; --- write constructor-env
|
||||
(disp constructor-env)
|
||||
;; --- write AV
|
||||
(for-each
|
||||
(lambda (AVS)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV num ($ template type) misc fields))
|
||||
(unless (eq? (AV-aux AV) tag)
|
||||
(disp (list 'AV num type misc (map AVS-num fields)))
|
||||
(set-AV-aux! AV tag))])
|
||||
(AVS-orig-objs AVS)))
|
||||
list-AVS)
|
||||
;; --- write AVS
|
||||
(for-each
|
||||
(match-lambda
|
||||
[($ AVS num orig-objs _ constraints edgeto)
|
||||
(disp (list `AVS num
|
||||
(map AVS-num orig-objs)
|
||||
(map rep-constraint constraints)
|
||||
(map AVS-num edgeto)))])
|
||||
AVS-live)
|
||||
;; --- write out-env, in-env
|
||||
(disp `(out-env ,@(map AVS-nu out-env)))
|
||||
(disp `(in-env ,@(map AVS-nu in-env)))
|
||||
;; --- all done
|
||||
(close-output-port p)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (read-constraint-set file)
|
||||
;; returns AVS-live out-env in-env
|
||||
1
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (ts file)
|
||||
(parameterize
|
||||
([mrspidey:progress-handler (mrspidey:text-progress)]
|
||||
[mrspidey:error-handler mrspidey:text-error])
|
||||
(seperately-analyze-file (files->file-thunk* file) "test/out.za")))
|
||||
|
||||
|
||||
|
@ -0,0 +1,685 @@
|
||||
;; sba-sigs.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mzlib:unprefixed-core^
|
||||
( (open mzlib:pretty-print^)
|
||||
(open mzlib:file^)
|
||||
(open mzlib:function^)
|
||||
(open mzlib:compat^)
|
||||
(open mzlib:string^)))
|
||||
|
||||
(define-signature mrspidey:library-paras^
|
||||
(make-parameter-boolean
|
||||
make-parameter-integer
|
||||
make-parameter-list))
|
||||
|
||||
(define-signature mrspidey:library-list^
|
||||
(mapLR
|
||||
mapRL
|
||||
foldl-with-n
|
||||
foldr2
|
||||
filter
|
||||
filter-map
|
||||
filter-map-split
|
||||
rac
|
||||
rdc
|
||||
map-with-n
|
||||
for-each-with-n
|
||||
map-ilist
|
||||
length-ilist
|
||||
improper?
|
||||
flatten-ilist
|
||||
map2
|
||||
for-each2
|
||||
andmap2
|
||||
andmap2len
|
||||
ormap2
|
||||
list-n-copies
|
||||
count
|
||||
get-prefix
|
||||
mklist
|
||||
nth
|
||||
list-pos
|
||||
list-pos-equal
|
||||
find
|
||||
index
|
||||
))
|
||||
|
||||
(define-signature mrspidey:library-vec^
|
||||
( vector-copy
|
||||
vector-map1
|
||||
vector-map2
|
||||
vector-map
|
||||
vector-for-each-with-n
|
||||
vector-for-each
|
||||
vector-andmap1
|
||||
vector-andmap2
|
||||
vector-andmap
|
||||
vector-ormap1
|
||||
vector-ormap2
|
||||
vector-ormap
|
||||
vector-zero!))
|
||||
|
||||
(define-signature mrspidey:library-set^
|
||||
(empty-set
|
||||
empty-set?
|
||||
set
|
||||
list->set
|
||||
list->set-equal?
|
||||
element-of?
|
||||
cardinality
|
||||
set<=
|
||||
set-eq?
|
||||
union2
|
||||
union
|
||||
setdiff2
|
||||
setdiff
|
||||
intersect2
|
||||
intersect))
|
||||
|
||||
(define-signature mrspidey:library-misc^
|
||||
(symbol-append
|
||||
get-cpu-time
|
||||
get&return-cpu-time
|
||||
make-timer
|
||||
clear-timer!
|
||||
record-time
|
||||
strip-string
|
||||
padl
|
||||
padr
|
||||
chop-number
|
||||
substring?
|
||||
char-find
|
||||
file-newer
|
||||
eqc?
|
||||
))
|
||||
|
||||
(define-signature
|
||||
mrspidey:env^
|
||||
( empty-env lookup-or-fail lookup-or-#f lookup bound-in-env?
|
||||
extend-env extend-env* join-env bang-env!
|
||||
env:change-binding env:remove
|
||||
))
|
||||
|
||||
(define-signature mrspidey:library^
|
||||
((open mrspidey:library-paras^)
|
||||
(open mrspidey:library-list^)
|
||||
(open mrspidey:library-vec^)
|
||||
(open mrspidey:library-set^)
|
||||
(open mrspidey:library-misc^)
|
||||
(open mrspidey:env^)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:interaction^
|
||||
(mrspidey:error
|
||||
mrspidey:warning
|
||||
mrspidey:internal-error
|
||||
mrspidey:add-summary
|
||||
mrspidey:add-summary-handler
|
||||
mrspidey:progress
|
||||
mrspidey:progress-handler
|
||||
record-analyzed-file
|
||||
record-analyzed-file-hook
|
||||
|
||||
))
|
||||
|
||||
(define-signature mrspidey:config^
|
||||
( st:restricted
|
||||
st:name
|
||||
st:version
|
||||
|
||||
st:fake-reader
|
||||
st:system-expand
|
||||
|
||||
st:constants
|
||||
st:const-merge-size
|
||||
st:if-split
|
||||
st:flow-sensitive
|
||||
st:fo-units
|
||||
st:lazy-fo-units
|
||||
st:cache-units
|
||||
st:whole-program
|
||||
st:special-fo-prims
|
||||
st:see-void
|
||||
st:cons-mutable
|
||||
st:use-fo-ftype
|
||||
need-label-types
|
||||
need-explanation
|
||||
st:zero-old-constraint-sets
|
||||
st:zero-old-asts
|
||||
|
||||
st:minimize-respect-assignable-part-of-fields
|
||||
|
||||
st:constraint-simplification-poly
|
||||
st:polymorphism
|
||||
|
||||
st:unit-read-za
|
||||
st:unit-write-za
|
||||
st:unit-simplify
|
||||
st:unit-separate-S
|
||||
st:save-za-in
|
||||
|
||||
;; --- Type Viewing Parameters
|
||||
st:sdl-fo
|
||||
st:sdl-fo-ivars
|
||||
st:sdl-fo-struct-fields
|
||||
st:sdl-fo-depth-limit?
|
||||
st:sdl-fo-depth-limit
|
||||
st:sdl-fo-size-limit?
|
||||
st:sdl-fo-size-limit
|
||||
st:sdl-constraint-simplification
|
||||
st:show-assignable-part-of-fields
|
||||
st:listify-etc
|
||||
st:sdl-constructor/selector
|
||||
st:naming-strategy
|
||||
st:primitive-types
|
||||
st:expand-output-type
|
||||
st:sdl-tidy
|
||||
st:pretty-type-width
|
||||
|
||||
st:check-kernel
|
||||
st:compare-min-algs
|
||||
|
||||
;; --- Checking Parameters
|
||||
st:all-checks
|
||||
|
||||
;; st:show-filters
|
||||
;; st:add-hyper-links
|
||||
;; st:dont-combine-definitions
|
||||
;; st:structure-opaque
|
||||
;; st:library-prims
|
||||
;; st:topo-sort
|
||||
|
||||
mrspidey:control-fn
|
||||
|
||||
))
|
||||
|
||||
(define-signature mrspidey:debugging^
|
||||
(debugging
|
||||
debugging-front
|
||||
debugging-traverse
|
||||
debugging-unit
|
||||
debugging-check
|
||||
debugging-atenv
|
||||
debugging-atype
|
||||
debugging-sdl
|
||||
debugging-sdl2
|
||||
debugging-gui
|
||||
|
||||
debugging-min
|
||||
debugging-min2
|
||||
debugging-few
|
||||
debugging-gram
|
||||
debugging-dfa-min
|
||||
debugging-min-table
|
||||
debugging-object
|
||||
|
||||
timing-min
|
||||
|
||||
pretty-print-debug
|
||||
set-debug-flag
|
||||
))
|
||||
|
||||
(define-signature mrspidey:CDL^
|
||||
((open mrspidey:config^)
|
||||
(open mrspidey:debugging^)
|
||||
(open mrspidey:library^)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Kernel analysis stuff
|
||||
|
||||
(define-signature mrspidey:hash^
|
||||
( init-hash-table
|
||||
hash-fn hash-fn*
|
||||
add-entry hash-find hash-table-info
|
||||
capture-hash-table-state restore-hash-table-state!
|
||||
prompt-hash-table-state unprompt-hash-table-state!
|
||||
free-hash-table-state!
|
||||
))
|
||||
|
||||
(define-signature
|
||||
mrspidey:kernel^
|
||||
(;; --- Structures
|
||||
(struct FlowType
|
||||
(num expr arrowto arrowfrom type-annotation proplist values-ftype))
|
||||
num-ftype list-ftype num-edge
|
||||
add-FlowType-arrow! add-FlowType!
|
||||
add-FlowType-prop! get-FlowType-prop FlowType-name
|
||||
|
||||
(struct Tvar (objs orig-objs constraints edgeto edgefrom L U))
|
||||
|
||||
(struct AV (num template misc fields+ fields- U PU))
|
||||
(struct template
|
||||
(type num+ num- ref assign super-templates misc-eq?))
|
||||
(struct con (num template field-no tvar misc sign))
|
||||
(struct con-filter (num filter tvar))
|
||||
(struct filter (sign templates))
|
||||
create-filter
|
||||
mt-vector
|
||||
|
||||
;; --- Values
|
||||
num-con
|
||||
num-AV
|
||||
num-AV-in-Tvar
|
||||
|
||||
;; --- Functions
|
||||
init-kernel!
|
||||
create-AV
|
||||
mk-Tvar
|
||||
create-con create-con-misc create-con-filter
|
||||
new-edge! new-bidir-edge! new-edge-para new-AV! new-create-AV! new-con!
|
||||
new-leq-top-s! new-geq-top-s!
|
||||
mk-Tvar-init-AV
|
||||
constraint-system-size
|
||||
get-Tvar-objs
|
||||
add-AV! add-con! add-edge!
|
||||
Tvar-name
|
||||
|
||||
save-kernel-state restore-kernel-state!
|
||||
prompt-kernel-state unprompt-kernel-state!
|
||||
free-kernel-state!
|
||||
|
||||
alloc-Tvar-field alloc-AV-field field->set
|
||||
check-kernel-ok
|
||||
really-check-kernel-ok
|
||||
check-unreachable
|
||||
))
|
||||
|
||||
(define-signature
|
||||
mrspidey:gram^
|
||||
( ;; --- grsyms
|
||||
(struct grsym (fn mono))
|
||||
(struct grsym-normal (template misc field-no))
|
||||
(struct grsym-misc ())
|
||||
grsym-eq?
|
||||
|
||||
;; --- rhs
|
||||
(struct rhs (grsym nt))
|
||||
add-rhs!
|
||||
|
||||
calc-productions!
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Front end stuff
|
||||
|
||||
(define-signature mrspidey:loadexpand^
|
||||
(open-code-file
|
||||
zodiac:read*
|
||||
mrspidey:zprogress
|
||||
strip-hash-percent
|
||||
system-expand-if-necy
|
||||
expand-zexp->port
|
||||
|
||||
clear-file-time-cache!
|
||||
extend-file-time-cache!
|
||||
zodiac-time
|
||||
zodiac-time*
|
||||
|
||||
init-expand!
|
||||
my-scheme-expand-program
|
||||
))
|
||||
|
||||
;;(define-signature mrspidey:parser^ (top-level-parse-defs top-level-parse-exp))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:atenv^
|
||||
( atenv:empty
|
||||
atenv:extend
|
||||
atenv:extend-mutated
|
||||
atenv:extend*
|
||||
atenv:extend-voids
|
||||
atenv:extend-undefineds
|
||||
atenv:lookup
|
||||
atenv:change-binding
|
||||
atenv:change-bindings
|
||||
atenv:capture-locs
|
||||
atenv:unflush
|
||||
atenv:flush!
|
||||
atenv->pretty
|
||||
atenv:domain
|
||||
atenv:ok?
|
||||
link-parsed-ftype!
|
||||
))
|
||||
|
||||
(define-signature mrspidey:traverse^
|
||||
( top-level-traverse-defs
|
||||
traverse-defs
|
||||
;;traverse-def
|
||||
traverse-exp
|
||||
))
|
||||
|
||||
(define-signature mrspidey:atype^
|
||||
((struct fo-FlowType (def))
|
||||
FlowType->Atype
|
||||
create-fo-FlowType
|
||||
fo-Atype? poly-atype?
|
||||
|
||||
(struct atconst (c))
|
||||
(struct schema (tvar tvar* edges))
|
||||
(struct atprim (sym type domain-filters predicate-fn attrs orig-type))
|
||||
(struct atthunk (thunk))
|
||||
(struct atstruct (struct:sym super-constructors
|
||||
parent-gen-args
|
||||
parent-match-args
|
||||
parent-field-types
|
||||
parent-list-mutable))
|
||||
(struct atvalues (values))
|
||||
wrap-value extract-1st-value multiple-value-components
|
||||
|
||||
(struct atunit (imports exports result expr))
|
||||
(struct atlunit (ui))
|
||||
|
||||
FlowType->Tvar
|
||||
Atype->Tvar
|
||||
FlowType->pretty
|
||||
FlowType->SDL
|
||||
copy-ftype
|
||||
))
|
||||
|
||||
(define-signature mrspidey:atlunit^
|
||||
(create-atlunit-unit
|
||||
create-atlunit-cmpd
|
||||
create-atlunit-reference
|
||||
|
||||
apply-unit
|
||||
atlunit->atunit
|
||||
apply-atlunit
|
||||
|
||||
))
|
||||
|
||||
|
||||
(define-signature mrspidey:type-env^
|
||||
(global-tref-env
|
||||
global-tdef-env
|
||||
global-tbang-env
|
||||
|
||||
add-global-tref!
|
||||
add-global-tdef!
|
||||
add-global-tbang!
|
||||
init-global-tenv!
|
||||
|
||||
connect-bangs-defs
|
||||
report-duplicate-defs
|
||||
connect-refs-defs
|
||||
report-unbound-vars
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; ???
|
||||
|
||||
(define-signature mrspidey:templates^
|
||||
( constructor->template
|
||||
constructor-env
|
||||
set-constructor-env!
|
||||
extend-constructor-env!
|
||||
add-constructor!
|
||||
constructor-alias!
|
||||
record-super-constructor!
|
||||
record-super-constructor-of-template!
|
||||
record-super-template!
|
||||
|
||||
lam-misc-eq?
|
||||
template-lam
|
||||
template-lam++
|
||||
filter-not-lam
|
||||
template-cons
|
||||
template-nil
|
||||
template-num
|
||||
template-sym
|
||||
template-str
|
||||
template-char
|
||||
template-void
|
||||
template-undefined
|
||||
template-true
|
||||
template-false
|
||||
template-promise
|
||||
template-unit
|
||||
template-structure
|
||||
template-mvalues
|
||||
template-internal-class
|
||||
template-all-ivars
|
||||
template-dots
|
||||
;;template-ivar-box
|
||||
template-top-s
|
||||
template-ivarset
|
||||
|
||||
init-default-constructor-env!
|
||||
|
||||
saved-constructor-env
|
||||
init-constructor-env!
|
||||
|
||||
get-unit-import-template
|
||||
get-unit-export-template
|
||||
get-ivar-template
|
||||
|
||||
type-constructor?
|
||||
lookup-template
|
||||
lookup-template-or-error
|
||||
is-template?
|
||||
))
|
||||
|
||||
(define-signature mrspidey:kernel-aux^
|
||||
( make-constructed-AV-template
|
||||
make-constructed-AV
|
||||
make-constructed-Tvar
|
||||
|
||||
make-AV-cons
|
||||
make-con-car
|
||||
make-con-cdr
|
||||
make-con-dom
|
||||
make-con-rng
|
||||
;make-con-arg-car
|
||||
;make-con-arg-cdr
|
||||
make-AV-vec
|
||||
make-AV-lam
|
||||
|
||||
AV-nil
|
||||
AV-numb
|
||||
AV-sym
|
||||
AV-str
|
||||
AV-char
|
||||
AV-true
|
||||
AV-false
|
||||
AV-void
|
||||
AV-undefined
|
||||
AV-top-s
|
||||
|
||||
mk-tvar-nil
|
||||
mk-tvar-numb
|
||||
mk-tvar-sym
|
||||
mk-tvar-str
|
||||
mk-tvar-char
|
||||
mk-tvar-void
|
||||
mk-tvar-undefined
|
||||
mk-tvar-true
|
||||
mk-tvar-false
|
||||
mk-tvar-empty
|
||||
|
||||
init-common-AV!
|
||||
traverse-simple-const
|
||||
traverse-const-exact
|
||||
|
||||
Tvar-transitive-edgeto
|
||||
copy-constraint-set
|
||||
AV->rep
|
||||
|
||||
;; --- NTs
|
||||
(struct NT (tvar type rhs*))
|
||||
mk-Tvar-NTs! mk-AV-NTs!
|
||||
alloc-NT-field
|
||||
nt->sym
|
||||
select-L
|
||||
select-U
|
||||
chk-Tvar-U
|
||||
chk-Tvar-L
|
||||
chk-AV-U
|
||||
))
|
||||
|
||||
(define-signature mrspidey:sdl^
|
||||
(Tvar->SDL))
|
||||
|
||||
(define-signature mrspidey:languages^
|
||||
( st:language
|
||||
initialize-language!
|
||||
st:numops
|
||||
get-default-bindings
|
||||
make-expander-namespace
|
||||
))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:typelang^
|
||||
( absUnion absunion absIntersect absintersect
|
||||
init-output-type-expander! install-output-type-expander!
|
||||
init-input-type-expander!
|
||||
install-input-type-expander!
|
||||
expand-input-type expand-input-type-err expand-output-type
|
||||
typevar?
|
||||
|
||||
type->templates
|
||||
split-schema
|
||||
schema->con
|
||||
tschema->con
|
||||
tschema->con-for-nargs
|
||||
;;dom+rng-for-nargs
|
||||
Tvar-in-type?
|
||||
primitive->atprim))
|
||||
|
||||
(define-signature mrspidey:contained^
|
||||
(Tvar-containment?))
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:min^
|
||||
( minimize-constraints-&-compare
|
||||
minimize-constraints
|
||||
min-record-progress))
|
||||
|
||||
(define-signature mrspidey:min-live^
|
||||
( copy-live-constraints
|
||||
copy-live-constraints-noe
|
||||
calc-live-tvars-nts
|
||||
copy-constraints-equiv!
|
||||
follow-antimono-fields))
|
||||
|
||||
(define-signature mrspidey:find-nonempty-tvars^
|
||||
( copy-nonempty-tvars
|
||||
find-nonempty-tvars))
|
||||
|
||||
(define-signature mrspidey:min-live-few-e^
|
||||
(copy-live-constraints-few-e))
|
||||
|
||||
(define-signature mrspidey:hopcroft^
|
||||
(Hopcroft-calc-equivalences))
|
||||
|
||||
(define-signature mrspidey:min-dfa-fast^
|
||||
( minimize-constraints-dfa-min-lub
|
||||
minimize-constraints-dfa-min-glb))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:calc-checks^
|
||||
( calc-checks
|
||||
calc-type-annotations
|
||||
(struct annotation (loc))
|
||||
(struct check-annotation (text num rest))
|
||||
(struct uncheck-annotation (text))
|
||||
(struct type-annotation (end-first finish FlowType))
|
||||
))
|
||||
|
||||
(define-signature mrspidey:za^
|
||||
(read-za write-za))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:program^
|
||||
(analyze-program global-def-env initialize-analysis!))
|
||||
|
||||
(define-signature mrspidey:driver^
|
||||
(st:analyze st: st:type-fn st:help st:set-debug))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature
|
||||
mrspidey:zodiac-aux^
|
||||
( compat compat*
|
||||
ast-size const-size
|
||||
unparse-dynamic-letd
|
||||
stripper
|
||||
|
||||
parsed-ftype set-parsed-ftype!
|
||||
parsed-check set-parsed-check!
|
||||
parsed-atprim set-parsed-atprim!
|
||||
app-tvar-args set-app-tvar-args!
|
||||
binding-refs set-binding-refs!
|
||||
binding-mutated set-binding-mutated!
|
||||
varref-binding
|
||||
my-create-binding
|
||||
|
||||
lambda-flatten-arglist
|
||||
|
||||
no-location
|
||||
location-inc
|
||||
determine-end-first-token
|
||||
|
||||
parsed-value?
|
||||
free-refs
|
||||
free-vars
|
||||
initialize-mutated
|
||||
free-vars-defs
|
||||
zero!
|
||||
inline-begins
|
||||
))
|
||||
|
||||
(define-signature mrspidey:zodiac^
|
||||
((open zodiac:system^) (open mrspidey:zodiac-aux^)))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define-signature mrspidey:hyper^
|
||||
( analysis-set-arrow-filter!
|
||||
analysis-filter-on?
|
||||
analysis-get-filters
|
||||
analysis-shortest-path
|
||||
analysis-parents
|
||||
analysis-children
|
||||
analysis-ancestors
|
||||
analysis-descendants
|
||||
analysis-callback
|
||||
analysis-get-param
|
||||
analysis-set-param!
|
||||
calc-annotations
|
||||
st:analyze-and-make-annotations
|
||||
|
||||
))
|
||||
|
||||
(define-signature mrspidey:sba^
|
||||
( (open mrspidey:driver^)
|
||||
(open mrspidey:CDL^)
|
||||
(open mrspidey:atype^)
|
||||
(open mrspidey:hyper^)
|
||||
(open mrspidey:kernel^)
|
||||
(open mrspidey:calc-checks^)
|
||||
(open mrspidey:languages^)
|
||||
(unit zodiac : mrspidey:zodiac^)
|
||||
))
|
||||
|
||||
; ----------------------------------------------------------------------
|
@ -0,0 +1,303 @@
|
||||
;; templates.ss
|
||||
;; Handles the constructor environment,
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;;
|
||||
;; ======================================================================
|
||||
;; Constructor environments: symbol -> template
|
||||
;; First a helper function
|
||||
|
||||
(define (constructor->template con . modes)
|
||||
(let* ( [n (length modes)]
|
||||
[assign (make-vector n #f)]
|
||||
[ref (make-vector n #f)])
|
||||
(recur loop ([i 0][n 0][modes modes])
|
||||
(match modes
|
||||
[() (make-template con n i ref assign '() eqv?)]
|
||||
[(#t . rest)
|
||||
(vector-set! ref n n)
|
||||
(vector-set! assign n i)
|
||||
(loop (add1 i) (add1 n) rest)]
|
||||
[(#f . rest)
|
||||
(vector-set! ref n n)
|
||||
(vector-set! assign n #f)
|
||||
(loop i (add1 n) rest)]))))
|
||||
|
||||
;; ======================================================================
|
||||
;; The constructor environment
|
||||
|
||||
(define constructor-env (void))
|
||||
|
||||
(define (set-constructor-env! c)
|
||||
(set! constructor-env (make-hash-table))
|
||||
(hash-table-for-each c
|
||||
(lambda (key val)
|
||||
(hash-table-put! constructor-env key val))))
|
||||
|
||||
(define (extend-constructor-env! template)
|
||||
(let* ( [type (template-type template)]
|
||||
[old (hash-table-get constructor-env type (lambda () #f))])
|
||||
(if old
|
||||
(match (list template old)
|
||||
[( ($ template _ n+1 n-1 ref1 assign1 super1 _)
|
||||
($ template _ n+2 n-2 ref2 assign2 super2 _))
|
||||
(unless (and (= n+1 n+2)
|
||||
(= n-1 n-2)
|
||||
(equal? assign1 assign2)
|
||||
(equal? ref1 ref2)
|
||||
(equal? super1 super2))
|
||||
(pretty-print-debug
|
||||
`( (,n+1 ,n-1 ,ref1 ,assign1 ,(map template-type super1))
|
||||
(,n+2 ,n-2 ,ref2 ,assign2 ,(map template-type super2))))
|
||||
(mrspidey:error
|
||||
(format "New definition of template ~s does not match old"
|
||||
type)))
|
||||
old])
|
||||
(begin
|
||||
(hash-table-put! constructor-env type template)
|
||||
template))))
|
||||
|
||||
(define (add-constructor! con . modes)
|
||||
(extend-constructor-env! (apply constructor->template con modes)))
|
||||
|
||||
(define (constructor-alias! new-con old-con)
|
||||
(hash-table-put! constructor-env new-con
|
||||
(lookup-template-or-error old-con)))
|
||||
|
||||
(define (record-super-constructor! super-C C)
|
||||
(record-super-constructor-of-template!
|
||||
super-C (lookup-template-or-error C)))
|
||||
|
||||
(define (record-super-constructor-of-template! super-C T)
|
||||
(record-super-template! (lookup-template-or-error super-C) T))
|
||||
|
||||
(define (record-super-template! super-T T)
|
||||
(set-template-super-templates!
|
||||
T
|
||||
(cons super-T (template-super-templates T))))
|
||||
|
||||
;; ======================================================================
|
||||
;; Default templates
|
||||
|
||||
;(define-typed-structure (lam-info nargs restarg))
|
||||
|
||||
(define lam-misc-eq?
|
||||
(match-lambda*
|
||||
[(('lam-info nargs1 restarg1) ('lam-info nargs2 restarg2))
|
||||
(and (= nargs1 nargs2) (eqv? restarg1 restarg2))
|
||||
#t]
|
||||
[(x y) (eq? x y)]))
|
||||
|
||||
(define template-lam
|
||||
(make-template
|
||||
'lambda
|
||||
1
|
||||
1
|
||||
(vector #f 0)
|
||||
(vector 0 #f)
|
||||
'()
|
||||
lam-misc-eq?))
|
||||
|
||||
(define filter-not-lam
|
||||
(create-filter #f (list template-lam)))
|
||||
|
||||
(define template-lam++ ;; monotonic in both positions
|
||||
(make-template
|
||||
'lambda
|
||||
2
|
||||
0
|
||||
(vector 0 1)
|
||||
(vector)
|
||||
'()
|
||||
lam-misc-eq?))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define template-top-s (void))
|
||||
(define template-cons (void))
|
||||
(define template-nil (void))
|
||||
(define template-num (void))
|
||||
(define template-sym (void))
|
||||
(define template-str (void))
|
||||
(define template-char (void))
|
||||
(define template-void (void))
|
||||
(define template-undefined (void))
|
||||
(define template-true (void))
|
||||
(define template-false (void))
|
||||
(define template-promise (void))
|
||||
(define template-unit (void))
|
||||
(define template-structure (void))
|
||||
(define template-mvalues (void))
|
||||
(define template-internal-class (void))
|
||||
(define template-all-ivars (void))
|
||||
(define template-dots (void))
|
||||
(define template-ivarset (void))
|
||||
|
||||
(define (init-default-constructor-env!)
|
||||
(pretty-debug ' (init-default-constructor-env!))
|
||||
;; These are things needed by the analysis
|
||||
(set! constructor-env (make-hash-table))
|
||||
(hash-table-put! constructor-env 'lambda template-lam)
|
||||
(set! template-top-s (add-constructor! 'top-s))
|
||||
(set! template-cons
|
||||
(if (st:cons-mutable)
|
||||
(add-constructor! 'cons #t #t)
|
||||
(add-constructor! 'cons #f #f)))
|
||||
(set! template-nil (add-constructor! 'nil ))
|
||||
(set! template-num (add-constructor! 'num ))
|
||||
(set! template-sym (add-constructor! 'sym ))
|
||||
(set! template-str (add-constructor! 'str ))
|
||||
(set! template-char (add-constructor! 'char ))
|
||||
(set! template-void (add-constructor! 'void ))
|
||||
(set! template-undefined (add-constructor! 'undefined))
|
||||
(set! template-true (add-constructor! 'true ))
|
||||
(set! template-false (add-constructor! 'false))
|
||||
(set! template-promise (add-constructor! 'promise #f))
|
||||
(set! template-unit (add-constructor! 'unit-result* #f))
|
||||
(set! template-structure (add-constructor! 'structure:))
|
||||
(set! template-mvalues (add-constructor! 'mvalues #f))
|
||||
(set! template-internal-class
|
||||
(extend-constructor-env!
|
||||
(make-template
|
||||
'internal-class
|
||||
4 4
|
||||
(vector 0 1 2 #f #f 3 #f #f 4)
|
||||
(vector #f #f #f 0 1 #f 2 3 #f)
|
||||
'() eq?)))
|
||||
(set! template-all-ivars
|
||||
(extend-constructor-env!
|
||||
(make-template
|
||||
'all-ivars
|
||||
1
|
||||
0
|
||||
(vector 0)
|
||||
(vector #f)
|
||||
'()
|
||||
eq?)))
|
||||
(set! template-dots (add-constructor! '...))
|
||||
(set! template-ivarset (add-constructor! 'ivarset #t))
|
||||
)
|
||||
|
||||
; ======================================================================
|
||||
; The "template-prompt"
|
||||
|
||||
(define saved-constructor-env (make-hash-table))
|
||||
|
||||
(define (init-constructor-env!)
|
||||
(set! constructor-env saved-constructor-env)
|
||||
(set! unit-import-export-env (vector (make-hash-table) (make-hash-table)))
|
||||
(set! object-ivar-template-env (make-hash-table))
|
||||
)
|
||||
|
||||
; ======================================================================
|
||||
; Unit templates
|
||||
|
||||
(define unit-import-export-env (vector (make-hash-table) (make-hash-table)))
|
||||
|
||||
(define (get-unit-import-export-template ndx sym thunk)
|
||||
(hash-table-get
|
||||
(vector-ref unit-import-export-env ndx)
|
||||
sym
|
||||
(lambda ()
|
||||
(let ([template (thunk)])
|
||||
(hash-table-put!
|
||||
(vector-ref unit-import-export-env ndx)
|
||||
sym template)
|
||||
template))))
|
||||
|
||||
(define (get-unit-import-template sym)
|
||||
(get-unit-import-export-template
|
||||
0 sym
|
||||
(lambda ()
|
||||
(extend-constructor-env!
|
||||
(make-template
|
||||
(symbol-append 'unit-import- sym)
|
||||
0
|
||||
1
|
||||
(vector #f)
|
||||
(vector 0)
|
||||
'()
|
||||
eq?)))))
|
||||
|
||||
(define (get-unit-export-template sym)
|
||||
(assert (symbol? sym) 'get-unit-export-template)
|
||||
(get-unit-import-export-template
|
||||
1 sym
|
||||
(lambda ()
|
||||
(extend-constructor-env!
|
||||
(make-template
|
||||
(symbol-append 'unit-export- sym)
|
||||
1
|
||||
0
|
||||
(vector 0)
|
||||
(vector #f)
|
||||
'()
|
||||
eq?)))))
|
||||
|
||||
; ======================================================================
|
||||
; Object templates
|
||||
|
||||
(define object-ivar-template-env (make-hash-table))
|
||||
|
||||
(define (get-ivar-template sym)
|
||||
(assert (symbol? sym) 'get-ivar-template sym)
|
||||
(hash-table-get
|
||||
object-ivar-template-env
|
||||
sym
|
||||
(lambda ()
|
||||
(let ([template (make-template
|
||||
(symbol-append 'ivar- sym)
|
||||
1
|
||||
0
|
||||
(vector 0)
|
||||
(vector #f)
|
||||
'()
|
||||
eq?)])
|
||||
(hash-table-put! object-ivar-template-env sym template)
|
||||
(record-super-template! template-all-ivars template)
|
||||
(extend-constructor-env! template)
|
||||
template))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (type-constructor? C)
|
||||
(if
|
||||
(hash-table-get constructor-env C (lambda () #f))
|
||||
#t #f))
|
||||
|
||||
(define (lookup-template C)
|
||||
(hash-table-get constructor-env C (lambda () #f)))
|
||||
|
||||
(define (lookup-template-or-error C)
|
||||
(or (lookup-template C)
|
||||
(mrspidey:error (format "Unknown type constructor ~s" C))))
|
||||
|
||||
(define is-template?
|
||||
(lambda (name)
|
||||
(lambda (t)
|
||||
(eq? t (lookup-template name)))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,775 @@
|
||||
;; test-suite1.ss
|
||||
;; Development helper file
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
;; Testing files:
|
||||
|
||||
(define (run-test-suites fn)
|
||||
(letrec ([doit
|
||||
(case-lambda
|
||||
[(s) (doit s 0 #f)]
|
||||
[(s a) (doit s a #f)]
|
||||
[(s a c)
|
||||
(fn (string-append "~/Spidey/test-suite/" s))
|
||||
(when a
|
||||
(unless (= (type-assert-failed-total 0) a)
|
||||
(error 'run-test-suites "Wrong # failed assertions!")))
|
||||
(when c
|
||||
(unless (= (total-checks 0) c)
|
||||
(error 'run-test-suites "Wrong # checks!")))])])
|
||||
|
||||
;; --- Core Scheme
|
||||
(doit "testall.ss" 1)
|
||||
(doit "test-const.ss")
|
||||
(doit "test-exprs.ss")
|
||||
(doit "test-if-split.ss")
|
||||
(doit "test-flow.ss")
|
||||
(doit "test-box.ss")
|
||||
(doit "test-user-prims.ss")
|
||||
(doit "test-struct.ss")
|
||||
(doit "test-mvalues.ss")
|
||||
(doit "test-checks.ss" 0 6)
|
||||
(doit "test-no-checks.ss" 0 0)
|
||||
|
||||
;; --- Objects
|
||||
(doit "test-obj-syntax.ss")
|
||||
(doit "test-obj-simple.ss")
|
||||
(doit "test-obj-thread.ss")
|
||||
(doit "test-obj-derive.ss")
|
||||
(doit "mflatt.ss" 0 3)
|
||||
(doit "../test/trivia/trivia-unit.ss" 0 1)
|
||||
|
||||
;; --- Units
|
||||
(dynamic-let ([st:system-expand #t])
|
||||
(dynamic-let ([st:fo-units #t]) (doit "test-unit.ss" 0))
|
||||
(dynamic-let ([st:fo-units #f]) (doit "test-unit.ss" 0))
|
||||
;;(doit "test-fo-units.ss" 0)
|
||||
)
|
||||
(doit "../test/trivia/trivia-unit.ss" 0 1)
|
||||
|
||||
"MrSpidey passes the test suite :-)"
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define mred-system
|
||||
'(
|
||||
"autoload.ss"
|
||||
"autosave.ss"
|
||||
"canvas.ss"
|
||||
"connect.ss"
|
||||
"console.ss"
|
||||
"containr.ss"
|
||||
"contfram.ss"
|
||||
"contkids.ss"
|
||||
"contpanl.ss"
|
||||
"cparens.ss"
|
||||
"cppmode.ss"
|
||||
"edframe.ss"
|
||||
"edit.ss"
|
||||
"exit.ss"
|
||||
"exn.ss"
|
||||
"fileutil.ss"
|
||||
"finder.ss"
|
||||
"findstr.ss"
|
||||
"frame.ss"
|
||||
"group.ss"
|
||||
"guiutils.ss"
|
||||
"handler.ss"
|
||||
"html.ss"
|
||||
"hyper.ss"
|
||||
"hypersig.ss"
|
||||
"hyprdial.ss"
|
||||
"hypredit.ss"
|
||||
"hyprfram.ss"
|
||||
"icon.ss"
|
||||
"include.ss"
|
||||
"keys.ss"
|
||||
"link.ss"
|
||||
"macros.ss"
|
||||
"mcache.ss"
|
||||
"menu.ss"
|
||||
"mode.ss"
|
||||
"mrsystem.ss"
|
||||
"noconsle.ss"
|
||||
"panel.ss"
|
||||
"paren.ss"
|
||||
"prefs.ss"
|
||||
"project.ss"
|
||||
"sig.ss"
|
||||
"sparen.ss"
|
||||
"ssmode.ss"
|
||||
"url.ss"
|
||||
"version.ss"
|
||||
))
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define benchmark-files
|
||||
(append
|
||||
(map (lambda (x) (string-append "~/Spidey/benchmarks/" x ".ss"))
|
||||
'(
|
||||
"one"
|
||||
"const"
|
||||
"sum"
|
||||
"qsort"
|
||||
;; Programs from experiment
|
||||
"gauss"
|
||||
"du"
|
||||
"hanoi"
|
||||
"merge"
|
||||
"np"
|
||||
"tc"
|
||||
|
||||
"taut"
|
||||
|
||||
;; Misc others
|
||||
"sba"
|
||||
"bignum"
|
||||
;;"TC"
|
||||
"elev"
|
||||
"dfs-bfs"
|
||||
"checks"
|
||||
"gauss-imp"
|
||||
"gauss-fn"
|
||||
"Cannibals-sba"
|
||||
"mst"
|
||||
;;"gab-boyer"
|
||||
;;"nucleic" -- internal defines, etc
|
||||
;;"nucleic2" -- internal defines, etc
|
||||
;;"slatex" -- too large
|
||||
))
|
||||
|
||||
(map (lambda (x) (string-append "~/Spidey/wright/" x ".scm"))
|
||||
'(
|
||||
"boyer"
|
||||
"browse"
|
||||
"check"
|
||||
"nbody"
|
||||
"graphs1"
|
||||
"graphs2"
|
||||
"lattice-cormac"
|
||||
;;"dynamic"
|
||||
))))
|
||||
|
||||
(define test-files
|
||||
(append
|
||||
(list "~/Spidey/test/sum.ss")
|
||||
(list "~/Spidey/test-suite/testall.ss")
|
||||
;; Can't use testnumeric as general test
|
||||
;; type annotations require accurate numeric constants
|
||||
;; (list "~/Spidey/test-suite/testnumeric.ss")
|
||||
(map (lambda (x) (string-append "~/Spidey/test/" x ".ss"))
|
||||
'(
|
||||
"defstruct"
|
||||
"defstruct2"))
|
||||
benchmark-files))
|
||||
|
||||
'(define test-files
|
||||
'("~/Spidey/test/one.ss"
|
||||
"~/Spidey/test/sum.ss"
|
||||
"~/Spidey/sba/testall.ss"
|
||||
"~/Spidey/test/du.ss"))
|
||||
|
||||
|
||||
;(define test-files '("test/one.ss" "test/test.ss" "test/readlot.ss"))
|
||||
|
||||
;; ======================================================================
|
||||
;; Helper functions
|
||||
|
||||
(define (exec-mzscheme exps)
|
||||
(recur loop ( [s "mzscheme -x -g -a -f /home/cormac/scheme/mzschemerc.ss"]
|
||||
[exps exps])
|
||||
(if (null? exps)
|
||||
(begin
|
||||
(printf "Command: ") (display s) (newline)
|
||||
(system s))
|
||||
(loop
|
||||
(string-append s (format " -e '~s'" (car exps)))
|
||||
(cdr exps)))))
|
||||
|
||||
(define (for-each-parameter para thunk)
|
||||
(for-each
|
||||
(lambda (p) (dynamic-let ([para p]) (thunk p)))
|
||||
(map car (para '?))))
|
||||
|
||||
(define (for-each-parameters para-list thunk)
|
||||
(if (null? para-list)
|
||||
(thunk)
|
||||
(for-each-parameter
|
||||
(car para-list)
|
||||
(lambda (x)
|
||||
(for-each-parameters (cdr para-list) thunk)))))
|
||||
|
||||
(define (for-each-quoted-parameters para-list thunk)
|
||||
(recur loop ([l para-list][d '()])
|
||||
(match l
|
||||
[()
|
||||
(printf "CONFIGURATION: ~s~n" d)
|
||||
(thunk)]
|
||||
[(p . rest)
|
||||
(for-each-parameter
|
||||
(eval p)
|
||||
(lambda (x) (loop (cdr l) (cons `(,p ,x) d))))])))
|
||||
|
||||
(define (smart-for-each-quoted-parameters para-list limit thunk)
|
||||
(for num-chgs 0 (add1 (min limit (length para-list)))
|
||||
;; Try changing num-chgs parameters
|
||||
(recur loop ([l para-list][d '()][n num-chgs])
|
||||
(match l
|
||||
[()
|
||||
(when (zero? n)
|
||||
;; run the test
|
||||
(printf "CONFIGURATION: num-chgs=~s ~s~n" num-chgs d)
|
||||
(thunk))]
|
||||
[(p . rest)
|
||||
(let* ([para (eval p)]
|
||||
[options (map car (para '?))]
|
||||
[default (car options)])
|
||||
;; --- First don't change
|
||||
(dynamic-let
|
||||
([para default])
|
||||
(loop rest (cons `(,p ,default) d) n))
|
||||
;; Now change
|
||||
(unless (zero? n)
|
||||
(for-each
|
||||
(lambda (v)
|
||||
(dynamic-let
|
||||
([para v])
|
||||
(loop rest (cons `(,p ,v) d) (sub1 n))))
|
||||
(cdr options))))]))))
|
||||
|
||||
(define (for-every-nth f l n)
|
||||
(recur loop ([i (random (inexact->exact n))][l l])
|
||||
(unless (null? l)
|
||||
(if (zero? i)
|
||||
(begin
|
||||
(f (car l))
|
||||
(loop n (cdr l)))
|
||||
(loop (sub1 i) (cdr l))))))
|
||||
|
||||
; ======================================================================
|
||||
; Check minimization algorithms preserve meaning
|
||||
|
||||
(define min-algs-to-check
|
||||
'( none
|
||||
nonempty
|
||||
nonempty-copy
|
||||
live
|
||||
live-few-e
|
||||
;live-few-e-L
|
||||
;live-few-e-U
|
||||
;(live-few-e dfa-min)
|
||||
;(live-few-e dfa-min-inv)
|
||||
;(live-few-e dfa-min-inv dfa-min)
|
||||
;(live-few-e dfa-min dfa-min-inv)
|
||||
|
||||
;(live-few-e dfa-min-1)
|
||||
;(live-few-e dfa-min-1)
|
||||
;(live-few-e dfa-min-2)
|
||||
;(live-few-e dfa-min-2)
|
||||
;(live-few-e dfa-min-1 live dfa-min-2)
|
||||
;(live-few-e dfa-min-2 live dfa-min-1)
|
||||
|
||||
(dfa-min-lub)
|
||||
(dfa-min-glb)
|
||||
(dfa-min-lub dfa-min-glb)
|
||||
(dfa-min-glb dfa-min-lub)
|
||||
|
||||
;(live-few-e min-table)
|
||||
))
|
||||
|
||||
(define (check-min-ok-file file)
|
||||
(let*
|
||||
( [defs (analyze-program file)]
|
||||
[type-annotations (calc-type-annotations defs)]
|
||||
[tvar* (filter Tvar? (map type-annotation-FlowType type-annotations))]
|
||||
;;[_ (pretty-print `(Tvar* ,(map Tvar-name tvar*)))]
|
||||
[min-algs min-algs-to-check]
|
||||
[p (make-parameter-list
|
||||
(car min-algs)
|
||||
(map (lambda (x) (list x "")) min-algs))]
|
||||
[min-con-1
|
||||
(lambda (which Tvar)
|
||||
(let*-vals
|
||||
([(_ Tvar->nutvar)
|
||||
(minimize-constraints which '() (list Tvar) '() '())])
|
||||
(Tvar->nutvar Tvar)))])
|
||||
|
||||
(printf "Testing ~s, ~s Tvar~n" file (length tvar*))
|
||||
;; Compression algorithms don't preserve filters,
|
||||
;; so turn all filters into edges
|
||||
(for-each
|
||||
(lambda (tvar)
|
||||
(when (Tvar? tvar)
|
||||
(set-Tvar-constraints!
|
||||
tvar
|
||||
(filter
|
||||
(match-lambda
|
||||
[($ con) #t]
|
||||
[($ con-filter _ _ to)
|
||||
(new-edge! tvar to)
|
||||
#f])
|
||||
(Tvar-constraints tvar)))))
|
||||
list-ftype)
|
||||
|
||||
(for-each-parameter
|
||||
p
|
||||
(lambda (v)
|
||||
(printf "Minimization strategy ~s~n" v)
|
||||
(for-each
|
||||
(lambda (Tvar)
|
||||
(printf ".") (flush-output)
|
||||
(let* ( [live-copy (min-con-1 'none Tvar)]
|
||||
[p-copy (min-con-1 (p) Tvar)])
|
||||
(Tvar-equiv?
|
||||
(lambda ()
|
||||
(printf "Original is:~n")
|
||||
(pretty-print (Tvar-name Tvar)))
|
||||
"Live copy" live-copy
|
||||
(format "~s p-copy" (p)) p-copy)))
|
||||
tvar*)
|
||||
(newline)))))
|
||||
|
||||
(define (Tvar-equiv? fail-thunk name-A A name-B B)
|
||||
(let* ( [c1 (Tvar-containment? A B)]
|
||||
[c2 (Tvar-containment? B A)])
|
||||
(unless (and c1 c2)
|
||||
(fail-thunk)
|
||||
(printf "~a is:~n" name-A)
|
||||
(pretty-print (Tvar-name A))
|
||||
(printf "~a is:~n" name-B)
|
||||
(pretty-print (Tvar-name B))
|
||||
(if c1
|
||||
(printf "~s is larger!~n" name-B)
|
||||
(printf "~s is smaller!~n" name-B))
|
||||
(error 'Tvar-equiv? "Failure!"))))
|
||||
|
||||
(define (check-min-ok-all)
|
||||
(for-each check-min-ok-file benchmark-files))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (check-type-file f)
|
||||
(printf "==================================================~n")
|
||||
(printf "File: ~s~n" f)
|
||||
(st: f)
|
||||
(pretty-print (st:type)))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define (check-SDL-file f)
|
||||
(printf "==================================================~n")
|
||||
(printf "File: ~s~n" f)
|
||||
(st: f)
|
||||
(let* ([l list-ftype])
|
||||
(for-each-parameter
|
||||
st:type-compression
|
||||
(lambda (t)
|
||||
(printf "----------------------------------------~n")
|
||||
(printf "Type compression: ~s~n" t)
|
||||
(for-each
|
||||
(lambda (Tvar)
|
||||
(when (Tvar? Tvar)
|
||||
(printf "~s~n" (Tvar-name Tvar))
|
||||
(flush-output)
|
||||
(let ([sdl (Tvar->SDL Tvar)])
|
||||
(void))))
|
||||
l)))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (check-SDL2-file f)
|
||||
(printf "==================================================~n")
|
||||
(printf "File: ~s~n" f)
|
||||
(st: f)
|
||||
(let* ([l list-ftype]
|
||||
[len (length l)])
|
||||
(smart-for-each-quoted-parameters
|
||||
'(st:type-compression
|
||||
st:primitive-types
|
||||
st:naming-strategy )
|
||||
2
|
||||
(lambda ()
|
||||
(for-every-nth
|
||||
(lambda (Tvar)
|
||||
(when (Tvar? Tvar)
|
||||
(printf "~s " (FlowType-num Tvar))
|
||||
(flush-output)
|
||||
(let ([sdl (Tvar->SDL Tvar)])
|
||||
(void))))
|
||||
l
|
||||
;; do (* 3 (sqrt len)) cases
|
||||
(truncate (/ len (* 3 (sqrt len)))))
|
||||
(newline)))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
|
||||
;; ### DOESNT WORK CAUSE LISTIFY ETC
|
||||
(define (check-SDL3-file f)
|
||||
(printf "==================================================~n")
|
||||
(printf "File: ~s~n" f)
|
||||
(st: f)
|
||||
(let* ([l list-ftype]
|
||||
[len (length l)])
|
||||
(dynamic-let ([st:primitive-types 'inferred])
|
||||
(smart-for-each-quoted-parameters
|
||||
'(st:type-compression
|
||||
st:naming-strategy )
|
||||
1
|
||||
(lambda ()
|
||||
(for-every-nth
|
||||
(lambda (Tvar)
|
||||
(when (Tvar? Tvar)
|
||||
(printf "~s " (FlowType-num Tvar))
|
||||
(flush-output)
|
||||
(let*-vals
|
||||
(;; minimize w/ live
|
||||
[(_ Tvar->nutvar)
|
||||
(minimize-constraints 'live '() (list Tvar))]
|
||||
[tvar-live (Tvar->nutvar Tvar)]
|
||||
[sdl (dynamic-let
|
||||
([st:listify-etc #f])
|
||||
(Tvar->SDL tvar-live))]
|
||||
[tvar2 (mk-Tvar 'check-SDL3)])
|
||||
(pretty-print sdl)
|
||||
(tschema->con
|
||||
(expand-input-type sdl)
|
||||
tvar2 'check-SDL3: '())
|
||||
(Tvar-equiv?
|
||||
(lambda ()
|
||||
(pretty-print
|
||||
`( st:type-compression ,(st:type-compression)
|
||||
st:naming-strategy ,(st:naming-strategy)
|
||||
sdl ,sdl)))
|
||||
"Live" tvar-live
|
||||
"Regenerated" tvar2))))
|
||||
l
|
||||
;; do (* 3 (sqrt len)) cases
|
||||
(truncate (/ len (* 3 (sqrt len)))))
|
||||
(newline))))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (acid-test-analysis sub-test)
|
||||
(lambda (f)
|
||||
(smart-for-each-quoted-parameters
|
||||
'(st:constants
|
||||
st:if-split
|
||||
st:flow-sensitive
|
||||
st:numops
|
||||
st:special-fo-prims
|
||||
;;st:system-expand
|
||||
st:see-void)
|
||||
3
|
||||
(lambda () (sub-test f)))))
|
||||
|
||||
(define (acid-acid-test-analysis f)
|
||||
((acid-test-analysis acid-test-SDL) f))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (all-test-sba-terminates)
|
||||
(for-each acid-test-SDL test-files)
|
||||
(for-each acid-acid-test-analysis test-files))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define compare-min-file-results (void))
|
||||
(define (compare-min-file file)
|
||||
(set! compare-min-file-results '())
|
||||
(for-each-parameter
|
||||
st:unit-simplify
|
||||
(lambda (p)
|
||||
(unless (eq? p 'none)
|
||||
(pretty-print `(st:unit-simplify ,p))
|
||||
(let*-vals
|
||||
( [(_ t real-t) (time-apply (lambda () (st: file)))])
|
||||
(set! compare-min-file-results
|
||||
(cons (list p t) compare-min-file-results))
|
||||
(pretty-print
|
||||
`(compare-min-file-results ,compare-min-file-results))))))
|
||||
compare-min-file-results)
|
||||
|
||||
;; ======================================================================
|
||||
;; EXPERIMENT A
|
||||
;;
|
||||
;; Figure describing Behavior of Constraint Compression Algorithms
|
||||
|
||||
(define compress-files
|
||||
(map (lambda (x) (string-append "~/papers/compress/bench/compress/" x ".ss"))
|
||||
'(
|
||||
"t"
|
||||
"map"
|
||||
"reverse2"
|
||||
"substring"
|
||||
"qsortmod"
|
||||
"unify"
|
||||
"hopcroft"
|
||||
"check-mod"
|
||||
"escher"
|
||||
"scanner"
|
||||
)))
|
||||
|
||||
(define (fig6-file file)
|
||||
(dynamic-let ( [st:compare-min-algs #t]
|
||||
[st:unit-read-za #f]
|
||||
[st:unit-write-za #f]
|
||||
[st:use-fo-ftype #f]
|
||||
[st:polymorphism 'compress]
|
||||
[st:if-split #f]
|
||||
[st:flow-sensitive #f]
|
||||
[st:unit-separate-S #f]
|
||||
)
|
||||
(st:analyze file)))
|
||||
|
||||
(define (fig6)
|
||||
(for-each fig6-file compress-files))
|
||||
|
||||
;; ======================================================================
|
||||
;; EXPERIMENT B
|
||||
;;
|
||||
;; Polymorphic analysis times
|
||||
|
||||
(define wright-files
|
||||
(map (lambda (x) (string-append "~/papers/compress/bench/poly/" x ".ss"))
|
||||
'(
|
||||
"t"
|
||||
"lattice"
|
||||
"browse"
|
||||
"splay"
|
||||
"check"
|
||||
"graphs"
|
||||
"boyer"
|
||||
"matrix"
|
||||
"maze"
|
||||
"nbody"
|
||||
"nucleic-3"
|
||||
;; "dynamic"
|
||||
|
||||
)))
|
||||
|
||||
;(define wright-poly-files
|
||||
; (map (lambda (file) (regexp-replace ".ss$" file ".poly.ss"))
|
||||
; wright-files))
|
||||
|
||||
(define fig7-algs
|
||||
'( (traverse none)
|
||||
(none none)
|
||||
(compress (dfa-min-lub))
|
||||
(compress (dfa-min-glb))
|
||||
(compress live-few-e)
|
||||
(compress live)
|
||||
(compress nonempty)
|
||||
(compress none)
|
||||
;;(copy-con none)
|
||||
(reanalyze none)))
|
||||
|
||||
(define (fig7-file-alg a b file)
|
||||
(dynamic-let ( [st:polymorphism (if (eq? a 'traverse) 'none a)]
|
||||
[st:type-compression-poly b]
|
||||
[st:use-fo-ftype #f]
|
||||
[st:if-split #f]
|
||||
[st:flow-sensitive #f]
|
||||
[keep-S-closed (if (eq? a 'traverse) #f (keep-S-closed))])
|
||||
(printf "--------------------------------------------------------~n")
|
||||
(printf "FILE: ~s ANALYSIS ~s~n" file (list a b))
|
||||
(clear-counters!)
|
||||
(set! need-label-types #t)
|
||||
(st: file)
|
||||
(printf "FILE: ~s ANALYSIS ~s~n" file (list a b))
|
||||
(show-counters)
|
||||
(show-stat-small)
|
||||
(list a b (get-counter 'top-level-traverse-defs))))
|
||||
|
||||
(define (fig7-file file)
|
||||
(let* ( [file (topo-file file)]
|
||||
[r (map
|
||||
(match-lambda [(a b) (fig7-file-alg a b file)])
|
||||
fig7-algs)])
|
||||
(pretty-print `(RESULTS-FOR ,file ,r))
|
||||
(list file r)))
|
||||
|
||||
(define (fig7)
|
||||
(recur loop ([files wright-files][r* '()])
|
||||
(unless (null? files)
|
||||
(let* ( [r (fig7-file (car files))]
|
||||
[r* (append r* (list r))])
|
||||
(pretty-print `(RESULTS-TO-DATE ,r*))
|
||||
(loop (cdr files) r*)))))
|
||||
|
||||
(define (fig7s-file file)
|
||||
;; Spawns nu mzscheme each time
|
||||
(let* ( [file (topo-file file)])
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and analyze (a b))
|
||||
(printf "--------------------------------------------------------~n")
|
||||
(printf "FILE: ~s ANALYSIS ~s~n" file analyze)
|
||||
(exec-mzscheme
|
||||
`( (define __NO_DEBUGGING 1)
|
||||
(ST)
|
||||
(set! mrspidey:zprogress (lambda x 1))
|
||||
(fig7-file-alg (quote ,a) (quote ,b) ,file)
|
||||
(exit)))])
|
||||
fig7-algs)))
|
||||
|
||||
(define (fig7s)
|
||||
(for-each fig7s-file (cdr wright-files)))
|
||||
|
||||
;; ======================================================================
|
||||
;; EXPERIMENT C
|
||||
;; Test how analysis scales to large programs
|
||||
;; Have:
|
||||
;; analyze-scanner.ss
|
||||
;; analyze-zodiac.ss
|
||||
;; analyze-small.ss - part of sba analysis
|
||||
;; analyze-no-min.ss - sba except minimization
|
||||
;; analyze.ss - all of sba
|
||||
;;
|
||||
;; analyze-CDL.ss - usless, units never used
|
||||
;; analyze-min.ss - useless, units never used
|
||||
|
||||
(define (test-scalable-alg alg file)
|
||||
(printf "--------------------------------------------------------~n")
|
||||
(printf "FILE: ~s SIMPLIFICATION ~s~n" file alg)
|
||||
(dynamic-let ( [st:unit-simplify (if (eq? alg 'traverse) 'none alg)]
|
||||
[st:use-fo-ftype #f]
|
||||
[st:if-split #f]
|
||||
[st:flow-sensitive #f]
|
||||
[keep-S-closed (if (eq? alg 'traverse) #f (keep-S-closed))]
|
||||
[st:unit-read-za #f]
|
||||
[st:unit-write-za #f]
|
||||
[st:unit-separate-S #t])
|
||||
(clear-counters!)
|
||||
(st:analyze file)
|
||||
(printf "FILE: ~s SIMPLIFICATION ~s~n" file alg)
|
||||
(show-counters)
|
||||
(pretty-print (st:control))
|
||||
(show-stat-small)))
|
||||
|
||||
(define (bad-alg-for-file? alg file)
|
||||
(cond
|
||||
[(equal? file "analyze-small.ss")
|
||||
;; none ran to 404M
|
||||
(memq alg '(none nonempty))]
|
||||
[(equal? file "analyze-no-min.ss")
|
||||
(memq alg '(none nonempty))]
|
||||
[(equal? file "analyze.ss")
|
||||
(memq alg '(none nonempty nonempty-copy))]
|
||||
[(equal? file "~/papers/compress/bench/separate/nucleic/nucleic.ss")
|
||||
(memq alg '())]
|
||||
[else #f]))
|
||||
|
||||
(define (test-scalable-file file)
|
||||
(for-each
|
||||
(lambda (t)
|
||||
(unless (bad-alg-for-file? t file)
|
||||
(exec-mzscheme
|
||||
`( (define __NO_DEBUGGING 1)
|
||||
(ST)
|
||||
;;(expander-eval (quote (defmacro cache-exp (exp za) exp)))
|
||||
;;(expander-eval (quote (defmacro cache-inv (exp za) exp)))
|
||||
(set! mrspidey:zprogress (lambda x 1))
|
||||
(test-scalable-alg (quote ,t) ,file)
|
||||
(exit)))))
|
||||
'(traverse none nonempty live live-few-e dfa-min-lub dfa-min-glb)))
|
||||
|
||||
(define (test-scalable-all)
|
||||
(for-each test-scalable-file
|
||||
'( "analyze-scanner.ss"
|
||||
"analyze-zodiac.ss"
|
||||
"analyze-small.ss"
|
||||
"analyze-no-min.ss"
|
||||
"analyze.ss")))
|
||||
|
||||
;; ======================================================================
|
||||
;; EXPERIMENT D
|
||||
;; Test separate analysis
|
||||
|
||||
(define (test-separate-analyze alg read-za file)
|
||||
(printf "--------------------------------------------------------~n")
|
||||
(printf "FILE: ~s SIMPLIFICATION ~s ~s~n" file alg read-za)
|
||||
(let ([files '()])
|
||||
(dynamic-let
|
||||
( [st:unit-simplify (if (eq? alg 'traverse) 'none alg)]
|
||||
[st:use-fo-ftype #f]
|
||||
[st:if-split #f]
|
||||
[st:flow-sensitive #f]
|
||||
[keep-S-closed (if (eq? alg 'traverse) #f (keep-S-closed))]
|
||||
[st:unit-separate-S #t]
|
||||
[st:unit-read-za read-za]
|
||||
[st:unit-write-za #t]
|
||||
[st:unit-separate-S #t]
|
||||
[record-analyzed-file-hook
|
||||
(lambda (filename . _)
|
||||
(printf "Record-analyzed-file ~s~n" filename)
|
||||
(set! files (cons filename files)))])
|
||||
(clear-counters!)
|
||||
(st:analyze file)
|
||||
(printf "FILE: ~s SIMPLIFICATION ~s ~s~n" file alg read-za)
|
||||
(show-counters)
|
||||
(pretty-print (st:control))
|
||||
(show-stat-small)
|
||||
(printf "ZA FILES:~n")
|
||||
(system
|
||||
(foldr
|
||||
(lambda (file acc)
|
||||
(string-append acc " " (regexp-replace "-source$" file "")))
|
||||
"wc "
|
||||
files)))))
|
||||
|
||||
(define (test-separate-alg alg file module-file)
|
||||
(assert (file-exists? module-file))
|
||||
(exec-mzscheme
|
||||
`( (define __NO_DEBUGGING 1)
|
||||
(ST)
|
||||
;(set! mrspidey:zprogress (lambda x 1))
|
||||
(test-separate-analyze (quote ,alg) (= 0 1) ,file)
|
||||
(exit)))
|
||||
(system (format "touch ~a" module-file))
|
||||
(exec-mzscheme
|
||||
`( (define __NO_DEBUGGING 1)
|
||||
(ST)
|
||||
;(set! mrspidey:zprogress (lambda x 1))
|
||||
(test-separate-analyze (quote ,alg) (= 1 1) ,file)
|
||||
(exit))))
|
||||
|
||||
(define (test-separate-file file module-file)
|
||||
(for-each
|
||||
(lambda (t)
|
||||
(unless (bad-alg-for-file? t file)
|
||||
(test-separate-alg t file module-file)))
|
||||
'(none nonempty-copy live live-few-e dfa-min-lub)))
|
||||
|
||||
(define (test-separate-all)
|
||||
'(test-separate-file
|
||||
"~/Spidey/Unit/mod/test-separate.ss"
|
||||
"/home/cormac/Spidey/Unit/mod/test-separate-1.ss")
|
||||
(test-separate-file "analyze-scanner.ss" "zodiac/scanner-parameters.ss")
|
||||
(test-separate-file "analyze-zodiac.ss" "zodiac/corelate.ss")
|
||||
(test-separate-file
|
||||
"~/papers/compress/bench/separate/nucleic/nucleic.ss"
|
||||
"/home/cormac/papers/compress/bench/separate/nucleic/search.ss")
|
||||
(test-separate-file "analyze-small.ss" "hash.ss")
|
||||
(test-separate-file "analyze-no-min.ss" "hash.ss")
|
||||
(test-separate-file "analyze.ss" "hash.ss"))
|
||||
|
||||
;; ======================================================================
|
||||
|
@ -0,0 +1,187 @@
|
||||
; testall.ss
|
||||
; Tries to test all of Teiresias's type inference algorithm
|
||||
; and uses type assertions to detect when it fails
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Constants
|
||||
|
||||
(: 1 (exact num))
|
||||
(: 'a (exact sym))
|
||||
(: #\a (exact char))
|
||||
(: #t (exact true))
|
||||
(: #f (exact false))
|
||||
(: nil (exact nil))
|
||||
(: '() (exact nil))
|
||||
(: "Cormac" (exact str))
|
||||
(: '(a b c) (exact (listof sym)))
|
||||
(: '(a b 1) (exact (listof (union sym num))))
|
||||
(: #(1 2 3) (exact (vec num)))
|
||||
(: #(1 2 "abc") (exact (vec (union num str))))
|
||||
;;;(: #&4 (exact (box num)))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; misc kinds of exprs
|
||||
|
||||
; top-level def
|
||||
(define x 'a-symbol)
|
||||
(: x (exact sym))
|
||||
|
||||
|
||||
; lexical binding -various sorts
|
||||
(let ([y 4][z 'a])
|
||||
(: y (exact num))
|
||||
(: z (exact sym)))
|
||||
(letrec ([y 4][z 'a])
|
||||
(: y (exact num))
|
||||
(: z (exact sym)))
|
||||
(let* ([y 4][z 'a])
|
||||
(: y (exact num))
|
||||
(: z (exact sym)))
|
||||
|
||||
; if - one and two armed
|
||||
(: (if (read) 1 'a) (exact (union num sym)))
|
||||
(: (if (read) 1) (exact (union num void)))
|
||||
|
||||
; set!
|
||||
(let ([z 4])
|
||||
(set! z 'a)
|
||||
(: z (exact (union num sym))))
|
||||
|
||||
; begin
|
||||
(: (begin 'a 1) (exact num))
|
||||
|
||||
; now various lambdas and applications
|
||||
((lambda (x y) (: x (exact num)) (: y (exact sym)))
|
||||
4 'a)
|
||||
((lambda x (: x (exact (cons num (cons num nil))))) 1 2)
|
||||
(apply (lambda (x) (: x (exact num))) (list 1))
|
||||
(apply (lambda x (: x (exact (cons num (cons num nil))))) (cons 1 (cons 2 nil)))
|
||||
(: (lambda (x) x) (_ -> _))
|
||||
(: ((lambda (x) 'a) 3) (exact sym))
|
||||
|
||||
;; Multiple calls, merged returns
|
||||
(let ([I (lambda (x) (: x (exact (union num sym))))])
|
||||
(: (I 3) (exact (union num sym)))
|
||||
(: (I 'a) (exact (union num sym))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; if-splitting
|
||||
|
||||
; (if (pred arg) ...)
|
||||
(let ([x (if (read) 1 'a)])
|
||||
(: x (exact (union num sym)))
|
||||
(if (number? x)
|
||||
(: x (exact num))
|
||||
(: x (exact sym))))
|
||||
|
||||
; assigned arg
|
||||
(let ([x (if (read) 1 'a)])
|
||||
(set! x 2)
|
||||
(if (number? x)
|
||||
(: x (exact (union num sym)))
|
||||
(: x (exact (union num sym)))))
|
||||
|
||||
; (if x ...)
|
||||
(let ([x (if (read) #t #f)])
|
||||
(if x
|
||||
(: x (exact true))
|
||||
(: x (exact false))))
|
||||
(let ([x (if (read) 5 #f)])
|
||||
(if x
|
||||
(: x (exact num))
|
||||
(: x (exact false))))
|
||||
|
||||
; (if (not x) ...)
|
||||
(let ([x (if (read) #t #f)])
|
||||
(if (not x)
|
||||
(: x (exact false))
|
||||
(: x (exact true))))
|
||||
(let ([x (if (read) 5 #f)])
|
||||
(if (not x)
|
||||
(: x (exact false))
|
||||
(: x (exact num))))
|
||||
|
||||
; (if (not (pred arg)) ...)
|
||||
(let ([x (if (read) 1 'a)])
|
||||
(if (not (number? x))
|
||||
(: x (exact sym))
|
||||
(: x (exact num))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Flow sensitive
|
||||
|
||||
(let ([x (if 1 (cons 1 2) 'a)])
|
||||
(: x (exact (union (cons num num) sym)))
|
||||
(car x)
|
||||
(: x (exact (cons num num)))
|
||||
(cdr x))
|
||||
|
||||
; not on assigned vars
|
||||
(let ([x (if (read) (cons 1 2) 'a)])
|
||||
(set! x 'b)
|
||||
(: x (exact (union (cons num num) sym)))
|
||||
(car x)
|
||||
(: x (exact (union (cons num num) sym)))
|
||||
(cdr x))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Boxes
|
||||
|
||||
(let ([x (: (box 1) (exact (box num)))])
|
||||
(: (unbox x) (exact num)))
|
||||
(let ([x (: (box 1) (exact (box (union num sym))))])
|
||||
(set-box! x 'a)
|
||||
(: (unbox x) (exact (union num sym))))
|
||||
(let ([x (if (read) (box 'a) #f)])
|
||||
(if (box? x) (: x (exact (box sym)))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; User primitives and types
|
||||
|
||||
(define-constructor Box #t)
|
||||
|
||||
(define-primitive Box? (_ -> bool) (predicate Box))
|
||||
(define-primitive Box (a -> (Box a)))
|
||||
(define-primitive unBox ((Box a) -> a))
|
||||
(define-primitive set-Box! ((Box (! a)) a -> void))
|
||||
|
||||
(let ([x (: (Box 1) (exact (Box num)))])
|
||||
(: (unBox x) (exact num)))
|
||||
(let ([x (: (Box 1) (exact (Box (union num sym))))])
|
||||
(set-Box! x 'a)
|
||||
(: (unBox x) (exact (union num sym))))
|
||||
(let ([x (if (read) (Box 'a) #f)])
|
||||
(if (Box? x) (: x (exact (Box sym)))))
|
||||
|
||||
(define-type env (listof (list sym num)))
|
||||
(define-primitive mk-env (-> env))
|
||||
(: (mk-env) (exact (listof (list sym num))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; define-structure
|
||||
|
||||
(define-structure (Triple a b c))
|
||||
|
||||
(let ([x (: (make-Triple 1 'a #\c) (exact (structure:Triple num sym char)))])
|
||||
(: (Triple-a x) (exact num))
|
||||
(: (Triple-1 x) (exact num)))
|
||||
(let ([x (: (make-Triple 1 'a #\c) (exact (structure:Triple (union num sym) sym char)))])
|
||||
(set-Triple-a! x 'a)
|
||||
(: (Triple-a x) (exact (union num sym))))
|
||||
(let ([x (if (read) (make-Triple 1 'a #\c) #f)])
|
||||
(if (Triple? x) (: x (exact (structure:Triple num sym char)))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; loops
|
||||
|
||||
(define Map
|
||||
(lambda (f l)
|
||||
(if (null? l)
|
||||
'()
|
||||
(cons (f (car l)) (Map f (cdr l))))))
|
||||
|
||||
(: (Map add1 '(1 2 3)) (exact (listof num)))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
; Could test all the primitives ...
|
||||
|
@ -0,0 +1,60 @@
|
||||
;; text-interaction
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (mrspidey:error msg . obj-list)
|
||||
(error 'Mrspidey msg))
|
||||
(define mrspidey:warning
|
||||
(case-lambda
|
||||
[(str . _) (printf "Warning: ~a~n" str)]
|
||||
;[(str loc . _) (printf "Warning: file ~s, line ~s: ~a~n"
|
||||
; (file-name-from-path (zodiac:location-file loc))
|
||||
; (zodiac:location-line loc)
|
||||
; str)]
|
||||
))
|
||||
(define mrspidey:internal-error error)
|
||||
(define (mrspidey:add-summary str . _)
|
||||
(printf "~a~n" str))
|
||||
(define mrspidey:progress
|
||||
(let ([current ()]
|
||||
[fresh-line #t])
|
||||
(letrec
|
||||
([f (match-lambda*
|
||||
[((? symbol? name) (? number? fraction))
|
||||
(unless (eq? name current)
|
||||
(f 'fresh-line)
|
||||
(set! current name)
|
||||
(mrspidey:progress-output (format "~s: " name)))
|
||||
(mrspidey:progress-output ".")
|
||||
(flush-output)
|
||||
(set! fresh-line #f)
|
||||
(when (= fraction 1) (f #\newline))]
|
||||
[((? string? str))
|
||||
(f 'fresh-line)
|
||||
(mrspidey:progress-output str)
|
||||
(when (char=? (string-ref str (sub1 (string-length str)))
|
||||
#\newline)
|
||||
(set! fresh-line #t))]
|
||||
[(#\newline)
|
||||
(mrspidey:progress-output (format "~n"))
|
||||
(set! fresh-line #t)]
|
||||
[('fresh-line)
|
||||
(unless fresh-line (f #\newline))])])
|
||||
f)))
|
||||
(define mrspidey:progress-output
|
||||
(lambda (str) (display str) (flush-output)))
|
@ -0,0 +1,212 @@
|
||||
;; toplevelenv.ss
|
||||
;; Handles the default top level environment
|
||||
;;
|
||||
;; ======================================================================
|
||||
;; Primitive environments: symbol -> priminfo
|
||||
;; First a helper fn
|
||||
|
||||
(define-structure (priminfo sym type domain-filters predicate-fn))
|
||||
|
||||
;; filter-domains is a list of filters for various args,
|
||||
;; if no error raised
|
||||
|
||||
;; inj-predicate is a fn : list-AVS x list-AVS x AVS x bool -> AVS
|
||||
;; used for (if (pred ... x ...) ...)
|
||||
|
||||
(define (primitive->priminfo name type . attrs)
|
||||
(let ([type (expand-type type)])
|
||||
(make-priminfo
|
||||
name
|
||||
type
|
||||
|
||||
;; Calculate filter-domains
|
||||
(match type
|
||||
[(domain '->* _)
|
||||
;; Now walk domain and args
|
||||
(recur loop ([domain domain])
|
||||
(match domain
|
||||
[('cons domain domain-rest)
|
||||
(cons
|
||||
(let ([templates (con-exp->templates domain)])
|
||||
(if templates
|
||||
(make-filter #t templates)
|
||||
#f))
|
||||
(loop domain-rest))]
|
||||
[_ '()]))]
|
||||
[_ '()])
|
||||
|
||||
;; Calculate predicate-fn
|
||||
(foldl
|
||||
(lambda (attr predicate-fn)
|
||||
(let*
|
||||
([mk-predicate-fn
|
||||
(lambda (filter-then filter-else)
|
||||
(lambda (b a AVS sign)
|
||||
(let ([filter (if sign filter-then filter-else)])
|
||||
(if filter
|
||||
(let ([nu-AVS (mk-AVS-tmp 'filter)])
|
||||
(new-con! AVS
|
||||
(create-con-filter filter
|
||||
nu-AVS))
|
||||
nu-AVS)
|
||||
AVS))))]
|
||||
[get-templates
|
||||
(lambda (C*) (map lookup-template C*))]
|
||||
[nu-fn
|
||||
(match attr
|
||||
[('predicate-fn exp) exp]
|
||||
[('predicate . C*)
|
||||
(let ([templates (get-templates C*)])
|
||||
(mk-predicate-fn (make-filter #t templates)
|
||||
(make-filter #f templates)))]
|
||||
[('predicate* true-info false-info)
|
||||
(apply
|
||||
mk-predicate-fn
|
||||
(map
|
||||
(match-lambda
|
||||
['_ #f]
|
||||
[(bool . C*)
|
||||
(let ([templates (get-templates C*)])
|
||||
(make-filter bool templates))]
|
||||
[_ (error 'predicate* "Bad syntax")])
|
||||
(list true-info false-info)))]
|
||||
[_ #f])])
|
||||
(if nu-fn
|
||||
;; compose
|
||||
(lambda (b a AVS sign)
|
||||
(nu-fn b a
|
||||
(predicate-fn b a AVS sign)
|
||||
sign))
|
||||
predicate-fn)))
|
||||
(lambda (b a AVS bool) AVS)
|
||||
attrs))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Now the default environment
|
||||
|
||||
(define default-primitive-env (void))
|
||||
;; type: symbol -> priminfo
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define output-type-expander (void))
|
||||
(define (init-output-type-expander!)
|
||||
(set! output-type-expander (lambda (x) x)))
|
||||
|
||||
(define (install-output-type-expander! expander)
|
||||
(let ([old-expander output-type-expander])
|
||||
(set! output-type-expander
|
||||
(lambda (type)
|
||||
(old-expander (recur loop ([type type])
|
||||
(let ([t (expander type)])
|
||||
(if (eq? t type) type (loop t)))))))))
|
||||
|
||||
;; ======================================================================
|
||||
;; For input-type-expander, recursion is done in expand-type
|
||||
|
||||
(define default-input-type-expander (void))
|
||||
(define input-type-expander (void))
|
||||
|
||||
(define (init-input-type-expander!)
|
||||
(set! input-type-expander default-input-type-expander))
|
||||
|
||||
(define (init-empty-input-type-expander!)
|
||||
(set! input-type-expander (lambda (x) x)))
|
||||
|
||||
(define (capture-input-type-expander!)
|
||||
(set! default-input-type-expander input-type-expander))
|
||||
|
||||
(define (install-input-type-expander! expander)
|
||||
(let ([old-expander input-type-expander])
|
||||
(set! input-type-expander
|
||||
(lambda (type)
|
||||
;;(pretty-print `(input-type-expander ,type))
|
||||
(old-expander (expander type))))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (extend-env-w/-define-structure env tag . args)
|
||||
;; env: sym -> priminfo
|
||||
(let ([add!
|
||||
(lambda (name type . attrs)
|
||||
(set! env
|
||||
(extend-env env name
|
||||
(apply primitive->priminfo name type attrs))))]
|
||||
[type (symbol-append 'structure: tag)]
|
||||
[gen-args (map (lambda (_) (gensym)) args)]
|
||||
[gen-arg (gensym)])
|
||||
(apply add-constructor! type (map (lambda (a) #t) args))
|
||||
(add! (symbol-append 'make- tag) `(,@gen-args -> (,type ,@gen-args)))
|
||||
(add! (symbol-append tag '?) `(_ -> bool) `(predicate ,type))
|
||||
(for-each-with-n
|
||||
(lambda (arg n)
|
||||
(let ([type-ref
|
||||
`((,type ,@(map (lambda (a)
|
||||
(if (eq? a arg) gen-arg '_))
|
||||
args))
|
||||
-> ,gen-arg)]
|
||||
[type-bang
|
||||
`((,type ,@(map (lambda (a)
|
||||
(if (eq? a arg) `(! ,gen-arg) '_))
|
||||
args))
|
||||
,gen-arg
|
||||
-> void)])
|
||||
(add! (symbol-append tag '- arg) type-ref)
|
||||
(add! (symbol-append tag '- (add1 n)) type-ref)
|
||||
(add! (symbol-append 'set- tag '- arg '!) type-bang)
|
||||
(add! (symbol-append 'set- tag '- (add1 n) '!) type-bang)))
|
||||
args)
|
||||
env))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (add-default-primitive! name type . attrs)
|
||||
;; working w/ default primitive env => use default constructor env
|
||||
(init-current-constructor-env!)
|
||||
(set! default-primitive-env
|
||||
(extend-env default-primitive-env
|
||||
name
|
||||
(apply primitive->priminfo name type attrs))))
|
||||
|
||||
(define (add-default-primitives! l)
|
||||
(for-each
|
||||
(lambda (args) (apply add-default-primitive! args))
|
||||
l))
|
||||
|
||||
(define
|
||||
select-language
|
||||
(make-parameter-list
|
||||
'none
|
||||
'((DrScheme "DrScheme")
|
||||
(MzScheme "MzScheme")
|
||||
(R4RS "R4RS")
|
||||
(Chez "Chez Scheme")
|
||||
(Rice "Rice Scheme")
|
||||
(none "None"))
|
||||
(lambda (scheme)
|
||||
(unless (eq? scheme 'none)
|
||||
(init-default-constructor-env!)
|
||||
(init-empty-input-type-expander!)
|
||||
(init-output-type-expander!)
|
||||
(set! default-primitive-env empty-env)
|
||||
(init-R4RS!)
|
||||
(case scheme
|
||||
[MzScheme (init-MzScheme-on-R4RS!)]
|
||||
[DrScheme (init-MzScheme-on-R4RS!)
|
||||
(init-DrScheme-on-MzScheme!)]
|
||||
[R4RS (void)]
|
||||
[Chez (init-Chez-on-R4RS!)]
|
||||
[Rice (init-Chez-on-R4RS!)
|
||||
(init-Rice-on-Chez!)]
|
||||
[none (void)])
|
||||
(when (st:numops) (init-smart-numops!))
|
||||
;; Load .spideyrc file and .spidey-system-rc files
|
||||
(when (file-exists? "~/.spideyrc") (load "~/.spideyrc"))
|
||||
(let ([systemrc (string-append "~/.spidey-"
|
||||
(symbol->string scheme)
|
||||
"-rc")])
|
||||
(when (file-exists? systemrc) (load systemrc)))
|
||||
(capture-input-type-expander!)))))
|
||||
|
||||
;; ======================================================================
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,419 @@
|
||||
;; type-con.ss
|
||||
;;
|
||||
;; Parses a type to produce a set of constraints
|
||||
;; Also tests an AVS for membership in a type
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define typevar?
|
||||
(lambda (v)
|
||||
(and (symbol? v)
|
||||
(not (type-constructor? v))
|
||||
(not (memq v '(_ union rec ->*))))))
|
||||
|
||||
(define (compat-type-once type cl-fn)
|
||||
(match type
|
||||
[(and c (or (? number?) (? char?) ('quote (? symbol?)))) c]
|
||||
[('rec bind t2)
|
||||
`(rec ,(map (match-lambda [(a t) (list a (cl-fn t))]) bind)
|
||||
,(cl-fn t2))]
|
||||
[('forall vars type)
|
||||
`(forall ,vars ,(cl-fn type))]
|
||||
[('case-> . (and types (? list?) (_ . _)))
|
||||
`(case-> ,@(map cl-fn types))]
|
||||
[('union . (? list? union)) `(union ,@(map cl-fn union))]
|
||||
[(? symbol? a) a]
|
||||
[(arg '->* res) (list (cl-fn arg) '->* (cl-fn res))]
|
||||
;; check constructors
|
||||
[((? type-constructor? C) . args)
|
||||
`(,C ,@(map (match-lambda
|
||||
[('! arg) (list '! (cl-fn arg))]
|
||||
[arg (cl-fn arg)])
|
||||
args))]
|
||||
[_ #f]))
|
||||
|
||||
(define (expand-input-type type)
|
||||
;; Do rewriting transformations
|
||||
;;(pretty-print `(expand-type ,type))
|
||||
(let ([t2 (input-type-expander type)])
|
||||
(if (eq? type t2)
|
||||
(or (compat-type-once type expand-input-type)
|
||||
(mrspidey:error
|
||||
(format "Bad input type ~s" type)))
|
||||
(expand-input-type t2))))
|
||||
|
||||
(define (expand-output-type type)
|
||||
;; Do rewriting transformations
|
||||
;;(pretty-print `(expand-type ,type))
|
||||
(let* ([type (or (compat-type-once type expand-output-type)
|
||||
type
|
||||
(mrspidey:error (format "Bad output type ~s" type)))])
|
||||
(recur fn ([type type])
|
||||
(let ([t2 (output-type-expander type)])
|
||||
(if (eq? type t2)
|
||||
type
|
||||
(fn t2))))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (con-exp->templates con-exp)
|
||||
;; Assumes con-exp already expanded
|
||||
(match con-exp
|
||||
[('union . E*)
|
||||
(let ([T* (map con-exp->templates E*)])
|
||||
(and (andmap (lambda (x) x) T*)
|
||||
(apply append T*)))]
|
||||
[('forall _ type) (con-exp->templates type)]
|
||||
[(_ '->* _) (list template-lam)]
|
||||
[(or (C . _) C)
|
||||
(if (type-constructor? C)
|
||||
(list (lookup-template C))
|
||||
#f)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (generic-type->con type prefix forall-env sign)
|
||||
;; Assumes type->con is already expanded
|
||||
(letrec
|
||||
([mk-AVS-tmp (lambda () (mk-AVS (symbol-append prefix ':tc)))]
|
||||
[parse-type-generic
|
||||
(lambda (t env sign)
|
||||
;; sign is #t for +ive, #f for -ive
|
||||
(let ([new-sign-edge!
|
||||
(lambda (from to)
|
||||
(if sign
|
||||
(new-edge! from to)
|
||||
(new-edge! to from)))]
|
||||
[parse-type
|
||||
(lambda (t)
|
||||
(parse-type-generic t env sign))])
|
||||
(match t
|
||||
|
||||
;; Recursive definitions
|
||||
[('rec bind t2)
|
||||
(let* ([a* (map car bind)]
|
||||
[AVS* (map
|
||||
(lambda (a)
|
||||
(mk-AVS (symbol-append prefix ': a)))
|
||||
a*)]
|
||||
[env (extend-env* env a* AVS*)])
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(a t)
|
||||
(new-sign-edge! (parse-type-generic t env sign)
|
||||
(lookup env a))])
|
||||
bind)
|
||||
(parse-type-generic t2 env sign))]
|
||||
|
||||
;; Unions
|
||||
[('union . (? list? union))
|
||||
(let ([AVS (mk-AVS-tmp)])
|
||||
(for-each
|
||||
(lambda (t)
|
||||
(new-sign-edge! (parse-type-generic t env sign)
|
||||
AVS))
|
||||
union)
|
||||
AVS)]
|
||||
|
||||
;; case->
|
||||
[('case-> . (? list? types))
|
||||
(parse-type-generic (rac types) env sign)]
|
||||
|
||||
;; type variables
|
||||
['_ (mk-AVS-tmp)]
|
||||
[(? symbol? a)
|
||||
(lookup-or-fail
|
||||
env a
|
||||
(lambda ()
|
||||
(lookup-or-fail
|
||||
forall-env a
|
||||
(lambda ()
|
||||
;; reference type named a
|
||||
;; if sign +ive, use this type
|
||||
;; if sign -ive, return dummy AVS
|
||||
(let ([AVS (mk-AVS (symbol-append prefix ': a))])
|
||||
(set! global-in-type-env
|
||||
(cons (list a AVS (box #f)) global-in-type-env))
|
||||
(if sign
|
||||
AVS
|
||||
(mk-AVS (symbol-append prefix ': a))))))))]
|
||||
|
||||
[(arg '->* res)
|
||||
(let ([AVS (mk-AVS-tmp)])
|
||||
(if sign
|
||||
;; make the AV
|
||||
(new-AV! AVS
|
||||
(make-AV-lam
|
||||
(parse-type-generic arg env #f)
|
||||
(parse-type-generic res env #t)
|
||||
0 #t))
|
||||
;; extract the various components
|
||||
(begin
|
||||
(new-con! AVS
|
||||
(create-con
|
||||
template-lam 0
|
||||
(parse-type-generic arg env #t)))
|
||||
(new-con! AVS
|
||||
(create-con
|
||||
template-lam 1
|
||||
(parse-type-generic res env #f)))))
|
||||
AVS)]
|
||||
|
||||
;; constants
|
||||
[(or (? number? c) (? char? c) ('quote (? symbol? c)))
|
||||
(let ([AVS (mk-AVS-tmp)])
|
||||
(if sign (new-AV! AVS (traverse-const c)))
|
||||
AVS)]
|
||||
|
||||
;; check constructors
|
||||
[((? type-constructor? C) . args)
|
||||
(match-let*
|
||||
([(and template ($ template type signs ref assign))
|
||||
(lookup-template C)]
|
||||
[AVS (mk-AVS-tmp)])
|
||||
(unless (= (vector-length ref) (length args))
|
||||
(mrspidey:error
|
||||
(format "Constructor ~s given ~s arg(s), expected ~s"
|
||||
C (length args) (vector-length ref))))
|
||||
(if sign
|
||||
;; make the AV, unless void and (st:see-void) is false
|
||||
(unless (and (eq? C 'void) (not (st:see-void)))
|
||||
(new-AV!
|
||||
AVS
|
||||
(apply
|
||||
make-constructed-AV C
|
||||
(map
|
||||
(lambda (a)
|
||||
(parse-type-generic a env sign))
|
||||
args)
|
||||
;; DO SOMETHING FOR NULL ARGS
|
||||
)))
|
||||
|
||||
;; extract the various components
|
||||
;; need to do unification on mutable fields,
|
||||
;; unless pattern matching arg is (! a)
|
||||
(for-each-with-n
|
||||
(lambda (arg n)
|
||||
(match arg
|
||||
['_ (void)]
|
||||
[('! a)
|
||||
(unless (vector-ref assign n)
|
||||
(mrspidey:error
|
||||
"! used on immutable field in type"))
|
||||
;; Inject only
|
||||
(new-con!
|
||||
AVS
|
||||
(create-con template (vector-ref assign n)
|
||||
(parse-type-generic a env #t)))]
|
||||
[arg
|
||||
;; Extract
|
||||
(new-con!
|
||||
AVS
|
||||
(create-con template (vector-ref ref n)
|
||||
(parse-type-generic arg env #f)))]))
|
||||
args))
|
||||
AVS)]
|
||||
[_
|
||||
;; Didn't match any type
|
||||
(mrspidey:error (format "invalid type syntax ~s" t))])))])
|
||||
|
||||
(let ([AVS (parse-type-generic type empty-env sign)])
|
||||
AVS)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (type->con type AVS prefix top-misc)
|
||||
;; Assumes type is already expanded
|
||||
(new-edge! (generic-type->con type prefix empty-env #t) AVS)
|
||||
|
||||
;; Put top-misc in misc field of each AV
|
||||
(for-each
|
||||
(lambda (AV) (set-AV-misc! AV top-misc))
|
||||
(get-AVS-objs AVS)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (split-schema type)
|
||||
(match type
|
||||
[('forall vars type)
|
||||
(list
|
||||
(map (lambda (v) (cons v (mk-AVS-tmp v))) vars)
|
||||
type)]
|
||||
[type (list '() type)]))
|
||||
|
||||
(define (type-schema->con type AVS prefix top-misc)
|
||||
;; Assumes type is already expanded
|
||||
(match-let ([(forall-env type) (split-schema type)])
|
||||
(new-edge! (generic-type->con type prefix forall-env #t) AVS)
|
||||
|
||||
;; Put top-misc in misc field of each AV
|
||||
(for-each
|
||||
(lambda (AV) (set-AV-misc! AV top-misc))
|
||||
(get-AVS-objs AVS))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (type-schema->con-for-nargs type prefix n)
|
||||
;; Assumes type is already expanded
|
||||
;; Puts top-misc in misc field of top AV
|
||||
;; returns ((AVS-para ...) . AVS-result) if possible
|
||||
;; otherwise returns #f
|
||||
|
||||
(match-let ([(forall-env type) (split-schema type)])
|
||||
(match (dom+rng-for-nargs type n)
|
||||
[#f #f]
|
||||
[(forall-env para* rng)
|
||||
(recur loop ([para* para*]
|
||||
[AVS-para* '()])
|
||||
(match para*
|
||||
[()
|
||||
(cons (reverse AVS-para*)
|
||||
(generic-type->con rng prefix forall-env #t))]
|
||||
[(para . rest)
|
||||
(let* ([AVS-para (generic-type->con para prefix forall-env #f)])
|
||||
(loop rest (cons AVS-para AVS-para*)))]))])))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (dom+rng-for-nargs type nargs)
|
||||
;; extracts appropriate type from top-level case->.
|
||||
;; returns (forall-env (para ...) result) if matching case
|
||||
;; o/w returns #f
|
||||
|
||||
(let* ([try1
|
||||
(lambda (type forall)
|
||||
;; See if type has the right # args
|
||||
(match type
|
||||
[(dom '->* rng)
|
||||
(recur loop ([dom dom][para* '()][n nargs])
|
||||
(match dom
|
||||
[('nil)
|
||||
(if (zero? n)
|
||||
(list (map (lambda (v) (cons v (mk-AVS-tmp 'dr)))
|
||||
forall)
|
||||
(reverse para*)
|
||||
rng)
|
||||
#f)]
|
||||
[('cons para rest) (loop rest (cons para para*) (sub1 n))]
|
||||
[_ #f]))])
|
||||
[_ #f])]
|
||||
[try2
|
||||
(lambda (type forall)
|
||||
(match type
|
||||
[('case-> . types)
|
||||
(ormap (lambda (t) (try1 t forall)) types)]
|
||||
[type (try1 type forall)]))])
|
||||
(match type
|
||||
[('forall vars type) (try2 type vars)]
|
||||
[type (try2 type '())])))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define AVS-in-type?
|
||||
(lambda (AVS type)
|
||||
;; Checks if AVS is contained in the type
|
||||
;; Assumes type is already expanded
|
||||
|
||||
(letrec
|
||||
([visit-alloc (lambda () (make-vector num-AV #f))]
|
||||
[add-visit!
|
||||
(lambda (v AV)
|
||||
(vector-set! v (AV-num AV) #t))]
|
||||
[visited?
|
||||
(lambda (v AV)
|
||||
(vector-ref v (AV-num AV)))]
|
||||
[AVS-in-type?
|
||||
(lambda (AVS type env)
|
||||
;; env maps type vars to AV-membership test function
|
||||
(andmap (lambda (AV) (AV-in-type? AV type env))
|
||||
(get-AVS-objs AVS)))]
|
||||
[AV-in-type?
|
||||
(lambda (AV type env)
|
||||
;; env maps type vars to AV-membership test function
|
||||
(match type
|
||||
|
||||
;; Recursive definitions
|
||||
[('rec bind t2)
|
||||
(let*
|
||||
([a* (map car bind)]
|
||||
[t* (map cadr bind)]
|
||||
[envbox (box #f)]
|
||||
[nuenv
|
||||
(extend-env*
|
||||
env a*
|
||||
(map (lambda (t)
|
||||
(let ([v (visit-alloc)])
|
||||
(lambda (AV)
|
||||
(or (visited? v AV)
|
||||
(begin
|
||||
(add-visit! v AV)
|
||||
(AV-in-type? AV t (unbox envbox)))))))
|
||||
t*))])
|
||||
(set-box! envbox nuenv)
|
||||
(AV-in-type? AV t2 nuenv))]
|
||||
|
||||
[('case-> . types) (AV-in-type? AV (rac types) env)]
|
||||
|
||||
[('union . (? list? union))
|
||||
(ormap (lambda (type) (AV-in-type? AV type env))
|
||||
union)]
|
||||
['_ #t]
|
||||
[(? symbol? a)
|
||||
((lookup-or-fail env a (lambda () (lambda (AV) #t)))
|
||||
AV)]
|
||||
[(arg '->* res) (eq? (AV-template AV) template-lam)]
|
||||
|
||||
[(? number? n)
|
||||
(and (eq? (template-type (AV-template AV)) 'num)
|
||||
(= (AV-misc AV) n))]
|
||||
[(? char? c)
|
||||
(and (eq? (template-type (AV-template AV)) 'char)
|
||||
(char=? (AV-misc AV) c))]
|
||||
[('quote (? symbol? s))
|
||||
(and (eq? (template-type (AV-template AV)) 'sym)
|
||||
(eq? (AV-misc AV) s))]
|
||||
|
||||
[((? type-constructor? C) . args)
|
||||
(match-let
|
||||
([(and template ($ template type signs ref assign))
|
||||
(lookup-template C)])
|
||||
(cond
|
||||
[(eq? (AV-template AV) template)
|
||||
(recur loop ([args args][n 0])
|
||||
(if (null? args)
|
||||
#t
|
||||
(and
|
||||
(AVS-in-type?
|
||||
(vector-ref (AV-fields AV) (vector-ref ref n))
|
||||
(match args
|
||||
[(('! a) . _) a]
|
||||
[(a . _) a])
|
||||
env)
|
||||
(loop (cdr args) (add1 n)))))]
|
||||
[(memq (AV-template AV) (template-sub-templates template))
|
||||
#t]
|
||||
[else #f]))]
|
||||
[_
|
||||
;; Didn't match any type
|
||||
(mrspidey:error (format "Invalid type syntax ~s" type))]))])
|
||||
(AVS-in-type? AVS type empty-env))))
|
||||
|
||||
;(trace AVS-in-type?)
|
||||
|
||||
|
||||
|
@ -0,0 +1,116 @@
|
||||
;; type-env.ss
|
||||
;; Handles the type environment (env for type inference)
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
;; ======================================================================
|
||||
;; Global type env
|
||||
|
||||
(define global-tref-env '())
|
||||
(define global-tdef-env '())
|
||||
(define global-tbang-env '())
|
||||
|
||||
(define (add-global-tref! sym tvar)
|
||||
(set! global-tref-env (cons (cons sym tvar) global-tref-env)))
|
||||
(define (add-global-tdef! sym tvar)
|
||||
(set! global-tdef-env (cons (cons sym tvar) global-tdef-env)))
|
||||
(define (add-global-tbang! sym tvar)
|
||||
(set! global-tbang-env (cons (cons sym tvar) global-tbang-env)))
|
||||
(define (init-global-tenv! r d b)
|
||||
(set! global-tref-env r)
|
||||
(set! global-tdef-env d)
|
||||
(set! global-tbang-env b))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; find-matching-def
|
||||
|
||||
(define (find-matching-def sym defs)
|
||||
(ormap (match-lambda
|
||||
[(sym2 . def) (and (eq? sym sym2) def)])
|
||||
defs))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; report-duplicate-defs
|
||||
;; Report duplicate definitions
|
||||
|
||||
(define (report-duplicate-defs env)
|
||||
(pretty-debug `(report-duplicate-defs ,@(map car env)))
|
||||
(recur loop ([env env][dupls '()])
|
||||
(match env
|
||||
[() (void)]
|
||||
[((sym1 . _) . rest)
|
||||
(if (and (find-matching-def sym1 rest)
|
||||
(not (memq sym1 dupls)))
|
||||
(begin
|
||||
(mrspidey:warning
|
||||
(format "Duplicate definition of variable ~s" sym1))
|
||||
(loop rest (cons sym1 dupls)))
|
||||
(loop rest dupls))])))
|
||||
|
||||
;;----------------------------------------------------------------------
|
||||
;; report-unbound-vars-env
|
||||
|
||||
(define report-unbound-vars
|
||||
(case-lambda
|
||||
[(ref-env) (report-unbound-vars ref-env "")]
|
||||
[(ref-env msg)
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(sym . _)
|
||||
(mrspidey:warning (format "Unbound type variable ~s~a" sym msg))])
|
||||
ref-env)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; connect-refs-defs
|
||||
;; Connects refs to defs, returns list of unbound refs
|
||||
|
||||
(define (connect-refs-defs ref-env def-env)
|
||||
(pretty-debug
|
||||
`(connect-refs-defs ,(map car ref-env) ,(map car def-env)))
|
||||
(filter
|
||||
(match-lambda
|
||||
[(and r (sym . tvar))
|
||||
(match (find-matching-def sym def-env)
|
||||
[#f #t]
|
||||
[ftype
|
||||
(new-edge! (FlowType->Tvar ftype) tvar)
|
||||
#f])])
|
||||
ref-env))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; combine-def-bang
|
||||
;; Connects each bang to def, and reports bangs to undefd vars
|
||||
|
||||
(define (connect-bangs-defs bang-env def-env)
|
||||
(pretty-debug
|
||||
`(connect-bangs-defs ,(map car bang-env) ,(map car def-env)))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(s2 . tvar2)
|
||||
(match (find-matching-def s2 def-env)
|
||||
[#f (mrspidey:warning
|
||||
(format "Assignment to undefined variable ~s" s2))]
|
||||
[tvar1
|
||||
(unless (Tvar? tvar1)
|
||||
(mrspidey:error "Assignment to annotated type"))
|
||||
(assert (Tvar? tvar2))
|
||||
(new-edge! tvar2 tvar1)])])
|
||||
bang-env))
|
||||
|
||||
|
||||
|
@ -0,0 +1,878 @@
|
||||
;; typelang.ss
|
||||
;; Parses a type to produce a set of constraints
|
||||
;; Also tests an Tvar for membership in a type
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
;; type ::= ...
|
||||
;; schema ::= type | (forall vars type)
|
||||
;; tschema ::= schema | (case-> schema ...)
|
||||
;; lambda types are
|
||||
;; (a b c -> d e f)
|
||||
;; (a b c rest *-> d e f)
|
||||
;; (a b c ->* results)
|
||||
;; (a b c rest *->* results)
|
||||
;; (lambda domain range)
|
||||
;; ======================================================================
|
||||
; Union, Intersect etc
|
||||
|
||||
(define absUnion
|
||||
(lambda (exps)
|
||||
(match
|
||||
(apply append
|
||||
(map
|
||||
(match-lambda
|
||||
['empty '()]
|
||||
[('union . exps) exps]
|
||||
[exp (list exp)])
|
||||
;;(list->set-equal? exps)
|
||||
exps
|
||||
))
|
||||
[() 'empty]
|
||||
[(e) e]
|
||||
[exps `(union ,@exps)])))
|
||||
|
||||
(define absunion (lambda exps (absUnion exps)))
|
||||
|
||||
(define absIntersect
|
||||
(lambda (exps)
|
||||
(match
|
||||
(apply append
|
||||
(map
|
||||
(match-lambda
|
||||
['_ '()]
|
||||
[('intersect . exps) exps]
|
||||
[exp (list exp)])
|
||||
(list->set-equal? exps)))
|
||||
[() '_]
|
||||
[(e) e]
|
||||
[exps `(intersect ,@exps)])))
|
||||
|
||||
(define absintersect (lambda exps (absIntersect exps)))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (output-type-constructor? C)
|
||||
(or
|
||||
(memq C '(bool listof list atom sexp values))
|
||||
(type-constructor? C)))
|
||||
|
||||
(define (output-type-expander type)
|
||||
(all-output-type-expanders
|
||||
(or
|
||||
(compat-type-once type output-type-expander)
|
||||
type)))
|
||||
|
||||
;---
|
||||
(define output-type-expanders '())
|
||||
|
||||
(define (all-output-type-expanders type)
|
||||
(foldl
|
||||
(lambda (expander type) (expander type))
|
||||
type
|
||||
output-type-expanders))
|
||||
|
||||
;---
|
||||
|
||||
(define (install-output-type-expander! expander)
|
||||
(set! output-type-expanders (cons expander output-type-expanders)))
|
||||
|
||||
(define (init-output-type-expander!)
|
||||
|
||||
(install-output-type-expander!
|
||||
(match-lambda
|
||||
[((? output-type-constructor? C)) C]
|
||||
[('cons t 'nil) `(list ,t)]
|
||||
[('cons t ('list . t*)) `(list ,t ,@t*)]
|
||||
[('lambda dom rng) (list dom '*->* rng)]
|
||||
[('unit-result* ('values rng)) `(unit-result ,rng)]
|
||||
[('union X) X]
|
||||
[(? list? t)
|
||||
(=> fail)
|
||||
(match (reverse t)
|
||||
[( ('values x)
|
||||
(and arrow (or '*->* '->*))
|
||||
. domains)
|
||||
(append (reverse domains)
|
||||
(list (case arrow
|
||||
[(*->*) '*->]
|
||||
[(->*) '->])
|
||||
x))]
|
||||
[_ (fail)])]
|
||||
[(('list . args) '*-> . results) `(,@args -> . ,results)]
|
||||
[(('list . args) '*->* . results) `(,@args ->* . ,results)]
|
||||
[('union . X)
|
||||
(=> fail)
|
||||
(cond
|
||||
[(and (memq 'true X) (memq 'false X))
|
||||
`(union bool ,@(remq 'true (remq 'false X)))]
|
||||
[(and (memq 'bool X)
|
||||
(or (memq 'true X) (memq 'false X)))
|
||||
`(union ,@(remq 'true (remq 'false X)))]
|
||||
[else (fail)])]
|
||||
[(or ('union 'true 'false) ('union 'false 'true)) 'bool]
|
||||
|
||||
[('mvalues ('list . x)) `(values ,@x)]
|
||||
[('rec () body) body]
|
||||
[(or
|
||||
('union 'nil ('cons X ('listof Y)))
|
||||
('union ('cons X ('listof Y)) 'nil))
|
||||
(=> fail)
|
||||
(if (equal? X Y) `(listof ,Y) (fail))]
|
||||
[('epsilon X) X]
|
||||
[((and combine (or 'union 'intersect)) . parts)
|
||||
(=> fail)
|
||||
(if (not (st:sdl-tidy))
|
||||
(fail)
|
||||
(let ([combine-fn (case combine
|
||||
[(intersect) absintersect]
|
||||
[(union) absunion])])
|
||||
(pretty-debug-sdl `(combine ,combine parts ,parts))
|
||||
(apply combine-fn
|
||||
(recur loop ([parts parts])
|
||||
(match parts
|
||||
[(a . d)
|
||||
(let ([d (loop d)])
|
||||
(if (member a d)
|
||||
d
|
||||
(match a
|
||||
[((? output-type-constructor? C) . C-args)
|
||||
(let*-vals
|
||||
( [len-C-args (length C-args)]
|
||||
[(args* rest)
|
||||
(filter-map-split
|
||||
(match-lambda
|
||||
[(C2 . args)
|
||||
(and
|
||||
(eq? C C2)
|
||||
(= len-C-args (length args))
|
||||
args)]
|
||||
[_ #f])
|
||||
parts)])
|
||||
(pretty-debug-sdl `(args* ,args* rest ,rest))
|
||||
(if (null? (cdr args*))
|
||||
(cons a d)
|
||||
(cons (cons C (apply map
|
||||
combine-fn
|
||||
args*))
|
||||
rest)))]
|
||||
[_ (cons a d)])))]
|
||||
[() '()])))))]
|
||||
[type type]))
|
||||
)
|
||||
|
||||
|
||||
|
||||
;; ======================================================================
|
||||
;; For input-type-expander, recursion is done in expand-input-type
|
||||
|
||||
(define input-type-expander 'input-type-expander)
|
||||
|
||||
(define (init-input-type-expander!)
|
||||
(set! input-type-expander (lambda (x) x))
|
||||
(let ([loop (lambda (x) x)])
|
||||
(install-input-type-expander!
|
||||
(match-lambda
|
||||
['atom (loop '(union nil num sym str char true false))]
|
||||
['sexp (let ([u (gensym)])
|
||||
(loop `(MU ,u (union atom (box ,u) (cons ,u ,u) (vec ,u)))))]
|
||||
['bool (loop '(union false true))]
|
||||
[('arg a b) (loop (list 'cons a b))]
|
||||
['noarg (loop 'nil)]
|
||||
['null (loop 'nil)]
|
||||
[('arglistof t)
|
||||
(let ((u (gensym)))
|
||||
(loop `(MU ,u (union noarg (arg ,t ,u)))))]
|
||||
[('arglist) (loop 'noarg)]
|
||||
[('arglist t . t*) (loop `(arg ,t (list ,@t*)))]
|
||||
[('listof t)
|
||||
(let ((u (gensym)))
|
||||
(loop `(MU ,u (union nil (cons ,t ,u)))))]
|
||||
[('list) (loop 'nil)]
|
||||
[('list t . t*) (loop `(cons ,t (list ,@t*)))]
|
||||
|
||||
[('MU (? typevar? a) t)
|
||||
(loop `(rec ([,a ,t]) ,a))]
|
||||
[(? type-constructor? C) (loop (list C))]
|
||||
[(? (lambda (t) (and (list? t) (memq '-> t)))
|
||||
t)
|
||||
;; Make the *-> function
|
||||
(recur loop2 ([wrapper-fn (lambda (x) x)]
|
||||
[t t])
|
||||
(match t
|
||||
[('-> . results)
|
||||
(loop `(,(wrapper-fn 'noarg) *-> ,@results))]
|
||||
[('optional y . rest)
|
||||
(loop2 (lambda (x) (wrapper-fn `(union noarg (arg ,y ,x))))
|
||||
rest)]
|
||||
[(y . rest)
|
||||
(loop2 (lambda (x) (wrapper-fn `(arg ,y ,x)))
|
||||
rest)]))]
|
||||
[(? (lambda (t) (and (list? t) (memq '*-> t)))
|
||||
t)
|
||||
;; Make the *->* function
|
||||
(recur loop2 ( [wrapper-fn (lambda (x) x)]
|
||||
[t t])
|
||||
(match t
|
||||
[('*-> . _) (mrspidey:error "*-> type w/o domain")]
|
||||
[(rest '*-> . results)
|
||||
(loop `(,(wrapper-fn rest)
|
||||
*->*
|
||||
(mvalues
|
||||
,(foldr (lambda (arg rest) `(cons ,arg ,rest))
|
||||
'(nil)
|
||||
results))))]
|
||||
[(y . rest)
|
||||
(loop2 (lambda (x) (wrapper-fn `(arg ,y ,x)))
|
||||
rest)]))]
|
||||
[(? (lambda (t) (and (list? t) (memq '->* t))) t)
|
||||
(match (reverse t)
|
||||
[(result '->* . domain)
|
||||
`( (list ,@(reverse domain)) *->* ,result)]
|
||||
[_ (mrspidey:error "Bad type ~s" t)])]
|
||||
[(dom '*->* rng) (loop `(lambda ,dom ,rng))]
|
||||
[type type]))))
|
||||
|
||||
(define (install-input-type-expander! expander)
|
||||
(let ([old-expander input-type-expander])
|
||||
(set! input-type-expander
|
||||
(lambda (type)
|
||||
;;(pretty-print-debug `(input-type-expander ,type))
|
||||
(old-expander (expander type))))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define typevar?
|
||||
(lambda (v)
|
||||
(and (symbol? v)
|
||||
(not (output-type-constructor? v))
|
||||
(not (memq v '(_ union rec -> *-> ->* *->*))))))
|
||||
|
||||
(define (compat-type-once type cl-fn)
|
||||
(match type
|
||||
[(and c (or (? number?) (? char?) ((or 'quote '#%quote) (? symbol?)))) c]
|
||||
[('rec bind t2)
|
||||
`(rec ,(map (match-lambda [(a t) (list a (cl-fn t))]) bind)
|
||||
,(cl-fn t2))]
|
||||
[('forall vars type)
|
||||
`(forall ,vars ,(cl-fn type))]
|
||||
[('case-> . (and types (? list?) (_ . _)))
|
||||
`(case-> ,@(map cl-fn types))]
|
||||
[('union . (? list? union)) `(union ,@(map cl-fn union))]
|
||||
[('scheme: E) type]
|
||||
[('intersect . (? list? union)) `(intersect ,@(map cl-fn union))]
|
||||
[(? symbol? a) a]
|
||||
[((? (lambda (t) (memq t '(object class))) t) . ivar-types)
|
||||
(cons t
|
||||
(map
|
||||
(match-lambda
|
||||
[(ivar type) (list ivar (cl-fn type))])
|
||||
ivar-types))]
|
||||
;; check constructors
|
||||
[((? output-type-constructor? C) . args)
|
||||
`(,C ,@(map (match-lambda
|
||||
[('! arg) (list '! (cl-fn arg))]
|
||||
[arg (cl-fn arg)])
|
||||
args))]
|
||||
[(? (lambda (t)
|
||||
(and (list? t)
|
||||
(or (memq '-> t) (memq '*-> t) (memq '->* t) (memq '*->* t))))
|
||||
t)
|
||||
(map cl-fn t)]
|
||||
[_ #f]))
|
||||
|
||||
(define (expand-input-type type)
|
||||
;; Do rewriting transformations
|
||||
;; (pretty-print-debug `(expand-type ,type))
|
||||
(let ([t2 (input-type-expander type)])
|
||||
(if (eq? type t2)
|
||||
(or (compat-type-once type expand-input-type)
|
||||
(mrspidey:error (format "Invalid type syntax ~s" type)))
|
||||
(expand-input-type t2))))
|
||||
|
||||
(define (expand-input-type-err type at)
|
||||
;; Do rewriting transformations
|
||||
;; (pretty-print-debug `(expand-type ,type))
|
||||
(let ([t2 (input-type-expander type)])
|
||||
(if (eq? type t2)
|
||||
(or (compat-type-once type
|
||||
(lambda (type) (expand-input-type-err type at)))
|
||||
(mrspidey:error (format "Invalid type syntax ~s" type) at))
|
||||
(expand-input-type-err t2 at))))
|
||||
|
||||
(define (expand-output-type type)
|
||||
;; Do rewriting transformations
|
||||
(pretty-debug `(expand-output-type ,type))
|
||||
(letrec
|
||||
([local-expand-output-type
|
||||
(lambda (type)
|
||||
(let* ([type (or (compat-type-once type local-expand-output-type)
|
||||
type
|
||||
(mrspidey:error (format "Bad output type ~s" type)))])
|
||||
(let ([t2 (output-type-expander type)])
|
||||
(if (equal? type t2)
|
||||
type
|
||||
(local-expand-output-type t2)))))])
|
||||
(if (st:expand-output-type)
|
||||
(match (local-expand-output-type type)
|
||||
[('values x) x]
|
||||
[('rec bindings ('values x)) `(rec ,bindings ,x)]
|
||||
[x x])
|
||||
type)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (type->templates con-exp)
|
||||
;; Assumes con-exp already expanded
|
||||
(match con-exp
|
||||
[('union . E*)
|
||||
(let* ([T* (map type->templates E*)])
|
||||
(if (andmap (lambda (x) x) T*)
|
||||
(apply union T*)
|
||||
#f))]
|
||||
[('intersect . E*)
|
||||
(let* ([T* (map type->templates E*)]
|
||||
[T* (filter (lambda (x) x) T*)])
|
||||
(apply intersect T*))]
|
||||
[('forall _ type) (type->templates type)]
|
||||
[(or (C . _) C)
|
||||
(if (type-constructor? C)
|
||||
(list (lookup-template C))
|
||||
#f)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define ( generic-type->con type prefix forall-env sign)
|
||||
;; Assumes type is already expanded
|
||||
(letrec
|
||||
([mk-Tvar-tmp (lambda () (mk-Tvar (symbol-append prefix ':tc)))]
|
||||
[parse-type-generic
|
||||
(lambda (t env sign)
|
||||
;; sign is #t for +ive, #f for -ive
|
||||
;; (pretty-print-debug `(parse-type-generic ,t ,env ,sign))
|
||||
(let ([new-sign-edge!
|
||||
(lambda (from to)
|
||||
(if sign
|
||||
(new-edge! from to)
|
||||
(new-edge! to from)))]
|
||||
[parse-type
|
||||
(lambda (t)
|
||||
(let ([r (parse-type-generic t env sign)])
|
||||
;;(pretty-print-debug `(parse-type-generic ,t ,(Tvar-name r)))
|
||||
r))])
|
||||
(match t
|
||||
|
||||
;; Recursive definitions
|
||||
[('rec bind t2)
|
||||
(let* ( [a* (map car bind)]
|
||||
[env env]
|
||||
[mk-tvar*
|
||||
(map
|
||||
(lambda (a rhs)
|
||||
(letrec
|
||||
([f (lambda (sign)
|
||||
(pretty-debug `(rec ,a ,sign))
|
||||
(let*
|
||||
( [sym (symbol-append prefix ': a)]
|
||||
[tvar (mk-Tvar sym)]
|
||||
[_ (set! f
|
||||
(lambda (sign2)
|
||||
(unless (eq? sign sign2)
|
||||
(mrspidey:error
|
||||
(format "rec-bound variable ~s referenced in covariant and contravariant positions in type ~s" a type)))
|
||||
tvar))]
|
||||
[tvar2
|
||||
(parse-type-generic rhs env sign)])
|
||||
(if sign
|
||||
(new-edge! tvar2 tvar)
|
||||
(new-edge! tvar tvar2))
|
||||
tvar))])
|
||||
(lambda (sign) (f sign))))
|
||||
a* (map cadr bind))])
|
||||
(set! env (extend-env* env a* mk-tvar*))
|
||||
(parse-type-generic t2 env sign))]
|
||||
|
||||
;; Unions
|
||||
[('union . (? list? union))
|
||||
(let ([Tvar (mk-Tvar-tmp)])
|
||||
(for-each
|
||||
(lambda (t)
|
||||
(new-sign-edge! (parse-type-generic t env sign) Tvar))
|
||||
union)
|
||||
Tvar)]
|
||||
|
||||
;; Scheme
|
||||
;[('scheme: E)
|
||||
; (assert (eq? sign #t) 'scheme:)
|
||||
; (let*-vals
|
||||
; ( [p (open-output-string)]
|
||||
; [_ '(pretty-print E p)]
|
||||
; [p (close-output-port)]
|
||||
; [s (get-output-string p)]
|
||||
; [p (open-input-string s)]
|
||||
; [E ((zodiac:read p))]
|
||||
; [defs (my-scheme-expand-program (list E))]
|
||||
; [(ftype _ _) (traverse-exp (car defs) atenv:empty)]
|
||||
; [tvar (FlowType->Tvar ftype)])
|
||||
; tvar)]
|
||||
|
||||
[('intersect . (? list? intersect))
|
||||
(when sign
|
||||
(mrspidey:error "Intersection in covariant position"))
|
||||
(let ([Tvar (mk-Tvar-tmp)])
|
||||
(for-each
|
||||
(lambda (t)
|
||||
(new-edge! Tvar (parse-type-generic t env sign)))
|
||||
intersect)
|
||||
Tvar)]
|
||||
|
||||
;; type variables
|
||||
['_
|
||||
(when sign
|
||||
(mrspidey:error "_ type in covariant position"))
|
||||
(mk-Tvar-tmp)]
|
||||
|
||||
['empty
|
||||
(unless sign
|
||||
(mrspidey:error
|
||||
(format "empty in contravariant position in ~s" type)))
|
||||
(mk-Tvar-tmp)]
|
||||
|
||||
[(? symbol? a)
|
||||
(cond
|
||||
[(lookup-or-#f env a)
|
||||
=> (lambda (mk-tvar) (mk-tvar sign))]
|
||||
[else
|
||||
(or
|
||||
(lookup-or-#f forall-env a)
|
||||
(let ([Tvar (mk-Tvar a)])
|
||||
(if sign
|
||||
(add-global-tref! a Tvar)
|
||||
(add-global-tbang! a Tvar))
|
||||
Tvar))])]
|
||||
|
||||
[('lambda arg res)
|
||||
(let ([Tvar (mk-Tvar-tmp)])
|
||||
(if sign
|
||||
;; make the AV
|
||||
(new-AV! Tvar
|
||||
(make-AV-lam
|
||||
(parse-type-generic arg env #f)
|
||||
(parse-type-generic res env #t)
|
||||
0 #t))
|
||||
;; extract the various components
|
||||
(begin
|
||||
(new-con! Tvar
|
||||
(make-con-dom (parse-type-generic arg env #t)))
|
||||
(new-con! Tvar
|
||||
(make-con-rng
|
||||
(parse-type-generic res env #f)))))
|
||||
Tvar)]
|
||||
|
||||
;; constants
|
||||
[(or (? number? c) (? char? c)
|
||||
((or 'quote '#%quote) (? symbol? c)))
|
||||
(let ([Tvar (mk-Tvar-tmp)])
|
||||
(if sign (new-AV! Tvar (traverse-simple-const c)))
|
||||
Tvar)]
|
||||
|
||||
;; check constructors
|
||||
[((? type-constructor? C) . args)
|
||||
(match-let*
|
||||
([(and template ($ template type n+ n- ref assign))
|
||||
(lookup-template C)]
|
||||
[Tvar (mk-Tvar-tmp)])
|
||||
(unless (= (vector-length ref) (length args))
|
||||
(mrspidey:error
|
||||
(format "Constructor ~s given ~s arg(s), expected ~s"
|
||||
C (length args) (vector-length ref))))
|
||||
(if sign
|
||||
;; make the AV, unless void and (st:see-void) is false
|
||||
(unless (and (eq? C 'void) (not (st:see-void)))
|
||||
(let ([args
|
||||
(map
|
||||
(lambda (a) (parse-type-generic a env sign))
|
||||
args)])
|
||||
;;(pretty-print-debug `(,C ,@(map Tvar-name args)))
|
||||
(new-AV!
|
||||
Tvar
|
||||
(apply make-constructed-AV C args))))
|
||||
;; DO SOMETHING FOR NULL ARGS
|
||||
|
||||
;; extract the various components
|
||||
;; need to do unification on mutable fields,
|
||||
;; unless pattern matching arg is (! a)
|
||||
(for-each-with-n
|
||||
(lambda (arg n)
|
||||
(match arg
|
||||
[(or '_ 'top)(void)]
|
||||
[('! a)
|
||||
(match (vector-ref assign n)
|
||||
[#f
|
||||
(mrspidey:error
|
||||
"! used on immutable field in type")]
|
||||
[n
|
||||
;; Inject only
|
||||
(new-con!
|
||||
Tvar
|
||||
(create-con template n
|
||||
(parse-type-generic a env #t) #f))])]
|
||||
[arg
|
||||
;; Extract
|
||||
(new-con!
|
||||
Tvar
|
||||
(create-con template (vector-ref ref n)
|
||||
(parse-type-generic arg env #f) #t))]))
|
||||
args))
|
||||
Tvar)]
|
||||
[_
|
||||
;; Didn't match any type
|
||||
(mrspidey:error (format "invalid type syntax ~s" t))])))])
|
||||
|
||||
(let ([Tvar (parse-type-generic type empty-env sign)])
|
||||
Tvar)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (split-schema type)
|
||||
(match type
|
||||
[('forall vars type)
|
||||
(values vars type)]
|
||||
[type (values '() type)]))
|
||||
|
||||
(define (schema->env+type type)
|
||||
(let-values ([(vars type) (split-schema type)])
|
||||
(values
|
||||
(map (lambda (v) (cons v (mk-Tvar v))) vars)
|
||||
type)))
|
||||
|
||||
(define (schema->con schema Tvar prefix top-misc)
|
||||
(let-values ([(forall-env type) (schema->env+type schema)])
|
||||
|
||||
(new-edge! (generic-type->con type prefix forall-env #t) Tvar)
|
||||
|
||||
;; Put top-misc in misc field of each AV
|
||||
(for-each
|
||||
(lambda (AV) (set-AV-misc! AV top-misc))
|
||||
(get-Tvar-objs Tvar))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (tschema->con tschema Tvar prefix top-misc)
|
||||
(schema->con
|
||||
(match tschema
|
||||
[('case-> . schema*) (rac schema*)]
|
||||
[schema schema])
|
||||
Tvar prefix top-misc))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (tschema->con-for-nargs tschema Tvar prefix top-misc n)
|
||||
;; Assumes type is already expanded
|
||||
|
||||
(match tschema
|
||||
[('case-> . schema*)
|
||||
(or
|
||||
(ormap
|
||||
(lambda (schema)
|
||||
(let-values ([(forall-env type) (schema->env+type schema)])
|
||||
(if (function-takes-nargs? type n)
|
||||
(schema->con schema Tvar prefix top-misc)
|
||||
#f)))
|
||||
schema*)
|
||||
(schema->con (rac schema*) Tvar prefix top-misc))]
|
||||
[schema
|
||||
(schema->con schema Tvar prefix top-misc)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (function-takes-nargs? type nargs)
|
||||
(match type
|
||||
[('lambda dom rng)
|
||||
(recur loop ([dom dom][n nargs])
|
||||
(match dom
|
||||
[('nil) (zero? n)]
|
||||
[('cons para rest) (loop rest (sub1 n))]
|
||||
[_ #f]))]
|
||||
[_ #f]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
'(define (Tvar-in-type? ftype type)
|
||||
(let* ([o (old-Tvar-in-type? ftype type)]
|
||||
[Tvar2 (mk-Tvar 'in-type?)]
|
||||
[_ (tschema->con type Tvar 'in-type? '())]
|
||||
[n (Tvar-containment? ftype ftype2)])
|
||||
(unless (eq? o n)
|
||||
(mrspidey:warning
|
||||
(format "Tvar-in-type old ~s new ~s type ~s" o n type))
|
||||
o)))
|
||||
|
||||
(define Tvar-in-type?
|
||||
(lambda (Tvar type forall-vars unbound)
|
||||
|
||||
;; (pretty-print `(Tvar-in-type? ,(Tvar-name Tvar) ,type ,forall-vars))
|
||||
;; Checks if Tvar is contained in the type
|
||||
;; Assumes type is already expanded
|
||||
|
||||
(letrec
|
||||
([visit-alloc (lambda () (make-vector num-AV #f))]
|
||||
[add-visit!
|
||||
(lambda (v AV)
|
||||
(vector-set! v (AV-num AV) #t))]
|
||||
[visited?
|
||||
(lambda (v AV)
|
||||
(vector-ref v (AV-num AV)))]
|
||||
[Tvar-in-type?
|
||||
(lambda (Tvar type env)
|
||||
;; env maps type vars to AV-membership test function
|
||||
(andmap (lambda (AV) (AV-in-type? AV type env))
|
||||
(get-Tvar-objs Tvar)))]
|
||||
[AV-in-type?
|
||||
(lambda (AV type env)
|
||||
;; env maps type vars to AV-membership test function
|
||||
(match type
|
||||
|
||||
;; Recursive definitions
|
||||
[('rec bind t2)
|
||||
(let*
|
||||
([a* (map car bind)]
|
||||
[t* (map cadr bind)]
|
||||
[envbox (box #f)]
|
||||
[nuenv
|
||||
(extend-env*
|
||||
env a*
|
||||
(map (lambda (t)
|
||||
(let ([v (visit-alloc)])
|
||||
(lambda (AV)
|
||||
(or (visited? v AV)
|
||||
(begin
|
||||
(add-visit! v AV)
|
||||
(AV-in-type? AV t (unbox envbox)))))))
|
||||
t*))])
|
||||
(set-box! envbox nuenv)
|
||||
(AV-in-type? AV t2 nuenv))]
|
||||
|
||||
[('case-> . types) (AV-in-type? AV (rac types) env)]
|
||||
|
||||
[('union . (? list? union))
|
||||
(ormap (lambda (type) (AV-in-type? AV type env))
|
||||
union)]
|
||||
[('intersect . (? list? intersect))
|
||||
(andmap (lambda (type) (AV-in-type? AV type env))
|
||||
intersect)]
|
||||
['_ #t]
|
||||
[(? symbol? a)
|
||||
(let ([fn (or (lookup-or-#f env a)
|
||||
(and (memq a forall-vars) (lambda (AV) #t))
|
||||
(let ([type:a a])
|
||||
(ormap
|
||||
(match-lambda
|
||||
[(sym . Tvar)
|
||||
(if (eq? sym type:a)
|
||||
(lambda (AV)
|
||||
(let ([Tvar-t (mk-Tvar 'in-type?)])
|
||||
(new-AV! Tvar-t AV)
|
||||
(Tvar-containment? Tvar-t Tvar)))
|
||||
#f)])
|
||||
global-tdef-env))
|
||||
(unbound a))])
|
||||
(fn AV))]
|
||||
[('lambda arg res)
|
||||
(and (eq? (AV-template AV) template-lam)
|
||||
(Tvar-in-type?
|
||||
(vector-ref (AV-fields+ AV) 0)
|
||||
res
|
||||
env))]
|
||||
[(? number? n)
|
||||
(and (eq? (template-type (AV-template AV)) 'num)
|
||||
(number? (AV-misc AV))
|
||||
(= (AV-misc AV) n))]
|
||||
[(? char? c)
|
||||
(and (eq? (template-type (AV-template AV)) 'char)
|
||||
(char=? (AV-misc AV) c))]
|
||||
[((or 'quote '#%quote) (? symbol? s))
|
||||
(and (eq? (template-type (AV-template AV)) 'sym)
|
||||
(eq? (AV-misc AV) s))]
|
||||
|
||||
[((? type-constructor? C) . args)
|
||||
(match-let
|
||||
([(and template ($ template type n+ n- ref assign))
|
||||
(lookup-template C)])
|
||||
(cond
|
||||
[(or (eq? (AV-template AV) template)
|
||||
(memq template
|
||||
(template-super-templates (AV-template AV))))
|
||||
(recur loop ([args args][n 0])
|
||||
(if (null? args)
|
||||
#t
|
||||
(and
|
||||
(or
|
||||
(not (vector-ref ref n));; Can't reference
|
||||
(Tvar-in-type?
|
||||
(vector-ref (AV-fields+ AV) (vector-ref ref n))
|
||||
(match args
|
||||
[(('! a) . _) a]
|
||||
[(a . _) a])
|
||||
env))
|
||||
(loop (cdr args) (add1 n)))))]
|
||||
[else
|
||||
'(pretty-print-debug
|
||||
`(fail ,(AV-template AV)
|
||||
,C
|
||||
,template
|
||||
,(template-super-templates (AV-template AV))
|
||||
,(memq template
|
||||
(template-super-templates (AV-template AV)))))
|
||||
#f]))]
|
||||
[_
|
||||
;; Didn't match any type
|
||||
(mrspidey:error (format "Invalid type syntax ~s" type))]))])
|
||||
(Tvar-in-type? Tvar type empty-env))))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
'(define (FV-tschema tschema)
|
||||
;; returns (FV-ref FV-bang)
|
||||
(let ([FV-ref '()]
|
||||
[FV-bang '()])
|
||||
(letrec
|
||||
([FV-type
|
||||
(lambda (type env sign)
|
||||
(match type
|
||||
[('rec bind t2)
|
||||
(let ([env (append (map car bind) env)])
|
||||
(FV-type* (map cadr bind) env sign)
|
||||
(FV-type t2 env sing))]
|
||||
[((or 'union 'intersect (? type-constructor?)) . (? list? args))
|
||||
(FV-type* args env sign)]
|
||||
[(or '_ 'empty (? number?) (? char?)
|
||||
((or 'quote '#%quote) (? symbol?)))
|
||||
(void)]
|
||||
[(or (? symbol? a) ('! (? symbol? a)))
|
||||
(if sign
|
||||
(set! FV-ref (set-add a FV-ref))
|
||||
(set! FV-bang (set-add a FV-bang)))]
|
||||
[x
|
||||
;; Didn't match any type
|
||||
(mrspidey:internal-error 'FV-type
|
||||
"invalid type syntax ~s" x)]))]
|
||||
[FV-type*
|
||||
(lambda (types env sign)
|
||||
(for-each (lambda (t) (FV-type t env sign)) types))]
|
||||
[FV-schema
|
||||
(match-lambda
|
||||
[('forall vars type)
|
||||
(setdiff2 (FV-type type) vars)]
|
||||
[type (FV-type type vars #t)])]
|
||||
[FV-tschema
|
||||
(match-lambda
|
||||
[('case-> . schemas)
|
||||
(apply union (map FV-schema schemas))]
|
||||
[schema (FV-schema schema)])])
|
||||
(FV-tschema tschema)
|
||||
(list FV-ref FV-bang))))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
(define (primitive->atprim name orig-type-schema . attrs)
|
||||
;;(pretty-debug `(primitive->atprim ,name))
|
||||
(match-let*
|
||||
( [type-schema (expand-input-type orig-type-schema)]
|
||||
[type (match type-schema
|
||||
[('forall _ type) type]
|
||||
[type type])])
|
||||
|
||||
(make-atprim
|
||||
name
|
||||
type-schema
|
||||
|
||||
;; Calculate filter-domains
|
||||
(match type
|
||||
[('lambda domain _)
|
||||
;; Now walk domain and args
|
||||
(recur loop ([domain domain])
|
||||
(match domain
|
||||
[('cons domain d-rest)
|
||||
(cons
|
||||
(let ([templates (type->templates domain)])
|
||||
(if templates
|
||||
(create-filter #t templates)
|
||||
#f))
|
||||
(loop d-rest))]
|
||||
[_ '()]))]
|
||||
[_ '()])
|
||||
|
||||
;; Calculate predicate-fn
|
||||
(foldl
|
||||
(lambda (attr predicate-fn)
|
||||
(let*
|
||||
([mk-predicate-fn
|
||||
(lambda (filter-then filter-else)
|
||||
(lambda (b a Tvar sign)
|
||||
'(printf "mk-predicate-fn ~s ~s ~s ~s ~s ~s~n"
|
||||
filter-then filter-else b a Tvar sign)
|
||||
(let ([filter (if sign filter-then filter-else)])
|
||||
(if filter
|
||||
(let ([nu-Tvar (mk-Tvar 'filter)])
|
||||
(new-con! Tvar
|
||||
(create-con-filter filter
|
||||
nu-Tvar))
|
||||
nu-Tvar)
|
||||
Tvar))))]
|
||||
[get-templates
|
||||
(lambda (C*)
|
||||
(map
|
||||
(lambda (C)
|
||||
(or (lookup-template C)
|
||||
(mrspidey:error
|
||||
(format "Unknown constructor ~s in primitive def" C))))
|
||||
C*))]
|
||||
[nu-fn
|
||||
(match attr
|
||||
[('predicate-fn exp) exp]
|
||||
[('predicate . C*)
|
||||
(let ([templates (get-templates C*)])
|
||||
(mk-predicate-fn (create-filter #t templates)
|
||||
(create-filter #f templates)))]
|
||||
[('predicate* true-info false-info)
|
||||
(apply
|
||||
mk-predicate-fn
|
||||
(map
|
||||
(match-lambda
|
||||
['_ #f]
|
||||
[(bool . C*)
|
||||
(let ([templates (get-templates C*)])
|
||||
(create-filter bool templates))]
|
||||
[_ (error 'predicate* "Bad syntax")])
|
||||
(list true-info false-info)))]
|
||||
[_ #f])])
|
||||
(if nu-fn
|
||||
;; compose
|
||||
(lambda (b a Tvar sign)
|
||||
(nu-fn b a
|
||||
(predicate-fn b a Tvar sign)
|
||||
sign))
|
||||
predicate-fn)))
|
||||
(lambda (b a Tvar bool) Tvar)
|
||||
attrs)
|
||||
|
||||
attrs
|
||||
orig-type-schema)))
|
||||
|
||||
; ======================================================================
|
||||
|
||||
|
@ -0,0 +1,328 @@
|
||||
;; za.ss
|
||||
;; Reads and writes .za files
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
;; ======================================================================
|
||||
;; za handling stuff
|
||||
;; ======================================================================
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; read-unit-za
|
||||
;; Returns (values ftype tref-env tdef-env tbang-env)
|
||||
|
||||
(define (read-za za)
|
||||
(let*-vals
|
||||
([(Tvar envs lookup-Tvar) (read-constraint-set za)]
|
||||
[cvt-env (match-lambda
|
||||
[(sym num) (cons sym (lookup-Tvar num))])])
|
||||
(match envs
|
||||
[('ftype sexp
|
||||
'tref-env tref-env
|
||||
'tdef-env tdef-env
|
||||
'tbang-env tbang-env)
|
||||
(values
|
||||
(recur sexp->ftype ([sexp sexp])
|
||||
;;(pretty-print `(sexp->ftype ,sexp))
|
||||
(match sexp
|
||||
[(? number? n) (lookup-Tvar n)]
|
||||
[('schema n n*)
|
||||
(create-fo-FlowType
|
||||
(make-schema (lookup-Tvar n)
|
||||
(map lookup-Tvar n*)
|
||||
'()))]
|
||||
[('atunit imports exports result)
|
||||
(create-fo-FlowType
|
||||
(make-atunit (map (match-lambda
|
||||
[(sym . n*)
|
||||
(cons sym (map lookup-Tvar n*))])
|
||||
imports)
|
||||
(map (match-lambda
|
||||
[(sym sexp)
|
||||
(cons sym (sexp->ftype sexp))])
|
||||
exports)
|
||||
(sexp->ftype result)
|
||||
#f))]
|
||||
[('atstruct A B C D E F)
|
||||
(create-fo-FlowType (make-atstruct A B C D E F))]
|
||||
[('prim sym type attrs)
|
||||
(create-fo-FlowType (apply primitive->atprim sym type attrs))]
|
||||
[x (mrspidey:internal-error 'read-za
|
||||
"Bad ftype-sexp in za: ~s" x)]))
|
||||
(map cvt-env tref-env)
|
||||
(map cvt-env tdef-env)
|
||||
(map cvt-env tbang-env))])))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; write-za
|
||||
|
||||
(define (write-za za tvar-live ftype tref-env tdef-env tbang-env)
|
||||
(write-constraint-set
|
||||
za tvar-live
|
||||
(lambda (Tvar->nu-num)
|
||||
(let ([cvt-env
|
||||
(match-lambda
|
||||
[(sym . tvar) (list sym (Tvar->nu-num tvar))])])
|
||||
(list
|
||||
'ftype
|
||||
(recur ftype->sexp ([ftype ftype])
|
||||
(pretty-debug-unit `(ftype->sexp ,(FlowType->pretty ftype)))
|
||||
(if (Tvar? ftype)
|
||||
(Tvar->nu-num ftype)
|
||||
(match (fo-FlowType-def ftype)
|
||||
[($ schema tvar tvar* '())
|
||||
(list 'schema
|
||||
(Tvar->nu-num tvar)
|
||||
(map Tvar->nu-num tvar*))]
|
||||
[($ atunit imports exports result exp)
|
||||
(list 'atunit
|
||||
(map (match-lambda
|
||||
[(sym . tvar*)
|
||||
(cons sym (map Tvar->nu-num tvar*))])
|
||||
imports)
|
||||
(map (match-lambda
|
||||
[(sym . ftype)
|
||||
(list sym (ftype->sexp ftype))])
|
||||
exports)
|
||||
(ftype->sexp result))]
|
||||
[($ atstruct A B C D E F) `(atstruct ,A ,B ,C ,D ,E ,F)]
|
||||
[($ atprim sym type _ _ attrs orig-type-schema)
|
||||
(list 'prim sym orig-type-schema attrs)]
|
||||
[x (mrspidey:internal-error 'ftype->sexp "Bad Atype ~s" x)])))
|
||||
|
||||
'tref-env (map cvt-env tref-env)
|
||||
'tdef-env (map cvt-env tdef-env)
|
||||
'tbang-env (map cvt-env tbang-env))))))
|
||||
|
||||
;; ======================================================================
|
||||
|
||||
(define (write-constraint-set file Tvar-live mk-envs)
|
||||
|
||||
(with-handlers
|
||||
([void
|
||||
(lambda (exn)
|
||||
(when (file-exists? file) (delete-file file))
|
||||
(raise exn))])
|
||||
|
||||
(let*-vals
|
||||
( [s (format "Saving ~a" (file-name-from-path file))]
|
||||
[_ (mrspidey:progress s '...)]
|
||||
[_ (when (file-exists? file) (delete-file file))]
|
||||
[p (open-output-file file 'text)]
|
||||
[disp (lambda (x) (write x p) (newline p))]
|
||||
[num-Tvar-live (length Tvar-live)]
|
||||
[(get-Tvar-ndx set-Tvar-ndx!) (alloc-Tvar-field)]
|
||||
[Tvar-ndx
|
||||
(lambda (tvar)
|
||||
(let ([ndx (get-Tvar-ndx tvar)])
|
||||
'(unless (number? ndx)
|
||||
(error 'write-constraint-set::Tvar-ndx
|
||||
"Tvar ~s not live ~s"
|
||||
(Tvar-name tvar) (map Tvar-name Tvar-live)))
|
||||
ndx))]
|
||||
[(AV-ndx set-AV-ndx!) (alloc-AV-field)]
|
||||
[num-nu-AV 0])
|
||||
|
||||
;; --- assign number to each live Tvar
|
||||
(for-each-with-n
|
||||
(lambda (Tvar n)
|
||||
(assert (eq? (Tvar-ndx Tvar) #f))
|
||||
(set-Tvar-ndx! Tvar n))
|
||||
Tvar-live)
|
||||
|
||||
;; --- write version
|
||||
(disp `(st:version ,(st:version)))
|
||||
|
||||
;; --- write configuration
|
||||
(pretty-print (mrspidey:control-fn) p)
|
||||
|
||||
;; --- write num Tvars
|
||||
(disp `(num-Tvar ,num-Tvar-live))
|
||||
|
||||
;; --- write constructor-env
|
||||
(disp `START-constructor-env)
|
||||
(hash-table-for-each
|
||||
constructor-env
|
||||
(lambda (sym template)
|
||||
(unless
|
||||
(hash-table-get saved-constructor-env sym (lambda () #f))
|
||||
(match template
|
||||
[($ template type n+ n- ref assign super-templates)
|
||||
(disp (list type n+ n- ref assign
|
||||
(map template-type super-templates)))]))))
|
||||
;; reverse it so defns in file occur before references ???
|
||||
(disp 'END-constructor-env)
|
||||
|
||||
;; --- write AV
|
||||
(disp `START-AV)
|
||||
(for-each
|
||||
(lambda (Tvar)
|
||||
;;(pretty-print (Tvar-name Tvar))
|
||||
(for-each
|
||||
(match-lambda
|
||||
[(and AV ($ AV num ($ template type) misc fields+ fields-))
|
||||
(unless (AV-ndx AV)
|
||||
(set-AV-ndx! AV num-nu-AV)
|
||||
(set! num-nu-AV (add1 num-nu-AV))
|
||||
(disp (list type
|
||||
(if (or (number? misc) (char? misc) (symbol? misc)
|
||||
(pair? misc))
|
||||
misc
|
||||
'())
|
||||
(map Tvar-ndx (vector->list fields+))
|
||||
(map Tvar-ndx (vector->list fields-)))))])
|
||||
(Tvar-objs Tvar)))
|
||||
Tvar-live)
|
||||
(disp 'END-AV)
|
||||
|
||||
;; --- write Tvar
|
||||
(disp 'START-Tvar)
|
||||
(for-each
|
||||
(lambda (Tvar)
|
||||
(disp
|
||||
(append (map AV-ndx (Tvar-objs Tvar))
|
||||
(map
|
||||
(match-lambda
|
||||
[($ con _ ($ template type) field-no Tvar sign)
|
||||
(list type field-no (Tvar-ndx Tvar) sign)]
|
||||
[($ con-filter _ ($ filter sign (($ template types) ...))
|
||||
Tvar)
|
||||
(list sign types (Tvar-ndx Tvar))])
|
||||
(Tvar-constraints Tvar))
|
||||
(let ([edgeto (Tvar-edgeto Tvar)])
|
||||
(if (null? edgeto)
|
||||
'()
|
||||
(cons 'T (map Tvar-ndx edgeto)))))))
|
||||
Tvar-live)
|
||||
(disp 'END-Tvar)
|
||||
|
||||
;; --- write in-env, out-env
|
||||
(let ([rep-envs (mk-envs Tvar-ndx)])
|
||||
(pretty-print `(envs ,@rep-envs) p)
|
||||
;; --- all done
|
||||
(close-output-port p))
|
||||
(mrspidey:progress s 'done))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (read-constraint-set file)
|
||||
(match-let*
|
||||
([p (open-input-file file 'text)]
|
||||
[('st:version save-st:version) (read p)]
|
||||
[configuration (read p)]
|
||||
[('num-Tvar save-num-Tvar) (read p)]
|
||||
[vec-Tvar (make-vector save-num-Tvar #f)]
|
||||
[vec-AV (void)]
|
||||
[lookup-Tvar
|
||||
(lambda (n)
|
||||
(if (number? n)
|
||||
(vector-ref vec-Tvar n)
|
||||
(let ([Tvar (mk-Tvar 'load-empty)])
|
||||
Tvar)))]
|
||||
[lookup-AV
|
||||
(lambda (n)
|
||||
(let ([AV (vector-ref vec-AV n)])
|
||||
(assert (AV? AV) 'lookup-AV)
|
||||
AV))])
|
||||
|
||||
(unless (equal? save-st:version (st:version))
|
||||
(mrspidey:error ".za file from previous MrSpidey release"))
|
||||
|
||||
(for i 0 save-num-Tvar (vector-set! vec-Tvar i (mk-Tvar 'load)))
|
||||
|
||||
;; --- constructors
|
||||
|
||||
(match (read p) ['START-constructor-env (void)])
|
||||
(recur loop ()
|
||||
(match (read p)
|
||||
[(type n+ n- ref assign super)
|
||||
(let ([t (make-template type n+ n- ref assign '() eqv?)])
|
||||
(for-each
|
||||
(lambda (s) (record-super-constructor-of-template! s t))
|
||||
(reverse super))
|
||||
(extend-constructor-env! t)
|
||||
(loop))]
|
||||
['END-constructor-env (void)]))
|
||||
|
||||
;; --- AV's
|
||||
|
||||
(match (read p) ['START-AV (void)])
|
||||
(set! vec-AV
|
||||
(list->vector
|
||||
(recur loop ()
|
||||
(match (read p)
|
||||
[(C misc tvar-num+* tvar-num-*)
|
||||
(cons
|
||||
(create-AV (lookup-template C)
|
||||
misc
|
||||
(list->vector (map lookup-Tvar tvar-num+*))
|
||||
(list->vector (map lookup-Tvar tvar-num-*)))
|
||||
(loop))]
|
||||
['END-AV '()]))))
|
||||
|
||||
;; --- Tvar's
|
||||
|
||||
(match (read p) ['START-Tvar (void)])
|
||||
(let ([new-AV! add-AV!]
|
||||
[new-con! add-con!]
|
||||
[new-edge! add-edge!])
|
||||
(recur loop ([n 0])
|
||||
(match (read p)
|
||||
['END-Tvar (void)]
|
||||
[in
|
||||
(let ([Tvar (lookup-Tvar n)])
|
||||
(recur loop2 ([in in])
|
||||
(match in
|
||||
[() (void)]
|
||||
[((? integer? n) . rest)
|
||||
(new-AV! Tvar (lookup-AV n))
|
||||
(loop2 rest)]
|
||||
[(((? boolean? sign) C* tvar-num) . rest)
|
||||
(new-con!
|
||||
Tvar
|
||||
(create-con-filter
|
||||
(create-filter sign (map lookup-template C*))
|
||||
(lookup-Tvar tvar-num)))
|
||||
(loop2 rest)]
|
||||
[((C n tvar-num sign) . rest)
|
||||
(new-con!
|
||||
Tvar
|
||||
(create-con
|
||||
(lookup-template C) n
|
||||
(lookup-Tvar tvar-num) sign))
|
||||
(loop2 rest)]
|
||||
[('T . edgeto*)
|
||||
(for-each
|
||||
(lambda (tvar-num)
|
||||
(new-edge! Tvar (lookup-Tvar tvar-num)))
|
||||
edgeto*)])))
|
||||
(loop (add1 n))])))
|
||||
|
||||
;; --- in-env and out-env
|
||||
|
||||
(match-let*
|
||||
([('envs . envs) (read p)])
|
||||
|
||||
(close-input-port p)
|
||||
|
||||
(values
|
||||
(vector->list vec-Tvar)
|
||||
envs
|
||||
lookup-Tvar))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
@ -0,0 +1,622 @@
|
||||
; zodiac-aux.ss
|
||||
; Helper functions for zodiac structures
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define compat
|
||||
(lambda (fn)
|
||||
(letrec
|
||||
([cl-fn
|
||||
(lambda (exp)
|
||||
;;(pretty-print-debug `(compat ,(stripper exp)))
|
||||
(let ([r (fn exp cl-fn)])
|
||||
(if r
|
||||
r
|
||||
(match exp
|
||||
[($ zodiac:if-form o s f b test then else)
|
||||
(zodiac:make-if-form o s f b
|
||||
(cl-fn test) (cl-fn then) (cl-fn else))]
|
||||
;;[($ zodiac:lambda-form o s f b args body)
|
||||
;; (let* ([args (map-ilist cl-fn args)])
|
||||
;; (zodiac:make-lambda-form o s f b args (cl-fn body)))]
|
||||
|
||||
[($ zodiac:case-lambda-form o s f b arglists bodies)
|
||||
(zodiac:make-case-lambda-form
|
||||
o s f b
|
||||
(map cl-fn arglists)
|
||||
(map cl-fn bodies))]
|
||||
[($ zodiac:arglist vars)
|
||||
(zodiac:make-arglist (map cl-fn vars))]
|
||||
[($ zodiac:set!-form o s f b var val)
|
||||
(zodiac:make-set!-form o s f b (cl-fn var) (cl-fn val))]
|
||||
[($ zodiac:begin-form o s f b bodies)
|
||||
(zodiac:make-begin-form o s f b (map cl-fn bodies))]
|
||||
[($ zodiac:let-values-form o s f b varss vals body)
|
||||
(let ([varss (map (lambda (vars) (map cl-fn vars))
|
||||
varss)])
|
||||
(zodiac:make-let-values-form
|
||||
o s f b
|
||||
varss (map cl-fn vals) (cl-fn body)))]
|
||||
[($ zodiac:letrec*-values-form o s f b varss vals body)
|
||||
(let ([varss (map (lambda (vars) (map cl-fn vars))
|
||||
varss)])
|
||||
(zodiac:make-letrec*-values-form
|
||||
o s f b
|
||||
varss (map cl-fn vals) (cl-fn body)))]
|
||||
[($ zodiac:define-values-form o s f b vars value)
|
||||
(zodiac:make-define-values-form o s f b
|
||||
(map cl-fn vars)
|
||||
(cl-fn value))]
|
||||
[($ zodiac:poly-form o s f b exp)
|
||||
(zodiac:make-poly-form o s f b (cl-fn exp))]
|
||||
|
||||
[($ zodiac:app o s f b fun args)
|
||||
(zodiac:make-app o s f b
|
||||
(cl-fn fun) (map cl-fn args))]
|
||||
;;[($ zodiac:delay-form o s f b expr)
|
||||
;; (zodiac:make-delay-form o s f b (cl-fn expr))]
|
||||
|
||||
[($ zodiac::-form o s f b exp type)
|
||||
(zodiac:make-:-form o s f b (cl-fn exp) type)]
|
||||
|
||||
[($ zodiac:type:-form o s f b type attrs)
|
||||
exp]
|
||||
|
||||
[($ zodiac:unit-form o s f b imports exports body)
|
||||
(zodiac:make-unit-form o s f b
|
||||
(map cl-fn imports)
|
||||
(map
|
||||
(match-lambda
|
||||
[(varref . sym)
|
||||
(cons (cl-fn varref) sym)])
|
||||
exports)
|
||||
(map cl-fn body))]
|
||||
[($ zodiac:compound-unit-form o s f b
|
||||
imports links exports)
|
||||
;;(pretty-print-debug `compound-unit)
|
||||
(zodiac:make-compound-unit-form
|
||||
o s f b
|
||||
(map cl-fn imports)
|
||||
(map (match-lambda
|
||||
[(tag exp . imports)
|
||||
;;(pretty-print-debug `compound-unit-link)
|
||||
(list*
|
||||
tag
|
||||
(cl-fn exp)
|
||||
(map
|
||||
(lambda (import)
|
||||
(if (zodiac:lexical-varref? import)
|
||||
(cl-fn import)
|
||||
import))
|
||||
imports))])
|
||||
links)
|
||||
exports)]
|
||||
[($ zodiac:reference-unit-form o s f b file kind signed?)
|
||||
(zodiac:make-reference-unit-form o s f b
|
||||
file kind signed?)]
|
||||
|
||||
[($ zodiac:invoke-unit-form o s f b exp vars)
|
||||
(zodiac:make-invoke-unit-form
|
||||
o s f b
|
||||
(cl-fn exp) (map cl-fn vars))]
|
||||
|
||||
;; ---------- objects! ----------
|
||||
[($ zodiac:class*/names-form o s f b
|
||||
this super-init super-expr interfaces init-vars
|
||||
inst-clauses)
|
||||
(zodiac:make-class*/names-form o s f b
|
||||
(cl-fn this)
|
||||
(cl-fn super-init)
|
||||
(cl-fn super-expr)
|
||||
interfaces
|
||||
(cl-fn init-vars)
|
||||
(map cl-fn inst-clauses))]
|
||||
[($ zodiac:public-clause exports internals exprs)
|
||||
(zodiac:make-public-clause
|
||||
exports
|
||||
(map cl-fn internals)
|
||||
(map cl-fn exprs))]
|
||||
[($ zodiac:private-clause internals exprs)
|
||||
(zodiac:make-private-clause
|
||||
(map cl-fn internals)
|
||||
(map cl-fn exprs))]
|
||||
[($ zodiac:inherit-clause internals imports)
|
||||
(zodiac:make-inherit-clause
|
||||
(map cl-fn internals) imports)]
|
||||
[($ zodiac:rename-clause internals inheriteds)
|
||||
(zodiac:make-rename-clause
|
||||
(map cl-fn internals)
|
||||
(map cl-fn inheriteds))]
|
||||
[($ zodiac:sequence-clause exprs)
|
||||
(zodiac:make-sequence-clause (map cl-fn exprs))]
|
||||
|
||||
;; ---------- sexps ----------
|
||||
[($ zodiac:list o s f l len marks)
|
||||
(zodiac:make-list o s f (map cl-fn l) len marks)]
|
||||
|
||||
[_ exp]))))])
|
||||
cl-fn)))
|
||||
|
||||
(define compat*
|
||||
(lambda (fn)
|
||||
(let ([cl-fn (compat fn)])
|
||||
(lambda (exp*) (map cl-fn exp*)))))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (ast-size defs)
|
||||
(let* ([size 0]
|
||||
[fn (lambda (x f)
|
||||
(set! size
|
||||
(+ size
|
||||
(match x
|
||||
[($ zodiac:quote-form 0 s f b expr)
|
||||
(const-size expr)]
|
||||
[_ 1])))
|
||||
#f)])
|
||||
((compat* fn) defs)
|
||||
size))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
;; const-size
|
||||
;; Gives the size of a zodiac constant
|
||||
|
||||
(define const-size
|
||||
(match-lambda
|
||||
[(a . d) (+ 1 (const-size a) (const-size d))]
|
||||
[(or ($ zodiac:list _ _ _ l) ($ zodiac:improper-list _ _ _ l))
|
||||
(const-size l)]
|
||||
[(or (? vector? v) ($ zodiac:vector _ _ _ v))
|
||||
(+ 1 (apply + (map const-size v)))]
|
||||
[else 1]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define unparse-dynamic-letd
|
||||
(lambda (fn)
|
||||
(letrec
|
||||
([cl-fn
|
||||
(lambda (exp)
|
||||
(let ([r (fn exp cl-fn)])
|
||||
(if r
|
||||
r
|
||||
(match exp
|
||||
[($ zodiac:varref _ _ _ _ sym) sym]
|
||||
[($ zodiac:binding _ _ _ _ sym) sym]
|
||||
[($ zodiac:if-form _ _ _ _ test then else)
|
||||
`(if ,(cl-fn test) ,(cl-fn then) ,(cl-fn else))]
|
||||
;;[($ zodiac:lambda-form _ _ _ _ args body)
|
||||
;; (let* ([args (map-ilist cl-fn args)])
|
||||
;; `(lambda ,args ,(cl-fn body)))]
|
||||
[($ zodiac:case-lambda-form _ _ _ _ arglists bodies)
|
||||
`(case-lambda
|
||||
,@(map
|
||||
(lambda (arglist body)
|
||||
(list (cl-fn arglist) (cl-fn body)))
|
||||
arglists bodies))]
|
||||
[($ zodiac:sym-arglist (var)) (cl-fn var)]
|
||||
[($ zodiac:list-arglist vars) (map cl-fn vars)]
|
||||
[($ zodiac:ilist-arglist vars)
|
||||
(cons (map cl-fn (rdc vars)) (cl-fn (rac vars)))]
|
||||
[($ zodiac:set!-form _ _ _ _ var val)
|
||||
`(set! ,(cl-fn var) ,(cl-fn val))]
|
||||
[($ zodiac:begin-form _ _ _ _ bodies)
|
||||
`(begin ,@(map cl-fn bodies))]
|
||||
[($ zodiac:let-values-form _ _ _ _ varss vals body)
|
||||
(let ([varss (map (lambda (vars) (map cl-fn vars))
|
||||
varss)])
|
||||
`(let-values ,(map list varss (map cl-fn vals))
|
||||
,(cl-fn body)))]
|
||||
[($ zodiac:letrec*-values-form _ _ _ _ varss vals body)
|
||||
(let ([varss (map (lambda (vars) (map cl-fn vars))
|
||||
varss)])
|
||||
`(letrec*-values ,(map list varss (map cl-fn vals))
|
||||
,(cl-fn body)))]
|
||||
[($ zodiac:define-values-form _ _ _ _ vars value)
|
||||
`(define-values ,(map cl-fn vars) ,(cl-fn value))]
|
||||
[($ zodiac:poly-form _ _ _ _ exp)
|
||||
`(poly ,(cl-fn exp))]
|
||||
[($ zodiac:app _ _ _ _ fun args)
|
||||
`(,(cl-fn fun) ,@(map cl-fn args))]
|
||||
[($ zodiac:quote-form _ _ _ _ expr)
|
||||
(list 'quote (cl-fn expr))]
|
||||
[($ zodiac::-form _ _ _ _ exp type)
|
||||
(list ': (cl-fn exp) type)]
|
||||
[($ zodiac:st:control-form o s f b para val)
|
||||
(list 'st:control para val)]
|
||||
|
||||
;; [($ zodiac:unchanged _ _ _ _ expr) (cl-fn expr)]
|
||||
[($ zodiac:unit-form o s f b imports exports body)
|
||||
`(unit (import ,@(map cl-fn imports))
|
||||
(export
|
||||
,@(map (match-lambda
|
||||
[(i . e) (list (cl-fn i) (zodiac:read-object e))])
|
||||
exports))
|
||||
,@(map cl-fn body))]
|
||||
[($ zodiac:compound-unit-form _ _ _ _
|
||||
imports links exports)
|
||||
`(compound-unit
|
||||
(import ,@(map cl-fn imports))
|
||||
(link
|
||||
,@(map
|
||||
(match-lambda
|
||||
[(tag exp . imports)
|
||||
(list tag
|
||||
(cons
|
||||
(cl-fn exp)
|
||||
(map (match-lambda
|
||||
[(tag . sym) (list tag sym)]
|
||||
[(? zodiac:varref? lvr)
|
||||
(zodiac:varref-var lvr)])
|
||||
imports)))])
|
||||
links))
|
||||
(export ,@(map
|
||||
(match-lambda
|
||||
[(tag i . e) (list tag (list i e))])
|
||||
exports)))]
|
||||
[($ zodiac:invoke-unit-form _ _ _ _ exp)
|
||||
`(invoke-unit ,(cl-fn exp))]
|
||||
[($ zodiac:reference-unit-form _ _ _ _ file kind signed?)
|
||||
(list
|
||||
(if signed?
|
||||
'reference-unit
|
||||
'reference-unit/sig)
|
||||
file)]
|
||||
[($ zodiac:struct-form _ _ _ _
|
||||
($ zodiac:symbol _ _ _ tag)
|
||||
parent
|
||||
(($ zodiac:symbol _ _ _ fields) ...))
|
||||
`(struct
|
||||
,(if parent (list tag (cl-fn parent)) tag)
|
||||
,fields)]
|
||||
[($ zodiac:string _ _ _ text) text]
|
||||
[($ zodiac:boolean _ _ _ text) text]
|
||||
[($ zodiac:char _ _ _ text) text]
|
||||
[($ zodiac:symbol _ _ _ text) text]
|
||||
[($ zodiac:number _ _ _ text) text]
|
||||
[($ zodiac:list _ _ _ contents)
|
||||
(map cl-fn contents)]
|
||||
[($ zodiac:improper-list _ _ _ contents)
|
||||
(map-ilist cl-fn contents)]
|
||||
[($ zodiac:vector _ _ _ contents)
|
||||
(list->vector (map cl-fn contents))]
|
||||
[($ zodiac:define-type-form _ _ _ _ sym type)
|
||||
`(define-type ,sym ,type)]
|
||||
[($ zodiac:define-constructor-form _ _ _ _ sym modes)
|
||||
`(define-constructor ,sym ,@modes)]
|
||||
[x x]
|
||||
;;[_ (error 'unparse "Bad exp ~s" exp)]
|
||||
))))])
|
||||
cl-fn)))
|
||||
|
||||
'(define (stripper exp)
|
||||
((unparse-dynamic-letd (lambda (x cl-fn) #f))
|
||||
exp))
|
||||
|
||||
(define (stripper exp)
|
||||
(if (zodiac:parsed? exp)
|
||||
(zodiac:parsed->raw exp)
|
||||
'stripper:not-a-parsed))
|
||||
|
||||
; ======================================================================
|
||||
;; Routines to add fields to each zodiac structure
|
||||
;; mutated and refs fields are only for binding structures
|
||||
|
||||
(define (myzodiac:register-client name init-fn)
|
||||
(let*-vals
|
||||
([(getter setter) (zodiac:register-client name init-fn)])
|
||||
(values
|
||||
(lambda (parsed) (getter (zodiac:parsed-back parsed)))
|
||||
(lambda (parsed val) (setter (zodiac:parsed-back parsed) val)))))
|
||||
|
||||
(define-values
|
||||
(parsed-ftype set-parsed-ftype!)
|
||||
(myzodiac:register-client 'ftype (lambda () #f)))
|
||||
|
||||
(define-values
|
||||
(parsed-check set-parsed-check!)
|
||||
(myzodiac:register-client 'check (lambda () #f)))
|
||||
|
||||
(define-values
|
||||
(parsed-atprim set-parsed-atprim!)
|
||||
(myzodiac:register-client 'atprim (lambda () #f)))
|
||||
|
||||
(define-values
|
||||
(app-tvar-args set-app-tvar-args!)
|
||||
(myzodiac:register-client 'app-args (lambda () #f)))
|
||||
|
||||
(define-values
|
||||
(binding-refs set-binding-refs!)
|
||||
(myzodiac:register-client 'refs (lambda () 0)))
|
||||
|
||||
(define-values
|
||||
(binding-mutated set-binding-mutated!)
|
||||
(myzodiac:register-client 'mutated (lambda () #f)))
|
||||
|
||||
;;(trace binding-mutated)
|
||||
;;(trace set-binding-mutated!)
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; Info on varrefs
|
||||
|
||||
(define (get-top-level-varref-binding x)
|
||||
(let* ( [b (zodiac:top-level-varref/bind-slot x)]
|
||||
[u (unbox b)])
|
||||
(if (zodiac:binding? u)
|
||||
u
|
||||
(let ([u (my-create-binding
|
||||
(zodiac:varref-var x)
|
||||
(zodiac:zodiac-start x)
|
||||
(zodiac:zodiac-finish x))])
|
||||
(set-box! b u)
|
||||
u))))
|
||||
|
||||
(define (varref-binding varref)
|
||||
(match varref
|
||||
[($ zodiac:bound-varref) (zodiac:bound-varref-binding varref)]
|
||||
[($ zodiac:top-level-varref/bind) (get-top-level-varref-binding varref)]
|
||||
[x (error 'varref-backinfo "Bad varref ~s" x)]))
|
||||
|
||||
(define my-create-binding
|
||||
(case-lambda
|
||||
[(name) (my-create-binding name (no-location) (no-location))]
|
||||
[(name open close)
|
||||
(zodiac:make-binding
|
||||
(zodiac:make-origin 'non-source 'spidey)
|
||||
open close (zodiac:make-empty-back-box) name name)]))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define lambda-flatten-arglist
|
||||
(match-lambda
|
||||
[($ zodiac:list _ _ _ l) l]
|
||||
[($ zodiac:improper-list _ _ _ l x) (append l (list x))]
|
||||
[(? zodiac:binding? b) (list b)]
|
||||
[() '()]
|
||||
[(a . b) (cons a (lambda-flatten-arglist b))]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define (no-location) (zodiac:make-location 0 0 0 "no-file"))
|
||||
|
||||
(define (location-inc loc)
|
||||
(zodiac:make-location
|
||||
0 0
|
||||
(add1 (zodiac:location-offset loc))
|
||||
(zodiac:location-file loc)))
|
||||
|
||||
(define determine-end-first-token
|
||||
(lambda (object)
|
||||
(cond
|
||||
[(or (zodiac:scalar? object)
|
||||
(zodiac:varref? object)
|
||||
(zodiac:binding? object)
|
||||
(and (zodiac:quote-form? object)
|
||||
(or
|
||||
(zodiac:boolean? (zodiac:quote-form-expr object))
|
||||
(zodiac:char? (zodiac:quote-form-expr object))
|
||||
(zodiac:symbol? (zodiac:quote-form-expr object))
|
||||
(zodiac:number? (zodiac:quote-form-expr object)))))
|
||||
(location-inc (zodiac:zodiac-finish object))]
|
||||
[(or (zodiac:sequence? object)
|
||||
(zodiac:parsed? object)
|
||||
(zodiac:app? object))
|
||||
(location-inc (zodiac:zodiac-start object))]
|
||||
[else (error 'zodiac:determine-end-first-token
|
||||
"shouldn't be here ~s" object)])))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define parsed-value?
|
||||
(match-lambda
|
||||
[(or
|
||||
($ zodiac:quote-form)
|
||||
;;($ zodiac:lambda-form)
|
||||
($ zodiac:case-lambda-form)
|
||||
($ zodiac:lexical-varref)) #t]
|
||||
[($ zodiac:letrec*-values-form
|
||||
_ _ _ _ vars
|
||||
((? parsed-value?) ...)
|
||||
(? parsed-value?)) #t]
|
||||
[_ #t]))
|
||||
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define free-refs
|
||||
(lambda (exp bindings)
|
||||
(let* ( [hash-bindings (make-hash-table)]
|
||||
[_ (for-each
|
||||
(lambda (bind) (hash-table-put! hash-bindings bind #t))
|
||||
bindings)]
|
||||
[refs '()]
|
||||
[fn
|
||||
(lambda (exp cl-fn)
|
||||
(match exp
|
||||
[($ zodiac:varref)
|
||||
(let ([bind (varref-binding exp)])
|
||||
(when
|
||||
(hash-table-get hash-bindings bind (lambda () #f))
|
||||
(set! refs (cons bind refs))))
|
||||
#f]
|
||||
[($ zodiac:unit-form) 'do-not-traverse]
|
||||
[_ #f]))])
|
||||
((compat fn) exp)
|
||||
refs)))
|
||||
|
||||
(define (free-vars exp bindings) (list->set (free-refs exp bindings)))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (initialize-mutated defs)
|
||||
(let* (;; set binding of mutated variables
|
||||
[_ (for-each
|
||||
(match-lambda
|
||||
[($ zodiac:define-values-form _ _ _ _ varrefs expr)
|
||||
(match expr
|
||||
;; kludge - don't consider define-struct variables
|
||||
;; to be mutable
|
||||
[($ zodiac:struct-form) (void)]
|
||||
[_
|
||||
(for-each
|
||||
(lambda (varref)
|
||||
(set-binding-mutated!
|
||||
(get-top-level-varref-binding varref)
|
||||
#t))
|
||||
varrefs)])]
|
||||
[_ (void)])
|
||||
defs)]
|
||||
[free '()]
|
||||
[fn
|
||||
(lambda (def cl-fn)
|
||||
;;(display `(initialize-mutated ,(stripper def))) (newline)
|
||||
(match def
|
||||
[($ zodiac:letrec*-values-form _ _ _ _ varss)
|
||||
(for-each
|
||||
(lambda (vars)
|
||||
(for-each
|
||||
(lambda (var) (set-binding-mutated! var #t))
|
||||
vars))
|
||||
varss)
|
||||
#f]
|
||||
[($ zodiac:set!-form _ _ _ _ var)
|
||||
;;(display `(initialize-mutated! ,(stripper var))) (newline)
|
||||
(set-binding-mutated! (varref-binding var) #t)
|
||||
#f]
|
||||
[_ #f]))])
|
||||
((compat* fn) defs)
|
||||
free))
|
||||
|
||||
(define (free-vars-defs defs)
|
||||
(let* ( ;; Put binding on slot field of variables that are defined
|
||||
;; and set to mutated
|
||||
[_ (for-each
|
||||
(match-lambda
|
||||
[($ zodiac:define-values-form _ _ _ _ varrefs expr)
|
||||
(match expr
|
||||
;; kludge - don't consider define-struct variables
|
||||
;; to be mutable
|
||||
[($ zodiac:struct-form)
|
||||
(for-each
|
||||
(lambda (varref)
|
||||
(get-top-level-varref-binding varref))
|
||||
varrefs)]
|
||||
[_
|
||||
(for-each
|
||||
(lambda (varref)
|
||||
(set-binding-mutated!
|
||||
(get-top-level-varref-binding varref)
|
||||
#t))
|
||||
varrefs)])]
|
||||
[_ (void)])
|
||||
defs)]
|
||||
[free '()]
|
||||
[fn
|
||||
(lambda (def cl-fn)
|
||||
;;(pretty-debug `(get-tlvr ,(stripper def)))
|
||||
(match def
|
||||
[($ zodiac:top-level-varref/bind)
|
||||
(when
|
||||
(not
|
||||
(zodiac:binding?
|
||||
(unbox (zodiac:top-level-varref/bind-slot def))))
|
||||
(set! free
|
||||
(cons (get-top-level-varref-binding def) free)))
|
||||
#f]
|
||||
[($ zodiac:unit-form) 'do-not-traverse]
|
||||
[($ zodiac:letrec*-values-form _ _ _ _ varss)
|
||||
(for-each
|
||||
(lambda (vars)
|
||||
(for-each
|
||||
(lambda (var) (set-binding-mutated! var #t))
|
||||
vars))
|
||||
varss)
|
||||
#f]
|
||||
;; struct-ref in function posn is not a free variable
|
||||
[($ zodiac:app _ _ _ _
|
||||
($ zodiac:top-level-varref/bind _ _ _ _ 'struct-ref)
|
||||
args)
|
||||
(for-each cl-fn args)
|
||||
#t]
|
||||
[_ #f]))])
|
||||
((compat* fn) defs)
|
||||
free))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (zero! p)
|
||||
'(let-macro
|
||||
zerostruct
|
||||
(lambda (name . fields)
|
||||
`(begin
|
||||
;;(display ',(symbol-append 'zodiac: name))
|
||||
(when (,(symbol-append 'zodiac: name '?) p)
|
||||
,@(map
|
||||
(lambda (field)
|
||||
`(begin
|
||||
;;(display ',(symbol-append 'zodiac: name '- field))
|
||||
(zero!
|
||||
(begin0
|
||||
(,(symbol-append 'zodiac: name '- field) p)
|
||||
(,(symbol-append 'zodiac:set- name '- field '!) p 'zro)))))
|
||||
fields))))
|
||||
|
||||
(zerostruct parsed back)
|
||||
(zerostruct app fun args)
|
||||
(zerostruct varref var)
|
||||
(zerostruct bound-varref binding)
|
||||
(zerostruct binding var orig-name)
|
||||
(zerostruct top-level-varref/bind slot)
|
||||
(zerostruct arglist vars)
|
||||
(zerostruct paroptarglist vars)
|
||||
(zerostruct set!-form var val)
|
||||
(zerostruct begin-form bodies)
|
||||
(zerostruct begin0-form bodies)
|
||||
(zerostruct define-values-form vars val)
|
||||
(zerostruct let-values-form vars vals body)
|
||||
(zerostruct letrec*-values-form vars vals body)
|
||||
(zerostruct if-form test then else)
|
||||
(zerostruct quote-form expr)
|
||||
(zerostruct case-lambda-form args bodies)
|
||||
(zerostruct struct-form type super fields)
|
||||
(zerostruct unit-form imports exports clauses)
|
||||
(zerostruct compound-unit-form imports links exports)
|
||||
(zerostruct invoke-unit-form unit variables)
|
||||
(zerostruct invoke-open-unit-form unit name-specifier variables)
|
||||
(zerostruct class*-form this super-names super-exprs init-vars inst-clauses)
|
||||
(zerostruct public-clause exports internals exprs)
|
||||
(zerostruct private-clause internals exprs)
|
||||
(zerostruct inherit-clause internals imports)
|
||||
(zerostruct rename-clause internals imports)
|
||||
(zerostruct sequence-clause exprs)
|
||||
(when (pair? p)
|
||||
(zero! (begin0 (car p) (set-car! p 'zro)))
|
||||
(zero! (begin0 (cdr p) (set-cdr! p 'zro))))
|
||||
|
||||
))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define (inline-begins defs)
|
||||
(recur loop ([defs defs])
|
||||
(match defs
|
||||
[() '()]
|
||||
[(($ zodiac:begin-form _ _ _ _ bodies) . rest)
|
||||
(append (loop bodies) (loop rest))]
|
||||
[(def . rest)
|
||||
(cons def (loop rest))])))
|
||||
|
@ -0,0 +1,75 @@
|
||||
; zod-extra.ss
|
||||
; ----------------------------------------------------------------------
|
||||
; Copyright (C) 1995-97 Cormac Flanagan
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
; ----------------------------------------------------------------------
|
||||
|
||||
(define mrspidey:zodiac:parameters@
|
||||
(unit/sig plt:parameters^
|
||||
(import)
|
||||
(define case-sensitive? #t)
|
||||
(define unmatched-cond/case-is-error? #t)
|
||||
(define allow-set!-on-undefined? #t)
|
||||
(define allow-improper-lists? #t)
|
||||
(define check-syntax-level 'advanced)
|
||||
;(define allow-internal-defines? #f)
|
||||
))
|
||||
|
||||
(define mrspidey:zodiac:interface@
|
||||
(unit/sig zodiac:interface^
|
||||
(import mrspidey:interaction^)
|
||||
(define default-error-handler
|
||||
(lambda (keyword)
|
||||
(lambda (where fmt-spec . args)
|
||||
(apply mrspidey:internal-error
|
||||
keyword fmt-spec args))))
|
||||
(define internal-error
|
||||
(lambda (where fmt-spec . args)
|
||||
(let ([msg
|
||||
(parameterize ([print-struct #t])
|
||||
(string-append "Syntax error: "
|
||||
(apply format fmt-spec args)))])
|
||||
(if #t ;(zodiac:zodiac? where)
|
||||
(mrspidey:error msg where)
|
||||
(mrspidey:error msg)))))
|
||||
(define static-error
|
||||
(lambda (where fmt-spec . args)
|
||||
(let ([msg
|
||||
(parameterize ([print-struct #t])
|
||||
(string-append "Syntax error: "
|
||||
(apply format fmt-spec args)))])
|
||||
(if #t ;(zodiac:zodiac? where)
|
||||
(mrspidey:error msg where)
|
||||
(mrspidey:error msg)))))
|
||||
(define dynamic-error
|
||||
(default-error-handler 'zodiac-run-time))))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define mrspidey:zodiac-aux@
|
||||
(unit/sig
|
||||
mrspidey:zodiac-aux^
|
||||
(import
|
||||
mrspidey:CDL^
|
||||
(zodiac : zodiac:system^))
|
||||
(include "zod-aux.ss")))
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(load-relative "zod-link.ss")
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
;; zod-link.ss
|
||||
|
||||
(define mrspidey:zodiac@;; mrspidey:zodiac^
|
||||
(compound-unit/sig
|
||||
(import
|
||||
(CDL : mrspidey:CDL^)
|
||||
(INTERACTION : mrspidey:interaction^))
|
||||
(link
|
||||
[PARAMETERS :
|
||||
plt:parameters^
|
||||
(mrspidey:zodiac:parameters@)]
|
||||
[INTERFACE :
|
||||
zodiac:interface^
|
||||
(mrspidey:zodiac:interface@ INTERACTION)]
|
||||
[Z :
|
||||
zodiac:system^
|
||||
(zodiac:system@ INTERFACE PARAMETERS (CORE pretty-print@) (CORE file@))]
|
||||
[CORE :
|
||||
mzlib:core^
|
||||
((reference-library-unit/sig "corer.ss"))]
|
||||
[AUX : mrspidey:zodiac-aux^ (mrspidey:zodiac-aux@ CDL Z)])
|
||||
(export (open Z) (open AUX))))
|
@ -0,0 +1,36 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>About MrSpidey</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<body>
|
||||
<H1>
|
||||
<img align=left src="logo.gif" border=0 alt="[logo]">
|
||||
MrSpidey</H1>
|
||||
<P>
|
||||
MrSpidey version 49s1, Copyright (C) 1995-97 Cormac Flanagan
|
||||
<p>
|
||||
MrSpidey is an interactive, graphical static debugger for Scheme. For more information, visit the
|
||||
<A HREF="http://www.cs.rice.edu/CS/PLT/packages/mrspidey/index.html"> MrSpidey home page</A>
|
||||
<P>
|
||||
Thanks to Matthew Flatt and Robby Findler for MrEd, and to Shriram
|
||||
Krishnamurthi for his source-correlating macro-expander. Thanks also
|
||||
to Stephanie Weirich for work on the first implementation of MrSpidey,
|
||||
and to Matthias Felleisen and Corky Cartwright for their feedback and
|
||||
help.
|
||||
<p>
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
<p>
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
<p>
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
</body>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue