MrEd_100.txt

original commit: 4a325ca403f0a0dac339262d6fedcf42170d56b9
This commit is contained in:
Matthew Flatt 1999-11-20 23:16:58 +00:00
parent 22f8c90ed0
commit 4ed8787871
1025 changed files with 351999 additions and 1 deletions

Binary file not shown.

1380
collects/mysterx/doc.txt Normal file

File diff suppressed because it is too large Load Diff

27
collects/mysterx/info.ss Normal file
View File

@ -0,0 +1,27 @@
;; info.ss for mysterx collection
(lambda (request failure-thunk)
(case request
[(name) "MysterX"]
[(compile-prefix)
(if (not (eq? (system-type) 'windows))
(begin
(fprintf (current-error-port)
"Error: can't install MysterX on non-Windows machine~n")
(failure-thunk))
`(begin
(current-require-relative-collection (list "mysterx"))
(require-library "macro.ss")
(require-library "cores.ss")
(require-relative-library "mysterxu.ss")
(let ([winsys-dir (find-system-path 'sys-dir)])
(if winsys-dir
(for-each
(lambda (dll)
(system
(format "~a\\REGSVR32 \"~a\\dlls\\~a\""
winsys-dir (current-directory) dll)))
'(myspage.dll myssink.dll))
(fprintf (current-error-port)
"Warning: Can't run REGSVR32 on libraries~n")))))]
[else (failure-thunk)]))

182
collects/mysterx/mxdemo.ss Normal file
View File

@ -0,0 +1,182 @@
;;; mxdemo.ss -- demo program for MysterX
;;; requires Office 97 to be installed for Calendar Control to work
(require-library "mysterx.ss" "mysterx")
; the document with the calendar
(define caldoc (make-object mx-document% "Demo or die!" 350 400 100 100 '()))
(send caldoc insert-html
(string-append
"<H1 id=\"mx-header\">MysterX Demo</H1>"
"<p>"
"<hr>"
"<p>"
(coclass->html "Calendar Control 8.0" 300 200)
"<p>"
"<H3 id=\"event-header\"></H3>"))
(define cal (car (send caldoc objects)))
; the control panel document
(define ctrldoc (make-object mx-document% "Control Panel" 180 350 600 300 '()))
(send ctrldoc insert-html
(string-append
"<table align = center>"
"<caption id=\"Caption\"><b>Keypress here</b></caption>"
"<colgroup align=left>"
"<colgroup align=center>"
"<colgroup align=right>"
"<tr>"
"<td><BUTTON id=\"Yesterday\" style=\"color: blue\">&LT----</BUTTON></td>"
"<td><b>Day</b></td>"
"<td><BUTTON id=\"Tomorrow\" style=\"color: red\">----&GT</BUTTON></td>"
"</tr>"
"<tr>"
"<td><BUTTON id=\"Last-month\" style=\"color: green\">&LT----</BUTTON></td>"
"<td><b>Month</b></td>"
"<td><BUTTON id=\"Next-month\" style=\"color: indigo\">----&GT</BUTTON></td>"
"</tr>"
"<tr>"
"<td><BUTTON id=\"Last-year\" style=\"color: yellow\">&LT----</BUTTON></td>"
"<td><b>Year</b></td>"
"<td><BUTTON id=\"Next-year\" style=\"color: purple\">----&GT</BUTTON></td>"
"</tr>"
"</table>"
"<table align=center>"
"<td><BUTTON id=\"Today\">Today</BUTTON></td>"
"</table>"
"<hr>"
"<table align=center>"
"<tr>"
"<td><BUTTON id=\"Hide\">Hide</BUTTON></td>"
"<td><BUTTON id=\"Show\">Show</BUTTON></td>"
"</tr>"
"</table>"
"<table align=center>"
"<td><BUTTON id=\"Rub-me\">Rub me!</BUTTON></td>"
"</table>"
"<table align=center>"
"<td><BUTTON id=\"About\">About</BUTTON></td>"
"</table>"
"<p>"
"<table align=center>"
"<td id=\"event-reflector\">Click on the calendar</td>"
"</table>"))
(define reflector (send ctrldoc find-element "TD" "event-reflector"))
(com-register-event-handler
cal "Click"
(lambda ()
(send reflector set-color! "white")
(send reflector set-background-color! "blue")
(thread
(lambda ()
(sleep 0.25)
(send reflector set-color! "black")
(send reflector set-background-color! "white")))))
(define (about-handler ev)
(when (send ev click?)
(com-invoke cal "AboutBox")))
(define (hide-handler ev)
(when (send ev click?)
(send caldoc show #f)))
(define (show-handler ev)
(when (send ev click?)
(send caldoc show #t)))
(define rub-me-handler
(let ([count 0])
(lambda (ev)
(when (send ev mousemove?)
(printf "mousemove #~a, but who's counting?~n" count)
(set! count (add1 count))))))
(define (today-handler ev)
(when (send ev click?)
(com-invoke cal "Today")))
(define (yesterday-handler ev)
(when (send ev click?)
(com-invoke cal "PreviousDay")))
(define (tomorrow-handler ev)
(when (send ev click?)
(com-invoke cal "NextDay")))
(define (last-month-handler ev)
(when (send ev click?)
(com-invoke cal "PreviousMonth")))
(define (next-month-handler ev)
(when (send ev click?)
(com-invoke cal "NextMonth")))
(define (last-year-handler ev)
(when (send ev click?)
(com-invoke cal "PreviousYear")))
(define (next-year-handler ev)
(when (send ev click?)
(com-invoke cal "NextYear")))
(define button-handlers
`(("About" ,about-handler)
("Hide" ,hide-handler)
("Show" ,show-handler)
("Rub-me" ,rub-me-handler)
("Today" ,today-handler)
("Yesterday" ,yesterday-handler)
("Tomorrow" ,tomorrow-handler)
("Last-month" ,last-month-handler)
("Next-month" ,next-month-handler)
("Last-year" ,last-year-handler)
("Next-year" ,next-year-handler)))
(send ctrldoc register-event-handler
(send ctrldoc find-element "CAPTION" "Caption")
(lambda (ev)
(when (send ev keypress?)
(printf "ooh that tickles~n"))))
(for-each
(lambda (sym-handler)
(send ctrldoc register-event-handler
(send ctrldoc find-element
"BUTTON" ; tag
(car sym-handler)) ; id
(cadr sym-handler))) ; handler
button-handlers)
(send ctrldoc handle-events)

View File

@ -0,0 +1,7 @@
;; mysterx.ss
(require-library "mysterxu.ss" "mysterx")
(define-values/invoke-unit/sig
mysterx:mysterx^
mysterx@)

View File

@ -0,0 +1,862 @@
;; mysterxe.ss
(require-library "xml.ss" "xml")
(unit/sig mysterx:mysterx^
(import
mzlib:function^
mzlib:string^
[mxprims : mysterx:prims^]
[xml : xml^])
(define com-invoke mxprims:com-invoke)
(define com-set-property! mxprims:com-set-property!)
(define com-get-property mxprims:com-get-property)
(define com-methods mxprims:com-methods)
(define com-get-properties mxprims:com-get-properties)
(define com-set-properties mxprims:com-set-properties)
(define com-events mxprims:com-events)
(define com-method-type mxprims:com-method-type)
(define com-get-property-type mxprims:com-get-property-type)
(define com-set-property-type mxprims:com-set-property-type)
(define com-event-type mxprims:com-event-type)
(define com-object-type mxprims:com-object-type)
(define com-is-a? mxprims:com-is-a?)
(define com-help mxprims:com-help)
(define com-register-event-handler mxprims:com-register-event-handler)
(define com-unregister-event-handler mxprims:com-unregister-event-handler)
(define com-all-coclasses mxprims:com-all-coclasses)
(define com-all-controls mxprims:com-all-controls)
(define coclass->html mxprims:coclass->html)
(define cocreate-instance mxprims:cocreate-instance)
(define com-object-eq? mxprims:com-object-eq?)
(define com-object? mxprims:com-object?)
(define com-omit mxprims:com-omit)
(define html-sem (make-semaphore 1)) ; protects HTML insertions
(define html-wait (lambda () (semaphore-wait html-sem)))
(define html-post (lambda () (semaphore-post html-sem)))
(define (xexp->string xexp)
(lambda (xexp)
(parameterize ([xml:empty-tag-shorthand #f])
(let* ([port (open-output-string)]
[xml (xml:xexpr->xml xexp)])
(xml:write-xml/content xml port)
(get-output-string port)))))
(define mx-element%
(class object% (document dhtml-element)
(private
[elt dhtml-element]
[doc document])
(public
[insert-html
(lambda (s)
(dynamic-wind
html-wait
(lambda () (mxprims:element-insert-html elt s))
html-post))]
[append-html
(lambda (s)
(dynamic-wind
html-wait
(lambda () (mxprims:element-append-html elt s))
html-post))]
[replace-html
(lambda (s)
(dynamic-wind
html-wait
(lambda () (mxprims:element-replace-html elt s))
html-post))]
[insert-text
(lambda (s)
(mxprims:element-insert-text elt s))]
[append-text
(lambda (s)
(mxprims:element-append-text elt s))]
[insert-object
(opt-lambda (object width height [size 'pixels])
(dynamic-wind
html-wait
(lambda ()
(let ([old-objects (mxprims:document-objects doc)])
(mxprims:element-insert-html
elt
(coclass->html object width height size))
(let* ([new-objects (mxprims:document-objects doc)]
[obj (car (remove* old-objects new-objects
com-object-eq?))])
(mxprims:com-register-object obj)
obj)))
html-post))]
[append-object
(opt-lambda (object width height [size 'pixels])
(dynamic-wind
html-wait
(lambda ()
(let* ([old-objects (mxprims:document-objects doc)])
(mxprims:element-append-html
elt
(coclass->html object width height size))
(let* ([new-objects (mxprims:document-objects doc)]
[obj (car (remove* old-objects
new-objects
com-object-eq?))])
(mxprims:com-register-object obj)
obj)))
html-post))]
[attribute
(lambda (s)
(mxprims:element-attribute elt s))]
[set-attribute!
(lambda (a v)
(mxprims:element-set-attribute! elt a v))]
[click
(lambda ()
(mxprims:element-click elt))]
[tag
(lambda ()
(mxprims:element-tag elt))]
[font-family
(lambda ()
(mxprims:element-font-family elt))]
[set-font-family!
(lambda (s)
(mxprims:element-set-font-family! elt s))]
[font-style
(lambda ()
(mxprims:element-font-style elt))]
[set-font-style!
(lambda (s)
(mxprims:element-set-font-style! elt s))]
[font-variant
(lambda ()
(mxprims:element-font-variant elt))]
[set-font-variant!
(lambda (s)
(mxprims:element-set-font-variant! elt s))]
[font-weight
(lambda ()
(mxprims:element-font-weight elt))]
[set-font-weight!
(lambda (s)
(mxprims:element-set-font-weight! elt s))]
[font
(lambda ()
(mxprims:element-font elt))]
[set-font!
(lambda (s)
(mxprims:element-set-font! elt s))]
[background
(lambda ()
(mxprims:element-background elt))]
[set-background!
(lambda (s)
(mxprims:element-set-background! elt s))]
[background-image
(lambda ()
(mxprims:element-background-image elt))]
[set-background-image!
(lambda (s)
(mxprims:element-set-background-image! elt s))]
[background-repeat
(lambda ()
(mxprims:element-background-repeat elt))]
[set-background-repeat!
(lambda (s)
(mxprims:element-set-background-repeat! elt s))]
[background-position
(lambda ()
(mxprims:element-background-position elt))]
[set-background-position!
(lambda (s)
(mxprims:element-set-background-position! elt s))]
[text-decoration
(lambda ()
(mxprims:element-text-decoration elt))]
[set-text-decoration!
(lambda (s)
(mxprims:element-set-text-decoration! elt s))]
[text-transform
(lambda ()
(mxprims:element-text-transform elt))]
[set-text-transform!
(lambda (s)
(mxprims:element-set-text-transform! elt s))]
[text-align
(lambda ()
(mxprims:element-text-align elt))]
[set-text-align!
(lambda (s)
(mxprims:element-set-text-align! elt s))]
[margin
(lambda ()
(mxprims:element-margin elt))]
[set-margin!
(lambda (s)
(mxprims:element-set-margin! elt s))]
[padding
(lambda ()
(mxprims:element-padding elt))]
[set-padding!
(lambda (s)
(mxprims:element-set-padding! elt s))]
[border
(lambda ()
(mxprims:element-border elt))]
[set-border!
(lambda (s)
(mxprims:element-set-border! elt s))]
[border-top
(lambda ()
(mxprims:element-border-top elt))]
[set-border-top!
(lambda (s)
(mxprims:element-set-border-top! elt s))]
[border-bottom
(lambda ()
(mxprims:element-border-bottom elt))]
[set-border-bottom!
(lambda (s)
(mxprims:element-set-border-bottom! elt s))]
[border-left
(lambda ()
(mxprims:element-border-left elt))]
[set-border-left!
(lambda (s)
(mxprims:element-set-border-left! elt s))]
[border-right
(lambda ()
(mxprims:element-border-right elt))]
[set-border-right!
(lambda (s)
(mxprims:element-set-border-right! elt s))]
[border-color
(lambda ()
(mxprims:element-border-color elt))]
[set-border-color!
(lambda (s)
(mxprims:element-set-border-color! elt s))]
[border-width
(lambda ()
(mxprims:element-border-width elt))]
[set-border-width!
(lambda (s)
(mxprims:element-set-border-width! elt s))]
[border-style
(lambda ()
(mxprims:element-border-style elt))]
[set-border-style!
(lambda (s)
(mxprims:element-set-border-style! elt s))]
[border-top-style
(lambda ()
(mxprims:element-border-top-style elt))]
[set-border-top-style!
(lambda (s)
(mxprims:element-set-border-top-style! elt s))]
[border-bottom-style
(lambda ()
(mxprims:element-border-bottom-style elt))]
[set-border-bottom-style!
(lambda (s)
(mxprims:element-set-border-bottom-style! elt s))]
[border-left-style
(lambda ()
(mxprims:element-border-left-style elt))]
[set-border-left-style!
(lambda (s)
(mxprims:element-set-border-left-style! elt s))]
[border-right-style
(lambda ()
(mxprims:element-border-right-style elt))]
[set-border-right-style!
(lambda (s)
(mxprims:element-set-border-right-style! elt s))]
[style-float
(lambda ()
(mxprims:element-style-float elt))]
[set-style-float!
(lambda (s)
(mxprims:element-set-style-float! elt s))]
[clear
(lambda ()
(mxprims:element-clear elt))]
[set-clear!
(lambda (s)
(mxprims:element-set-clear! elt s))]
[display
(lambda ()
(mxprims:element-display elt))]
[set-display!
(lambda (s)
(mxprims:element-set-display! elt s))]
[visibility
(lambda ()
(mxprims:element-visibility elt))]
[set-visibility!
(lambda (s)
(mxprims:element-set-visibility! elt s))]
[list-style-type
(lambda ()
(mxprims:element-list-style-type elt))]
[set-list-style-type!
(lambda (s)
(mxprims:element-set-list-style-type! elt s))]
[list-style-position
(lambda ()
(mxprims:element-list-style-position elt))]
[set-list-style-position!
(lambda (s)
(mxprims:element-set-list-style-position! elt s))]
[list-style-image
(lambda ()
(mxprims:element-list-style-image elt))]
[set-list-style-image!
(lambda (s)
(mxprims:element-set-list-style-image! elt s))]
[list-style
(lambda ()
(mxprims:element-list-style elt))]
[set-list-style!
(lambda (s)
(mxprims:element-set-list-style! elt s))]
[whitespace
(lambda ()
(mxprims:element-whitespace elt))]
[set-whitespace!
(lambda (s)
(mxprims:element-set-whitespace! elt s))]
[position
(lambda ()
(mxprims:element-position elt))]
[overflow
(lambda ()
(mxprims:element-overflow elt))]
[set-overflow!
(lambda (s)
(mxprims:element-set-overflow! elt s))]
[pagebreak-before
(lambda ()
(mxprims:element-pagebreak-before elt))]
[set-pagebreak-before!
(lambda (s)
(mxprims:element-set-pagebreak-before! elt s))]
[pagebreak-after
(lambda ()
(mxprims:element-pagebreak-after elt))]
[set-pagebreak-after!
(lambda (s)
(mxprims:element-set-pagebreak-after! elt s))]
[css-text
(lambda ()
(mxprims:element-css-text elt))]
[set-css-text!
(lambda (s)
(mxprims:element-set-css-text! elt s))]
[cursor
(lambda ()
(mxprims:element-cursor elt))]
[set-cursor!
(lambda (s)
(mxprims:element-set-cursor! elt s))]
[clip
(lambda ()
(mxprims:element-clip elt))]
[set-clip!
(lambda (s)
(mxprims:element-set-clip! elt s))]
[filter
(lambda ()
(mxprims:element-filter elt))]
[set-filter!
(lambda (s)
(mxprims:element-set-filter! elt s))]
[style-string
(lambda ()
(mxprims:element-style-string elt))]
[text-decoration-none
(lambda ()
(mxprims:element-text-decoration-none elt))]
[set-text-decoration-none!
(lambda (s)
(mxprims:element-set-text-decoration-none! elt s))]
[text-decoration-underline
(lambda ()
(mxprims:element-text-decoration-underline elt))]
[set-text-decoration-underline!
(lambda (s)
(mxprims:element-set-text-decoration-underline! elt s))]
[text-decoration-overline
(lambda ()
(mxprims:element-text-decoration-overline elt))]
[set-text-decoration-overline!
(lambda (s)
(mxprims:element-set-text-decoration-overline! elt s))]
[text-decoration-linethrough
(lambda ()
(mxprims:element-text-decoration-linethrough elt))]
[set-text-decoration-linethrough!
(lambda (s)
(mxprims:element-set-text-decoration-linethrough! elt s))]
[text-decoration-blink
(lambda ()
(mxprims:element-text-decoration-blink elt))]
[set-text-decoration-blink!
(lambda (s)
(mxprims:element-set-text-decoration-blink! elt s))]
[pixel-top
(lambda ()
(mxprims:element-pixel-top elt))]
[set-pixel-top!
(lambda (s)
(mxprims:element-set-pixel-top! elt s))]
[pixel-left
(lambda ()
(mxprims:element-pixel-left elt))]
[set-pixel-left!
(lambda (s)
(mxprims:element-set-pixel-left! elt s))]
[pixel-width
(lambda ()
(mxprims:element-pixel-width elt))]
[set-pixel-width!
(lambda (s)
(mxprims:element-set-pixel-width! elt s))]
[pixel-height
(lambda ()
(mxprims:element-pixel-height elt))]
[set-pixel-height!
(lambda (s)
(mxprims:element-set-pixel-height! elt s))]
[pos-top
(lambda ()
(mxprims:element-pos-top elt))]
[set-pos-top!
(lambda (s)
(mxprims:element-set-pos-top! elt s))]
[pos-left
(lambda ()
(mxprims:element-pos-left elt))]
[set-pos-left!
(lambda (s)
(mxprims:element-set-pos-left! elt s))]
[pos-width
(lambda ()
(mxprims:element-pos-width elt))]
[set-pos-width!
(lambda (s)
(mxprims:element-set-pos-width! elt s))]
[pos-height
(lambda ()
(mxprims:element-pos-height elt))]
[set-pos-height!
(lambda (s)
(mxprims:element-set-pos-height! elt s))]
[font-size
(lambda ()
(mxprims:element-font-size elt))]
[set-font-size!
(lambda (s)
(mxprims:element-set-font-size! elt s))]
[color
(lambda ()
(mxprims:element-color elt))]
[set-color!
(lambda (s)
(mxprims:element-set-color! elt s))]
[background-color
(lambda ()
(mxprims:element-background-color elt))]
[set-background-color!
(lambda (s)
(mxprims:element-set-background-color! elt s))]
[background-position-x
(lambda ()
(mxprims:element-background-position-x elt))]
[set-background-position-x!
(lambda (s)
(mxprims:element-set-background-position-x! elt s))]
[background-position-y
(lambda ()
(mxprims:element-background-position-y elt))]
[set-background-position-y!
(lambda (s)
(mxprims:element-set-background-position-y! elt s))]
[word-spacing
(lambda ()
(mxprims:element-word-spacing elt))]
[set-word-spacing!
(lambda (s)
(mxprims:element-set-word-spacing! elt s))]
[letter-spacing
(lambda ()
(mxprims:element-letter-spacing elt))]
[set-letter-spacing!
(lambda (s)
(mxprims:element-set-letter-spacing! elt s))]
[vertical-align
(lambda ()
(mxprims:element-vertical-align elt))]
[set-vertical-align!
(lambda (s)
(mxprims:element-set-vertical-align! elt s))]
[text-indent
(lambda ()
(mxprims:element-text-indent elt))]
[set-text-indent!
(lambda (s)
(mxprims:element-set-text-indent! elt s))]
[line-height
(lambda ()
(mxprims:element-line-height elt))]
[set-line-height!
(lambda (s)
(mxprims:element-set-line-height! elt s))]
[margin-top
(lambda ()
(mxprims:element-margin-top elt))]
[set-margin-top!
(lambda (s)
(mxprims:element-set-margin-top! elt s))]
[margin-bottom
(lambda ()
(mxprims:element-margin-bottom elt))]
[set-margin-bottom!
(lambda (s)
(mxprims:element-set-margin-bottom! elt s))]
[margin-left
(lambda ()
(mxprims:element-margin-left elt))]
[set-margin-left!
(lambda (s)
(mxprims:element-set-margin-left! elt s))]
[margin-right
(lambda ()
(mxprims:element-margin-right elt))]
[set-margin-right!
(lambda (s)
(mxprims:element-set-margin-right! elt s))]
[padding-top
(lambda ()
(mxprims:element-padding-top elt))]
[set-padding-top!
(lambda (s)
(mxprims:element-set-padding-top! elt s))]
[padding-bottom
(lambda ()
(mxprims:element-padding-bottom elt))]
[set-padding-bottom!
(lambda (s)
(mxprims:element-set-padding-bottom! elt s))]
[padding-left
(lambda ()
(mxprims:element-padding-left elt))]
[set-padding-left!
(lambda (s)
(mxprims:element-set-padding-left! elt s))]
[padding-right
(lambda ()
(mxprims:element-padding-right elt))]
[set-padding-right!
(lambda (s)
(mxprims:element-set-padding-right! elt s))]
[border-top-color
(lambda ()
(mxprims:element-border-top-color elt))]
[set-border-top-color!
(lambda (s)
(mxprims:element-set-border-top-color! elt s))]
[border-bottom-color
(lambda ()
(mxprims:element-border-bottom-color elt))]
[set-border-bottom-color!
(lambda (s)
(mxprims:element-set-border-bottom-color! elt s))]
[border-left-color
(lambda ()
(mxprims:element-border-left-color elt))]
[set-border-left-color!
(lambda (s)
(mxprims:element-set-border-left-color! elt s))]
[border-right-color
(lambda ()
(mxprims:element-border-right-color elt))]
[set-border-right-color!
(lambda (s)
(mxprims:element-set-border-right-color! elt s))]
[border-top-width
(lambda ()
(mxprims:element-border-top-width elt))]
[set-border-top-width!
(lambda (s)
(mxprims:element-set-border-top-width! elt s))]
[border-bottom-width
(lambda ()
(mxprims:element-border-bottom-width elt))]
[set-border-bottom-width!
(lambda (s)
(mxprims:element-set-border-bottom-width! elt s))]
[border-left-width
(lambda ()
(mxprims:element-border-left-width elt))]
[set-border-left-width!
(lambda (s)
(mxprims:element-set-border-left-width! elt s))]
[border-right-width
(lambda ()
(mxprims:element-border-right-width elt))]
[set-border-right-width!
(lambda (s)
(mxprims:element-set-border-right-width! elt s))]
[width
(lambda ()
(mxprims:element-width elt))]
[set-width!
(lambda (s)
(mxprims:element-set-width! elt s))]
[height
(lambda ()
(mxprims:element-height elt))]
[set-height!
(lambda (s)
(mxprims:element-set-height! elt s))]
[top
(lambda ()
(mxprims:element-top elt))]
[set-top!
(lambda (s)
(mxprims:element-set-top! elt s))]
[left
(lambda ()
(mxprims:element-left elt))]
[set-left!
(lambda (s)
(mxprims:element-set-left! elt s))]
[z-index
(lambda ()
(mxprims:element-z-index elt))]
[set-z-index!
(lambda (s)
(mxprims:element-set-z-index! elt s))])
(sequence (super-init))))
(define mx-event%
(class object% (dhtml-event)
(private
[event dhtml-event])
(public
; predicates
[keypress? (lambda () (mxprims:event-keypress? event))]
[keydown? (lambda () (mxprims:event-keydown? event))]
[keyup? (lambda () (mxprims:event-keyup? event))]
[mousedown? (lambda () (mxprims:event-mousedown? event))]
[mousemove? (lambda () (mxprims:event-mousemove? event))]
[mouseover? (lambda () (mxprims:event-mouseover? event))]
[mouseout? (lambda () (mxprims:event-mouseout? event))]
[mouseup? (lambda () (mxprims:event-mouseup? event))]
[click? (lambda () (mxprims:event-click? event))]
[dblclick? (lambda () (mxprims:event-dblclick? event))]
[error? (lambda () (mxprims:event-error? event))]
; attributes
[tag (lambda () (mxprims:event-tag event))]
[id (lambda () (mxprims:event-id event))]
[from-tag (lambda () (mxprims:event-from-tag event))]
[from-id (lambda () (mxprims:event-id event))]
[to-tag (lambda () (mxprims:event-to-tag event))]
[to-id (lambda () (mxprims:event-to-id event))]
[keycode (lambda () (mxprims:event-keycode event))]
[shiftkey (lambda () (mxprims:event-shiftkey event))]
[ctrlkey (lambda () (mxprims:event-ctrlkey event))]
[altkey (lambda () (mxprims:event-altkey event))]
[x (lambda () (mxprims:event-x event))]
[y (lambda () (mxprims:event-y event))])
(sequence (super-init))))
(define mx-document%
(class object%
((label "MysterX")
(width 'default)
(height 'default)
(x 'default)
(y 'default)
(style-options null))
(private
[doc (mxprims:make-document label width height x y style-options)]
[thread-sem (make-semaphore 1)] ; protects *handler-threads*
[thread-wait (lambda () (semaphore-wait thread-sem))]
[thread-post (lambda () (semaphore-post thread-sem))]
[handler-sem (make-semaphore 1)] ; protects *handler-table* and its contained hash tables
[handler-wait (lambda () (semaphore-wait handler-sem))]
[handler-post (lambda () (semaphore-post handler-sem))]
[handler-table (make-hash-table)]
[handler-thread #f]
[block-until-event
(lambda () (mxprims:block-until-event doc))]
[make-event-key
(lambda (tag id) ; string x string -> symbol
(let ([new-tag (string-copy tag)]
[new-id (string-copy id)])
(string-uppercase! new-tag)
(string-uppercase! new-id)
(string->symbol
(string-append new-tag "@" new-id))))])
(public
[show
(lambda (b)
(mxprims:document-show doc b))]
[find-element
(lambda (tag id)
(make-object mx-element% doc (mxprims:document-find-element doc tag id)))]
[objects
(lambda ()
(mxprims:document-objects doc))]
[insert-html
(lambda (html-string)
(dynamic-wind
html-wait
(lambda () (mxprims:document-insert-html doc html-string))
html-post))]
[append-html
(lambda (html-string)
(dynamic-wind
html-wait
(lambda () (mxprims:document-append-html doc html-string))
html-post))]
[replace-html
(lambda (html-string)
(dynamic-wind
html-wait
(lambda () (mxprims:document-replace-html doc html-string))
html-post))]
[register-event-handler
(lambda (elt fn)
(dynamic-wind
handler-wait
(lambda ()
(let* ([tag (send elt tag)]
[id (send elt attribute "id")])
(let ([key (make-event-key tag id)])
(hash-table-remove! handler-table key)
(hash-table-put! handler-table key fn))))
handler-post))]
[unregister-event-handler
(lambda (elt)
(dynamic-wind
handler-wait
(lambda ()
(let* ([tag (send elt tag)]
[id (send elt attribute "id")])
(let ([key (make-event-key tag id)])
(hash-table-remove! handler-table key))))
handler-post))]
[insert-object
(opt-lambda (object width height [size 'pixels])
(dynamic-wind
html-wait
(lambda ()
(mxprims:document-insert-html
doc
(coclass->html object width height size))
(car (mxprims:document-objects doc)))
html-post))]
[append-object
(opt-lambda (object width height [size 'pixels])
(dynamic-wind
html-wait
(lambda ()
(mxprims:document-append-html
doc
(coclass->html object width height size))
(car (last-pair (mxprims:document-objects doc))))
html-post))]
[handle-events
(lambda ()
(dynamic-wind
thread-wait
(lambda () ; no-op if existing handler-thread
(unless handler-thread
(dynamic-wind
handler-wait
(lambda ()
(let* ([handler-thunk
(lambda ()
(let loop ()
(block-until-event)
(let* ([prim-event
(with-handlers
([void
(lambda (e)
(printf "~a~n" (exn-message e))
(loop))])
(mxprims:get-event doc))]
[event (make-object mx-event% prim-event)]
[tag (send event tag)]
[id (send event id)]
[key (make-event-key tag id)]
[handler (hash-table-get handler-table key void)])
(unless (void? handler)
(handler event))
(loop))))])
(set! handler-thread (thread handler-thunk))))
handler-post)))
thread-post))]
[stop-handling-events
(lambda ()
(dynamic-wind
thread-wait
(lambda ()
(when handler-thread
(kill-thread handler-thread))
(set! handler-thread #f))
thread-post))])
(sequence
(super-init))))
(thread
(lambda ()
(let loop ()
(mxprims:process-win-events)
(sleep)
(loop))))
(let ([old-exit-handler (exit-handler)])
(exit-handler
(lambda (arg)
(for-each
(lambda (obj)
(let ([val (cdr obj)])
(cond
[(com-object? val)
(mxprims:com-release-object (cdr obj))]
; rely on GC to release interfaces in documents, elements
; not entirely reliable, since collector is conservative
[(or (is-a? val mx-document%)
(is-a? val mx-element%))
(undefine (car obj))])))
(make-global-value-list))
(collect-garbage)
(mxprims:release-type-table)
(mxprims:com-terminate)
(old-exit-handler arg)))))

View File

@ -0,0 +1,21 @@
;;; mysterxu.ss
(require-library "cores.ss")
(require-library "macro.ss")
(require-library "sigs.ss" "mysterx")
(require-library "xmls.ss" "xml")
(define mysterx@
(compound-unit/sig
(import)
(link [core : mzlib:core^ ((require-library "corer.ss"))]
[mxprims : mysterx:prims^ ((require-library "prims.ss" "mysterx"))]
[xml : xml^ ((require-library "xmlr.ss" "xml") (core function))]
[mysterx : mysterx:mysterx^
((require-library "mysterxe.ss" "mysterx")
(core function) (core string)
mxprims xml)])
(export
(open mysterx))))

View File

@ -0,0 +1,7 @@
;; prims.ss
(unit->unit/sig
(load-extension
(build-path (collection-path "mysterx") "dlls" "mxmain.dll"))
()
mysterx:prims^)

276
collects/mysterx/sigs.ss Normal file
View File

@ -0,0 +1,276 @@
;; sigs.ss for mysterx collection
(define-signature mysterx:mysterx^
(mx-document%
xexp->string
com-invoke
com-set-property!
com-get-property
com-methods
com-get-properties
com-set-properties
com-events
com-method-type
com-get-property-type
com-set-property-type
com-event-type
com-object-type
com-is-a?
com-help
com-register-event-handler
com-unregister-event-handler
com-all-coclasses
com-all-controls
coclass->html
cocreate-instance
com-object-eq?
com-object?
com-omit))
(define-signature mysterx:prims^
(com-invoke
com-set-property!
com-get-property
com-methods
com-get-properties
com-set-properties
com-events
com-method-type
com-get-property-type
com-set-property-type
com-event-type
com-object-type
com-is-a?
com-help
com-register-event-handler
com-unregister-event-handler
com-all-coclasses
com-all-controls
coclass->html
cocreate-instance
com-object-eq?
com-object?
com-register-object
com-release-object
make-document
document?
document-insert-html
document-append-html
document-replace-html
document-find-element
document-objects
document-show
element-insert-html
element-append-html
element-insert-text
element-append-text
element-replace-html
element-attribute
element-set-attribute!
element-click
element-tag
element-font-family
element-set-font-family!
element-font-style
element-set-font-style!
element-font-variant
element-set-font-variant!
element-font-weight
element-set-font-weight!
element-font
element-set-font!
element-background
element-set-background!
element-background-image
element-set-background-image!
element-background-repeat
element-set-background-repeat!
element-background-position
element-set-background-position!
element-text-decoration
element-set-text-decoration!
element-text-transform
element-set-text-transform!
element-text-align
element-set-text-align!
element-margin
element-set-margin!
element-padding
element-set-padding!
element-border
element-set-border!
element-border-top
element-set-border-top!
element-border-bottom
element-set-border-bottom!
element-border-left
element-set-border-left!
element-border-right
element-set-border-right!
element-border-color
element-set-border-color!
element-border-width
element-set-border-width!
element-border-style
element-set-border-style!
element-border-top-style
element-set-border-top-style!
element-border-bottom-style
element-set-border-bottom-style!
element-border-left-style
element-set-border-left-style!
element-border-right-style
element-set-border-right-style!
element-style-float
element-set-style-float!
element-clear
element-set-clear!
element-display
element-set-display!
element-visibility
element-set-visibility!
element-list-style-type
element-set-list-style-type!
element-list-style-position
element-set-list-style-position!
element-list-style-image
element-set-list-style-image!
element-list-style
element-set-list-style!
element-whitespace
element-set-whitespace!
element-position
element-overflow
element-set-overflow!
element-pagebreak-before
element-set-pagebreak-before!
element-pagebreak-after
element-set-pagebreak-after!
element-css-text
element-set-css-text!
element-cursor
element-set-cursor!
element-clip
element-set-clip!
element-filter
element-set-filter!
element-style-string
element-text-decoration-none
element-set-text-decoration-none!
element-text-decoration-underline
element-set-text-decoration-underline!
element-text-decoration-overline
element-set-text-decoration-overline!
element-text-decoration-linethrough
element-set-text-decoration-linethrough!
element-text-decoration-blink
element-set-text-decoration-blink!
element-pixel-top
element-set-pixel-top!
element-pixel-left
element-set-pixel-left!
element-pixel-width
element-set-pixel-width!
element-pixel-height
element-set-pixel-height!
element-pos-top
element-set-pos-top!
element-pos-left
element-set-pos-left!
element-pos-width
element-set-pos-width!
element-pos-height
element-set-pos-height!
element-font-size
element-set-font-size!
element-color
element-set-color!
element-background-color
element-set-background-color!
element-background-position-x
element-set-background-position-x!
element-background-position-y
element-set-background-position-y!
element-word-spacing
element-set-word-spacing!
element-letter-spacing
element-set-letter-spacing!
element-vertical-align
element-set-vertical-align!
element-text-indent
element-set-text-indent!
element-line-height
element-set-line-height!
element-margin-top
element-set-margin-top!
element-margin-bottom
element-set-margin-bottom!
element-margin-left
element-set-margin-left!
element-margin-right
element-set-margin-right!
element-padding-top
element-set-padding-top!
element-padding-bottom
element-set-padding-bottom!
element-padding-left
element-set-padding-left!
element-padding-right
element-set-padding-right!
element-border-top-color
element-set-border-top-color!
element-border-bottom-color
element-set-border-bottom-color!
element-border-left-color
element-set-border-left-color!
element-border-right-color
element-set-border-right-color!
element-border-top-width
element-set-border-top-width!
element-border-bottom-width
element-set-border-bottom-width!
element-border-left-width
element-set-border-left-width!
element-border-right-width
element-set-border-right-width!
element-width
element-set-width!
element-height
element-set-height!
element-top
element-set-top!
element-left
element-set-left!
element-z-index
element-set-z-index!
event?
get-event
event-tag
event-id
event-from-tag
event-from-id
event-to-tag
event-to-id
event-keycode
event-shiftkey
event-ctrlkey
event-altkey
event-x
event-y
event-keypress?
event-keydown?
event-keyup?
event-mousedown?
event-mousemove?
event-mouseover?
event-mouseout?
event-mouseup?
event-click?
event-dblclick?
event-error?
block-until-event
process-win-events
com-omit
com-terminate
release-type-table))

13
collects/mzlib/awk.ss Normal file
View File

@ -0,0 +1,13 @@
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (awk)
(require-relative-library "awkr.ss")))
(define-macro awk awk)
(define-values/invoke-unit (match:start match:end match:substring regexp-exec)
(require-relative-library "awkr.ss"))

177
collects/mzlib/awkr.ss Normal file
View File

@ -0,0 +1,177 @@
(unit
(import)
(export awk match:start match:end match:substring regexp-exec)
(define awk
(lambda (get-next-record . rest)
(let*-values ([(user-fields rest) (values (car rest) (cdr rest))]
[(counter rest) (if (and (pair? rest) (symbol? (car rest)))
(values (car rest) (cdr rest))
(values (gensym) rest))]
[(user-state-var-decls rest) (values (car rest) (cdr rest))]
[(continue rest) (if (and (pair? rest) (symbol? (car rest)))
(values (car rest) (cdr rest))
(values (gensym) rest))]
[(user-state-vars) (map car user-state-var-decls)]
[(local-user-state-vars) (map gensym user-state-vars)]
[(first) (car user-fields)]
[(clauses) rest]
[(loop) (gensym)]
[(remainder) (gensym)]
[(extras) (gensym)]
[(arg) (gensym)]
[(else-ready?) (gensym)]
[(orig-on?) (gensym)]
[(post-on-on?) (gensym)]
[(escape) (gensym)]
[(initvars) null])
(letrec ([get-after-clauses
(lambda ()
(let loop ([l clauses][afters null])
(cond
[(null? l) (if (null? afters)
`((values ,@user-state-vars))
afters)]
[(eq? (caar l) 'after)
(loop (cdr l) (append afters (cdar l)))]
[else
(loop (cdr l) afters)])))]
[wrap-state
(lambda (e)
(if (eq? (car e) '=>)
`(=>
(lambda (,arg)
,@(wrap-state `((,(cadr e) ,arg)))))
`((call-with-values
(lambda () ,@e)
(lambda ,(append local-user-state-vars extras)
(set! ,else-ready? #f)
(set!-values ,user-state-vars
(values ,@local-user-state-vars)))))))]
[make-range
(lambda (include-on? include-off? body rest)
(let* ([on? (gensym)])
(set! initvars (cons `(,on? #f) initvars))
(cons
`(let ([,orig-on? ,on?])
(unless ,on? (set! ,on? ,(make-test (car body))))
(let ([,post-on-on? ,on?])
(when ,on? (set! ,on? (not ,(make-test (cadr body)))))
(when ,(if include-on?
(if include-off?
post-on-on?
on?)
(if include-off?
orig-on?
`(and ,orig-on? ,on?)))
,@(wrap-state (cddr body)))))
rest)))]
[make-test
(lambda (test)
(cond
[(string? test)
(let ([g (gensym)])
(set! initvars (cons `(,g (regexp ,test)) initvars))
`(regexp-exec ,g ,first))]
[(number? test)
`(= ,test ,counter)]
[else test]))]
[get-testing-clauses
(lambda ()
(let loop ([l clauses])
(if (null? l)
null
(let* ([clause (car l)]
[test (car clause)]
[body (cdr clause)]
[rest (loop (cdr l))])
(cond
[(or (string? test) (number? test))
(cons
`(cond [,(make-test test)
,@(wrap-state body)]
[else (void)])
rest)]
[(eq? test 'else)
(cons
`(when ,else-ready?
,@(wrap-state body))
(cons
`(set! ,else-ready? #t)
rest))]
[(eq? test 'range)
(make-range #f #f body rest)]
[(eq? test ':range)
(make-range #t #f body rest)]
[(eq? test 'range:)
(make-range #f #t body rest)]
[(eq? test ':range:)
(make-range #t #t body rest)]
[(eq? test 'after)
rest]
[(eq? test '/)
(let ([g (gensym)]
[re (car body)]
[vars (append (map (lambda (s)
(or s (gensym)))
(caddr body))
(gensym))]
[body (cdddr body)])
(set! initvars (cons `(,g (regexp ,re)) initvars))
(cons
`(cond
[(regexp-match ,re ,first)
=> (lambda (,arg)
(apply
(lambda ,vars ,@(wrap-state body))
,arg))]
[else (void)])
rest))]
[else
(cons
`(cond (,test ,@(wrap-state body)) (else (void)))
rest)])))))])
(let ([testing-clauses (get-testing-clauses)])
`(let (,@user-state-var-decls ,@initvars)
(let ,loop ([,counter 1])
(call-with-values
(lambda () ,get-next-record)
(lambda ,user-fields
(if (eof-object? ,first)
(begin
,@(get-after-clauses))
(let ([,else-ready? #t])
(let/ec ,escape
(let ([,continue
(lambda ,(append local-user-state-vars extras)
(set!-values ,user-state-vars
(values ,@local-user-state-vars))
(,escape))])
,@testing-clauses))
(,loop (add1 ,counter)))))))))))))
(define-struct match (s a))
(define match:start
(case-lambda
[(rec) (match:start rec 0)]
[(rec which) (car (list-ref (match-a rec) which))]))
(define match:end
(case-lambda
[(rec) (match:end rec 0)]
[(rec which) (cdr (list-ref (match-a rec) which))]))
(define match:substring
(case-lambda
[(rec) (match:substring rec 0)]
[(rec which) (let ([p (list-ref (match-a rec) which)])
(substring (match-s rec) (car p) (cdr p)))]))
(define regexp-exec
(lambda (re s)
(let ([r (regexp-match-positions re s)])
(if r
(make-match s r)
#f)))))

View File

@ -0,0 +1,9 @@
(require-library "cmdlineu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:command-line^ mzlib:command-line@ #f)
(require-library "cmdlinem.ss")

View File

@ -0,0 +1,9 @@
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (command-line)
(require-library "cmdlinemr.ss")))
(define-macro command-line command-line)

107
collects/mzlib/cmdlinemr.ss Normal file
View File

@ -0,0 +1,107 @@
(unit
(import)
(export command-line)
(define command-line
(lambda args
(let* ([serror
(lambda (msg . detail)
(apply
raise-syntax-error
'command-line
msg
(cons 'command-line args)
detail))]
[missing
(lambda (what)
(serror (format "missing ~a" what)))]
[extract (lambda (what args . detail)
(if (null? args)
(apply serror (format "missing ~a" what) detail)
(values (car args) (cdr args))))]
[listify (lambda (l)
(let loop ([l l])
(cond
[(null? l) null]
[(pair? l) (cons (car l) (loop(cdr l)))]
[else (list l)])))]
[check-formals
(lambda (l)
(unless (andmap symbol? (listify l))
(serror "bad argument specification" l)))]
[formal-names
(lambda (l)
(let loop ([l l])
(cond
[(null? l) null]
[(pair? l) (cons (symbol->string (car l)) (loop(cdr l)))]
[else (list (let ([s (symbol->string l)])
(if (char=? #\* (string-ref s (sub1 (string-length s))))
(substring s 0 (sub1 (string-length s)))
s)))])))])
(let*-values ([(name args) (extract "name string" args)]
[(_) (unless (string? name)
(serror "program name is not a string" name))]
[(argv args) (extract "argv vector expression" args)])
`(parse-command-line
,name ,argv
,@(let loop ([args args][clauses null])
(if (null? args)
`((list ,@clauses)
(lambda (accum) (void))
null)
(let ([line (car args)])
(if (pair? line)
(case (car line)
[(once-each once-any multi)
(loop (cdr args)
(append
clauses
(list
(list* 'list
(list 'quote (car line))
(let loop ([sublines (cdr line)])
(if (null? sublines)
null
(cons
(let ([line (car sublines)])
(let-values ([(flags rest) (extract "flag string(s)" line line)])
(unless (or (string? flags)
(and (list? flags)
(andmap string? flags)))
(serror "flag specification is not a string or sequence of strings" flags))
(if (and (pair? rest) (eq? (car rest) '=>))
(let ([rest (cdr rest)])
(unless (and (list? rest) (= 2 (length rest)))
(serror "two expressions must follow a => line" line))
`(list ',(listify flags) ,@rest))
(let*-values ([(formals rest) (let loop ([a null][rest rest])
(cond
[(null? rest) (values a null)]
[(symbol? (car rest)) (values (append a (list (car rest))) (cdr rest))]
[else (values a rest)]))]
[(_) (check-formals formals)]
[(help rest) (extract "help string" rest line)]
[(_) (unless (string? help)
(serror "help info is not a string" help))]
[(expr1 rest) (extract "handler body expressions" rest line)])
`(list ',(listify flags)
(lambda ,(cons (gensym 'flag) formals)
,expr1 ,@rest)
'(,help ,@(formal-names formals)))))))
(loop (cdr sublines)))))))))]
[(=>)
(when (pair? (cdr args)) (serror "=> must be the last clause"))
`((list ,@clauses)
,@(cdr line))]
[(args)
(when (pair? (cdr args)) (serror "args must be the last clause"))
(let*-values ([(formals rest) (extract "arg-handler formals" (cdr line) line)]
[(_) (check-formals formals)]
[(expr1 rest) (extract "arg-handler body expressions" rest line)])
`((list ,@clauses)
(lambda ,(cons (gensym 'accum) formals) ,expr1 ,@rest)
,(cons 'list (formal-names formals))))]
[else (serror "not a once-each, once-any, multi, args, or => line" line)])
(serror "not a once-each, once-any, multi, or args line" line)))))))))))

293
collects/mzlib/cmdliner.ss Normal file
View File

@ -0,0 +1,293 @@
(unit/sig
mzlib:command-line^
(import)
(define number-regexp (regexp "^[-+][0-9]*(|[.][0-9]*)$"))
(define print-args
(lambda (port l f)
(let loop ([l l][a (letrec ([a (arity f)]
[a-c (lambda (a)
(cond
[(number? a) (cons (sub1 a) (sub1 a))]
[(arity-at-least? a)
(let ([v (sub1 (arity-at-least-value a))])
(cons v v))]
[else (let ([r (map a-c a)])
(cons (apply min (map car r))
(apply max (map cdr r))))]))])
(a-c a))])
(unless (null? l)
(fprintf port " ~a<~a>~a"
(if (positive? (car a)) "" "[")
(car l)
(if (positive? (car a)) "" "]"))
(unless (positive? (cdr a))
(fprintf port " ..."))
(loop (cdr l) (cons (sub1 (car a)) (sub1 (cdr a))))))))
(define (procedure-arity-includes-at-least? p n)
(letrec ([a-c
(lambda (a)
(cond
[(number? a) (>= a n)]
[(arity-at-least? a) #t]
[else (ormap a-c a)]))])
(a-c (arity p))))
(define parse-command-line
(case-lambda
[(program arguments table finish finish-help)
(parse-command-line program arguments table finish finish-help
(lambda (s)
(display s)
(exit 0)))]
[(program arguments table finish finish-help help)
(parse-command-line program arguments table finish finish-help help
(lambda (flag)
(error (string->symbol program) "unknown flag: ~s" flag)))]
[(program arguments table finish finish-help help unknown-flag)
(unless (string? program)
(raise-type-error 'parse-command-line "program name string" program))
(unless (and (vector? arguments)
(andmap string? (vector->list arguments)))
(raise-type-error 'parse-command-line "argument vector of strings" arguments))
(unless (and (list? table)
(let ([bad-table
(lambda (reason)
(raise-type-error 'parse-command-line
(format "table as a list of flag-list/procedure pairs (~a)"
reason)
table))])
(andmap (lambda (spec)
(and (or (and (list? spec) (pair? spec))
(bad-table (format "spec-set must be a non-empty list: ~a" spec)))
(or (memq (car spec) '(once-any once-each multi))
(bad-table (format "spec-set type must be 'once-any, 'once-each, or 'multi: ~a"
(car spec))))
(andmap (lambda (line)
(and (or (and (list? line) (= (length line) 3))
(bad-table (format "spec-line must be a list of at three items: ~e" line)))
(or (list? (car line))
(bad-table (format "flags part of a spec-line must be a list: ~e" (car line))))
(andmap
(lambda (flag)
(or (string? flag)
(bad-table (format "flag must be a string: ~e" flag)))
(or (and (or (regexp-match "^-[^-]$" flag)
(regexp-match "^[+][^+]$" flag)
(regexp-match "^--." flag)
(regexp-match "^[+][+]." flag))
(not (or (regexp-match "^--help$" flag)
(regexp-match "^-h$" flag)
(regexp-match number-regexp flag))))
(bad-table (format "no ill-formed or pre-defined flags: ~e" flag))))
(car line))
(or (procedure? (cadr line))
(bad-table (format "second item in a spec-line must be a procedure: ~e" (cadr line))))
(let ([a (arity (cadr line))])
(or (and (number? a)
(or (>= a 1)
(bad-table (format "flag handler procedure must take at least 1 argument: ~e"
(cadr line)))))
(arity-at-least? a)
(bad-table (format "flag handler procedure cannot have multiple cases: ~e" (cadr line)))))
(or (and (list? (caddr line))
(andmap string? (caddr line)))
(bad-table (format "spec-line help section must be a list of strings")))
(or (let ([l (length (caddr line))]
[a (arity (cadr line))])
(if (number? a)
(= a l)
(and (>= l 1)
(>= l (arity-at-least-value a)))))
(bad-table (format "spec-line help list strings must match procedure arguments")))))
(cdr spec))))
table)))
(raise-type-error 'parse-command-line "table of spec sets" table))
(unless (and (procedure? finish)
(procedure-arity-includes-at-least? finish 1))
(raise-type-error 'parse-command-line "finish procedure accepting at least 1 argument" finish))
(unless (and (list? finish-help) (andmap string? finish-help))
(raise-type-error 'parse-command-line "argument help list of strings" finish-help))
(unless (and (procedure? help) (procedure-arity-includes? help 1))
(raise-type-error 'parse-command-line "help procedure of arity 1" help))
(unless (and (procedure? unknown-flag) (procedure-arity-includes? unknown-flag 1)
(let ([a (arity unknown-flag)])
(or (number? a) (arity-at-least? a))))
(raise-type-error 'parse-command-line "unknown-flag procedure of simple arity, accepting 1 argument (an perhaps more)" unknown-flag))
(letrec ([a (arity finish)]
[l (length finish-help)]
[a-c (lambda (a)
(or (and (number? a) (sub1 a))
(and (arity-at-least? a)
(max 1 (arity-at-least-value a)))
(and (list? a) (apply max (map a-c a)))))])
(unless (= (a-c a) l)
(error 'parse-command-line "the length of the argument help string list does not match the arity of the finish procedure")))
(let* ([once-spec-set
(lambda (lines)
(let ([set (cons #f (apply append (map car lines)))])
(map
(lambda (line) (cons set line))
lines)))]
[table
(apply
append
(list
(list #f (list "--help" "-h")
(lambda (f)
(let* ([sp (open-output-string)])
(fprintf sp "~a~a" program
(if (null? table)
""
" [ <flag> ... ]"))
(print-args sp finish-help finish)
(fprintf sp "~n where <flag> is one of~n ")
(for-each
(lambda (set)
(for-each
(lambda (line)
(let loop ([flags (car line)])
(let ([flag (car flags)])
(fprintf sp " ~a" flag)
(print-args sp (cdaddr line) (cadr line)))
(unless (null? (cdr flags))
(fprintf sp ",")
(loop (cdr flags))))
(fprintf sp " : ~a~n " (caaddr line)))
(cdr set)))
table) ; the original table
(fprintf sp " --help, -h : Show this help~n")
(fprintf sp " -- : Do not treat any remaining argument as a flag (at this level)~n")
(fprintf sp " Multiple single-letter flags can be combined after one `-'.~n E.g.: `-h-' is the same as `-h --'~n")
(help (get-output-string sp))))
(list "Help")))
(map
(lambda (spec)
(cond
[(eq? (car spec) 'once-each)
(apply
append
(map
(lambda (line) (once-spec-set (list line)))
(cdr spec)))]
[(eq? (car spec) 'once-any)
(once-spec-set (cdr spec))]
[(eq? (car spec) 'multi)
(map
(lambda (line) (cons #f line))
(cdr spec))]))
table))]
[done
(lambda (args r-acc)
(let ([options (reverse r-acc)]
[c (length args)])
(if (procedure-arity-includes? finish (add1 c))
(apply finish options args)
(error (string->symbol program)
(format "expects~a on the command line, given ~a argument~a~a"
(if (null? finish-help)
" no arguments"
(let ([s (open-output-string)])
(parameterize ([current-output-port s])
(print-args s finish-help finish))
(let ([s (get-output-string s)])
(if (equal? 2 (arity finish))
(format " 1~a" s)
s))))
c
(cond
[(zero? c) "s"]
[(= c 1) ": "]
[else "s: "])
(let loop ([args args])
(if (null? args)
""
(string-append (car args) " " (loop (cdr args))))))))))]
[call-handler
(lambda (handler flag args r-acc k)
(let* ([a (arity handler)]
[remaining (length args)]
[needed (if (number? a)
(sub1 a)
(sub1 (arity-at-least-value a)))]
[use (if (number? a)
(sub1 a)
remaining)])
(if (< remaining needed)
(error (string->symbol program)
"the ~s flag needs ~a argument~a, but only ~a provided"
flag needed (if (> needed 1) "s" "")
remaining)
(let ([v (apply handler
flag
(let loop ([n use][args args])
(if (zero? n)
null
(cons (car args)
(loop (sub1 n) (cdr args))))))])
(k (list-tail args use)
(if (void? v)
r-acc
(cons v r-acc)))))))]
[handle-flag
(lambda (flag args r-acc orig-multi k)
(let loop ([table table])
(cond
[(null? table)
(call-handler unknown-flag flag args r-acc k)]
[(member flag (cadar table))
(when (caar table)
(let ([set (caar table)])
(if (car set)
(let ([flags (cdr set)])
(error (string->symbol program)
(let ([s (if (= 1 (length flags))
(format "the ~a flag can only be specified once" (car flags))
(format "only one instance of one flag from ~a is allowed" flags))])
(if orig-multi
(format "~a; note that ~s is shorthand for ~s, in contrast to ~s"
s
orig-multi
(let loop ([prefix (string-ref orig-multi 0)]
[flags (string->list (substring orig-multi 1 (string-length orig-multi)))]
[sep ""])
(if (null? flags)
""
(format "~a~a~a~a" sep prefix (car flags)
(loop prefix (cdr flags) " "))))
(string-append (substring orig-multi 0 1) orig-multi))
s))))
(set-car! set #t))))
(call-handler (caddar table) flag args r-acc k)]
[else (loop (cdr table))])))])
(let loop ([args (vector->list arguments)][r-acc null])
(if (null? args)
(done args r-acc)
(let ([arg (car args)]
[rest (cdr args)])
(cond
[(regexp-match number-regexp arg)
(done args r-acc)]
[(regexp-match "^--$" arg)
(done (cdr args) r-acc)]
[(regexp-match "^[-+][-+]" arg)
(handle-flag arg rest r-acc #f loop)]
[(regexp-match "^[-+]." arg)
(let a-loop ([s (string->list (substring arg 1 (string-length arg)))]
[rest rest]
[r-acc r-acc])
(if (null? s)
(loop rest r-acc)
(handle-flag (string (string-ref arg 0) (car s))
rest r-acc
arg
(lambda (args r-acc)
(a-loop (cdr s) args r-acc)))))]
[else
(done args r-acc)])))))])))

View File

@ -0,0 +1,3 @@
(define-signature mzlib:command-line^
(parse-command-line))

View File

@ -0,0 +1,7 @@
(require-library "cmdlines.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:command-line@ (require-library-unit/sig "cmdliner.ss"))

11
collects/mzlib/compat.ss Normal file
View File

@ -0,0 +1,11 @@
(require-library "compatu.ss")
(require-library "functio.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:compat^
mzlib:compat@
#f
mzlib:function^)

View File

@ -0,0 +1,9 @@
(define-macro defmacro
(lambda (name args . body)
`(define-macro ,name (lambda ,args ,@body))))
(define-macro letmacro
(lambda (name args mbody . body)
`(let-macro ,name (lambda ,args ,mbody)
,body)))

73
collects/mzlib/compatr.ss Normal file
View File

@ -0,0 +1,73 @@
(unit/sig
mzlib:compat^
(import mzlib:function^)
(define 1+ add1)
(define 1- sub1)
(define #%1+ #%add1)
(define #%1- #%sub1)
(define =? =)
(define <? <)
(define >? >)
(define <=? <)
(define >=? >)
(define atom? (lambda (v) (not (pair? v))))
(define gentemp gensym)
(define sort ; Chez argument order
(lambda (less-than? l)
(quicksort l less-than?)))
(define bound? defined?)
(define flush-output-port flush-output)
(define real-time current-milliseconds)
(define getprop (void))
(define putprop (void))
(let ([table (make-hash-table)])
(letrec ([gp
(case-lambda
[(k prop) (gp k prop #f)]
[(k prop def)
(let ([al (hash-table-get table k (lambda () #f))])
(if al
(let ([v (assq prop al)])
(if v
(cdr v)
def))
def))])]
[pp
(lambda (k prop nv)
(let ([al (hash-table-get table k (lambda () '()))])
(let ([v (assq prop al)])
(if v
(set-cdr! v nv)
(hash-table-put! table k (cons (cons prop nv) al))))))])
(set! getprop gp)
(set! putprop pp)))
; Chez's new-cafe
(define new-cafe
(letrec ([nc
(case-lambda
[() (nc (current-eval))]
[(eval)
(let/ec escape
(let ([orig-exit (exit-handler)]
[orig-eval (current-eval)])
(dynamic-wind
(lambda ()
(current-eval eval)
(exit-handler
(lambda (v) (escape v))))
read-eval-print-loop
(lambda ()
(current-eval orig-eval)
(exit-handler orig-exit)))))])])
nc))
)

16
collects/mzlib/compats.ss Normal file
View File

@ -0,0 +1,16 @@
(begin-elaboration-time
(require-library "functios.ss"))
(define-signature mzlib:compat^
(real-time
1+ 1- #%1+ #%1-
>=? <=? >? <? =?
flush-output-port
bound?
sort
gentemp
atom?
putprop getprop
new-cafe))

11
collects/mzlib/compatu.ss Normal file
View File

@ -0,0 +1,11 @@
(begin-elaboration-time
(require-library "compatm.ss"))
(require-library "compats.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:compat@ (require-library-unit/sig "compatr.ss"))

View File

@ -0,0 +1,8 @@
(require-library "compileu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:compile^
mzlib:compile@)

327
collects/mzlib/compiler.ss Normal file
View File

@ -0,0 +1,327 @@
(compound-unit/sig
(import)
(link
[referf
: (require-unit reference-file)
((unit->unit/sig (require-relative-library "referf.ss")
()
(require-unit reference-file)))]
[compile
: mzlib:compile^
((unit/sig mzlib:compile^
(import (r : (require-unit reference-file)))
(define identity (lambda (x n) x))
; top-level begin-elaboration-time => begin-expansion-time
; nested begin-elaboration-time => begin
; require-XXX => usual expansion w/o string check
(define -require-library-unit/sig (r:require-unit #f #t #f #t 'require-library-unit/sig))
(define -require-library-unit (r:require-unit #f #t #f #f 'require-library-unit))
(define -require-relative-library-unit/sig (r:require-unit #f #t #t #t 'require-relative-library-unit/sig))
(define -require-relative-library-unit (r:require-unit #f #t #t #f 'require-relative-library-unit))
(define -require-unit/sig (r:require-unit #f #f #f #t 'require-unit/sig))
(define -require-unit (r:require-unit #f #f #f #f 'require-unit))
(define -reference-file (r:reference-file #f #f #f))
(define -require-library (r:reference-file #f #t #f))
(define -require-relative-library (r:reference-file #f #t #t))
(define make--begin-elaboration-time
(lambda (do?)
(lambda body
(when do?
(eval `(begin ,@body)))
`(#%eval (#%eval (#%quote (begin ,@body)))))))
(define make-compile-namespace
(lambda (flags preserve-elab? do-elab? preserve-constr? do-constr?)
(let ([n (apply make-namespace flags)]
[gvs (make-global-value-list)])
(parameterize ([current-namespace n])
(for-each
(lambda (gvp)
(unless (defined? (car gvp))
(eval `(define ,(car gvp) (quote ,(cdr gvp))))))
gvs)
(setup-preserving-compile-namespace preserve-elab? do-elab? preserve-constr? do-constr?))
n)))
(define (setup-preserving-compile-namespace preserve-elab? do-elab? preserve-constr? do-constr?)
(when (or preserve-elab? do-elab? preserve-constr? do-constr?)
(eval `(begin
(require-library "refer.ss")
(define-macro reference-file ,-reference-file)
(define-macro require-unit/sig ,-require-unit/sig)
(define-macro require-unit ,-require-unit)
(define-macro require-library-unit/sig ,-require-library-unit/sig)
(define-macro require-library-unit ,-require-library-unit)
(define-macro require-library ,-require-library)
(define-macro require-relative-library-unit/sig ,-require-relative-library-unit/sig)
(define-macro require-relative-library-unit ,-require-relative-library-unit)
(define-macro require-relative-library ,-require-relative-library)
,@(let ([e (if preserve-elab?
`((define-macro begin-elaboration-time ,(make--begin-elaboration-time do-elab?)))
null)]
[c (if preserve-constr?
`((define-macro begin-construction-time ,(make--begin-elaboration-time do-constr?)))
null)])
(append e c))))))
(define compile-file
(case-lambda
[(srcs dest) (compile-file srcs dest null identity)]
[(srcs dest flags) (compile-file srcs dest flags identity)]
[(srcs dest flags preprocessor)
(unless (or (string? srcs)
(input-port? srcs)
(and (list? srcs) (andmap (lambda (x) (or (string? x)
(input-port? x)))
srcs)))
(raise-type-error 'compile-file
"string, input-port, or list of strings or input-ports"
srcs))
(unless (or (string? dest) (output-port? dest))
(raise-type-error 'compile-file "string or output-port" dest))
(unless (and (list flags)
(andmap (lambda (s)
(member s '(ignore-macro-definitions
strip-macro-definitions
expand-load
use-current-namespace
ignore-require-library
expand-require-library
no-warnings
only-expand
preserve-elaborations
also-preserve-elaborations
preserve-constructions
also-preserve-constructions)))
flags))
(raise-type-error 'compile-file "list of flag symbols" flags))
(unless (and (procedure? preprocessor)
(procedure-arity-includes? preprocessor 2))
(raise-type-error 'compile-file "procedure (arity 2)" preprocessor))
(let* ([do-macros? (not (member 'ignore-macro-definitions flags))]
[keep-macros? (not (member 'strip-macro-definitions flags))]
[expand-load? (member 'expand-load flags)]
[expand-rl? (member 'expand-require-library flags)]
[ignore-rl? (member 'ignore-require-library flags)]
[expand-only? (member 'only-expand flags)]
[also-keep-elab? (member 'also-preserve-elaborations flags)]
[keep-elab? (or also-keep-elab? (member 'preserve-elaborations flags))]
[also-keep-constr? (member 'also-preserve-constructions flags)]
[keep-constr? (or also-keep-elab? (member 'preserve-constructions flags))]
[namespace (if (member 'use-current-namespace flags)
(begin
(setup-preserving-compile-namespace
keep-elab?
also-keep-elab?
keep-constr?
also-keep-constr?)
(current-namespace))
(make-compile-namespace
(if (built-in-name 'wx:frame%) ; HACK!!!
'(wx)
null)
keep-elab?
also-keep-elab?
keep-constr?
also-keep-constr?))]
[required (make-hash-table)]
[warning
(lambda (s)
(unless (member 'no-warnings flags)
(fprintf (current-error-port)
"compile-file warning: ~a~n"
s)))])
(let ([out (if (output-port? dest)
dest
(open-output-file dest 'truncate/replace))])
(dynamic-wind
void
(lambda ()
(when keep-elab?
(display "'e " out)) ; mark of an elaboration-time file
(write
`(#%if (#%not (#%string=? (#%version) ,(version)))
(#%error (#%quote ,(if (string? srcs)
(string->symbol srcs)
'compiled-file))
,(string-append
"compiled for MzScheme version "
(version)
", not ~a")
(#%version)))
out)
(newline out)
(let src-loop ([srcs srcs])
(unless (null? srcs)
(let*-values ([(src next-srcs)
(if (list? srcs)
(values (car srcs) (cdr srcs))
(values srcs null))]
[(in) (if (input-port? src)
src
(open-input-file src))])
(parameterize ([current-load-relative-directory
(let ([clrp (current-load-relative-directory)])
(if (string? src)
(let-values ([(base name dir?)
(split-path (path->complete-path
src
(or clrp
(current-directory))))])
base)
clrp))])
(dynamic-wind
void
(lambda ()
(let loop ([in in])
(let ([s (read in)])
(if (not (eof-object? s))
(let* ([do-defmacro
(lambda (s)
(let ([m (if (pair? (cdr s))
(cadr s)
#f)])
(if (symbol? m)
(parameterize ([current-namespace namespace])
(eval s)
#f)
(begin
(warning
(format
"define-macro expression is ill-formed: ~s"
s))
#f))))]
[do-load
(lambda (s cd? rel?)
(let ([name (if (pair? (cdr s))
(cadr s)
#f)])
(if (and (string? name)
(null? (cddr s)))
(let*-values ([(name) (if (and rel?
(relative-path? name)
(current-load-relative-directory))
(build-path (current-load-relative-directory) name)
name)]
[(base nameonly dir?) (split-path name)]
[(cd?) (and cd?
(string? base))]
[(orig-dir) (and cd?
(current-directory))])
(if cd?
(current-directory
base))
(let ([in (open-input-file
(if cd?
nameonly
name))])
(dynamic-wind
void
(lambda ()
(parameterize ([current-load-relative-directory
(if (string? base)
base
(current-load-relative-directory))])
(loop in))
#t)
(lambda ()
(close-input-port in)
(if cd?
(current-directory
orig-dir)))))
#t)
(begin
(warning
(format
"load expression is ill-formed or ~a: ~s"
"contains an expression for file name"
s))
#f))))]
[find-library
(lambda (collection name)
(let ([all-paths (current-library-collection-paths)])
(let loop ([paths all-paths])
(if (null? paths)
(error 'compile-file "require-library: collection not found: ~s (in any of ~s)"
collection all-paths)
(let ([dir (build-path (car paths) collection)])
(if (directory-exists? dir)
(build-path dir name)
(loop (cdr paths))))))))]
[do-rl
(lambda (s)
(if (and (pair? (cdr s))
(string? (cadr s))
(or (null? (cddr s))
(and (pair? (cddr s))
(string? (caddr s))
(null? (cdddr s)))))
(let ([name (cadr s)]
[collection (if (null? (cddr s))
"mzlib"
(caddr s))])
(if expand-rl?
(let* ([key (string->symbol (string-append collection (string #\null) name))])
(if (hash-table-get required key (lambda () #f))
#t
(let ([fullname (find-library collection name)])
(hash-table-put! required key #t)
(do-load s #f #t)
#t)))
(parameterize ([current-namespace namespace])
(eval `(require-library/proc ,name
,collection))
#f)))
(begin
(warning
(format
"require-library expression is ill-formed or ~a: ~s"
"contains an expression for library/collection name"
s))
#f)))]
[s (let ([p (preprocessor s namespace)])
(parameterize ([current-namespace namespace])
(expand-defmacro p)))]
[v-c (if expand-only?
s
(if (void? s)
(compile '(#%void))
(parameterize ([current-namespace namespace])
(compile s))))]
[v (if (pair? s)
(let ([t (car s)])
(case t
[(define-macro
define-id-macro
define-expansion-time
#%define-macro
#%define-id-macro
#%define-expansion-time)
(and do-macros? (or (do-defmacro s) (not keep-macros?)))]
[(load #%load)
(and expand-load? (do-load s #f #f))]
[(load/cd #%load/cd)
(and expand-load? (do-load s #t #f))]
[(load-relative #%load-relative)
(and expand-load? (do-load s #f #t))]
[(require-library/proc #%require-library/proc)
(and (not ignore-rl?) (do-rl s))]
[else #f]))
#f)])
(unless v
(write v-c out))
(newline out)
(loop in))))))
(lambda ()
(if (input-port? src)
(void)
(close-input-port in)))))
(src-loop next-srcs)))))
(lambda ()
(if (output-port? dest)
(void)
(close-output-port out))))))])))
referf)])
(export (open compile)))

View File

@ -0,0 +1,3 @@
(define-signature mzlib:compile^
(compile-file))

View File

@ -0,0 +1,10 @@
(require-library "compiles.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:compile@ (require-library-unit/sig "compiler.ss"))

13
collects/mzlib/core.ss Normal file
View File

@ -0,0 +1,13 @@
; Load core mzlib
(require-relative-library "coreu.ss")
(require-relative-library "pretty.ss")
(require-relative-library "file.ss")
(require-relative-library "function.ss")
(require-relative-library "string.ss")
(require-relative-library "compile.ss")
(require-relative-library "math.ss")
(require-relative-library "thread.ss")

View File

@ -0,0 +1,17 @@
(compound-unit/sig
(import)
(link [pretty-print : mzlib:pretty-print^ ((require-library-unit/sig "prettyr.ss"))]
[file : mzlib:file^ ((require-library-unit/sig "filer.ss") string function)]
[function : mzlib:function^ ((require-library-unit/sig "functior.ss"))]
[string : mzlib:string^ ((require-library-unit/sig "stringr.ss"))]
[compile : mzlib:compile^ ((require-library-unit/sig "compiler.ss"))]
[math : mzlib:math^ ((require-library-unit/sig "mathr.ss"))]
[thread : mzlib:thread^ ((require-library-unit/sig "threadr.ss"))])
(export (open pretty-print)
(open file)
(open function)
(open string)
(open compile)
(open math)
(open thread)))

View File

@ -0,0 +1,12 @@
(require-library "cores.ss")
(define-signature mzlib:core-flat^
((open mzlib:pretty-print^)
(open mzlib:file^)
(open mzlib:function^)
(open mzlib:string^)
(open mzlib:compile^)
(open mzlib:math^)
(open mzlib:thread^)))

13
collects/mzlib/corem.ss Normal file
View File

@ -0,0 +1,13 @@
; Loads macro parts of MzLib:
(require-library "refer.ss")
(require-relative-library "spidey.ss")
(require-relative-library "macro.ss")
(require-relative-library "match.ss")
(require-relative-library "defstru.ss")
(require-relative-library "compatm.ss")
(require-relative-library "shared.ss")

17
collects/mzlib/corer.ss Normal file
View File

@ -0,0 +1,17 @@
(compound-unit/sig
(import)
(link [pretty-print : mzlib:pretty-print^ ((require-library-unit/sig "prettyr.ss"))]
[file : mzlib:file^ ((require-library-unit/sig "filer.ss") string function)]
[function : mzlib:function^ ((require-library-unit/sig "functior.ss"))]
[string : mzlib:string^ ((require-library-unit/sig "stringr.ss"))]
[compile : mzlib:compile^ ((require-library-unit/sig "compiler.ss"))]
[math : mzlib:math^ ((require-library-unit/sig "mathr.ss"))]
[thread : mzlib:thread^ ((require-library-unit/sig "threadr.ss"))])
(export (unit pretty-print)
(unit file)
(unit function)
(unit string)
(unit compile)
(unit math)
(unit thread)))

21
collects/mzlib/cores.ss Normal file
View File

@ -0,0 +1,21 @@
(begin-elaboration-time
(require-relative-library "prettys.ss")
(require-relative-library "files.ss")
(require-relative-library "functios.ss")
(require-relative-library "strings.ss")
(require-relative-library "compiles.ss")
(require-relative-library "maths.ss")
(require-relative-library "threads.ss")
(require-library "refer.ss"))
(define-signature mzlib:core^
((unit pretty-print : mzlib:pretty-print^)
(unit file : mzlib:file^)
(unit function : mzlib:function^)
(unit string : mzlib:string^)
(unit compile : mzlib:compile^)
(unit math : mzlib:math^)
(unit thread : mzlib:thread^)))

20
collects/mzlib/coreu.ss Normal file
View File

@ -0,0 +1,20 @@
; Load core mzlib
(require-relative-library "corem.ss")
(require-relative-library "prettyu.ss")
(require-relative-library "fileu.ss")
(require-relative-library "functiou.ss")
(require-relative-library "compatu.ss")
(require-relative-library "stringu.ss")
(require-relative-library "compileu.ss")
(require-relative-library "mathu.ss")
(require-relative-library "threadu.ss")
(require-relative-library "cores.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:core@ (require-relative-library-unit/sig "corer.ss"))

11
collects/mzlib/date.ss Normal file
View File

@ -0,0 +1,11 @@
(require-library "dateu.ss")
(require-library "functio.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:date^
mzlib:date@
#f
mzlib:function^)

359
collects/mzlib/dater.ss Normal file
View File

@ -0,0 +1,359 @@
(unit/sig mzlib:date^
(import mzlib:function^)
;; Support for Julian calendar added by Shriram;
;; current version only works until 2099 CE Gregorian
#|
(define-primitive seconds->date (num -> structure:date))
(define-primitive current-seconds (-> num))
(define-primitive date-second (structure:date -> num))
(define-primitive date-minute (structure:date -> num))
(define-primitive date-hour (structure:date -> num))
(define-primitive date-day (structure:date -> num))
(define-primitive date-month (structure:date -> num))
(define-primitive date-year (structure:date -> num))
(define-primitive date-week-day (structure:date -> num))
(define-primitive date-year-day (structure:date -> num))
(define-primitive date-dst? (structure:date -> bool))
(define-primitive make-date (num num num num num num num num bool ->
structure:date))
(define-primitive expr->string (a -> string))
(define-primitive foldl (case->
((a z -> z) z (listof a) -> z)
((a b z -> z) z (listof a) (listof b) -> z)
((a b c z -> z) z (listof a) (listof b) (listof c) -> z)
(((arglistof x) ->* z) z (listof (arglistof x)) ->* z)))
(define-primitive foldr (case->
((a z -> z) z (listof a) -> z)
((a b z -> z) z (listof a) (listof b) -> z)
((a b c z -> z) z (listof a) (listof b) (listof c) -> z)
(((arglistof x) ->* z) z (listof (arglistof x)) ->* z)))
|#
(define legal-formats
(list 'american 'chinese 'german 'indian 'irish 'julian))
(define date-display-format
(make-parameter 'american
(lambda (s)
(unless (memq s legal-formats)
(raise-type-error 'date-display-format
(format "symbol in ~a" legal-formats)
s))
s)))
(define month/number->string
(lambda (x)
(case x
[(12) "December"] [(1) "January"] [(2) "February"]
[(3) "March"] [(4) "April"] [(5) "May"]
[(6) "June"] [(7) "July"] [(8) "August"]
[(9) "September"] [(10) "October"] [(11) "November"]
[else ""])))
(define day/number->string
(lambda (x)
(case x
[(0) "Sunday"]
[(1) "Monday"]
[(2) "Tuesday"]
[(3) "Wednesday"]
[(4) "Thursday"]
[(5) "Friday"]
[(6) "Saturday"]
[else ""])))
(define date->string
(case-lambda
[(date) (date->string date #f)]
[(date time?)
(let* ((add-zero (lambda (n) (if (< n 10)
(string-append "0" (number->string n))
(number->string n))))
(year (number->string (date-year date)))
(num-month (number->string (date-month date)))
(week-day (day/number->string (date-week-day date)))
(week-day-num (date-week-day date))
(month (month/number->string (date-month date)))
(day (number->string (date-day date)))
(day-th (if (<= 11 (date-day date) 13)
"th"
(case (modulo (date-day date) 10)
[(1) "st"]
[(2) "nd"]
[(3) "rd"]
[(0 4 5 6 7 8 9) "th"])))
(hour (date-hour date))
(am-pm (if (> hour 12) "pm" "am"))
(hour24 (add-zero hour))
(hour12 (if (> hour 12)
(number->string (- hour 12))
(number->string hour)))
(minute (add-zero (date-minute date)))
(second (add-zero (date-second date))))
(let-values
([(day time)
(case (date-display-format)
[(american)
(values (list week-day ", " month " " day day-th ", " year)
(list " " hour12 ":" minute ":" second am-pm))]
[(chinese)
(values
(list year "/" num-month "/" day
" xingqi" (case (date-week-day date)
[(0) "ri"]
[(1) "yi"]
[(2) "er"]
[(3) "san"]
[(4) "si"]
[(5) "wu"]
[(6) "liu"]
[else ""]))
(list " " hour24 ":" minute ":" second))]
[(indian)
(values (list day "-" num-month "-" year)
(list " " hour12 ":" minute ":" second am-pm))]
[(german)
(values (list day ". " month " " year)
(list ", " hour24 "." minute))]
[(irish)
(values (list week-day ", " day day-th " " month " " year)
(list ", " hour12 ":" minute am-pm))]
[(julian)
(values (list (julian/scalinger->string
(date->julian/scalinger date)))
(list ", " hour24 ":" minute ":" second))]
[else (error 'date->string "unknown date-display-format: ~s"
(date-display-format))])])
(apply string-append (if time?
(append day time)
day))))]))
(define leap-year?
(lambda (year)
(or (= 0 (modulo year 400))
(and (= 0 (modulo year 4))
(not (= 0 (modulo year 100)))))))
;; it's not clear what months mean in this context -- use days
(define-struct date-offset (second minute hour day year))
(define date-
(lambda (date1 date2)
(let* ((second (- (date-second date1) (date-second date2)))
(minute (+ (- (date-minute date1) (date-minute date2))
(if (< second 0) -1 0)))
(hour (+ (- (date-hour date1) (date-hour date2))
(if (< minute 0) -1 0)
(cond [(equal? (date-dst? date1) (date-dst? date2)) 0]
[(date-dst? date1) -1]
[(date-dst? date2) 1])))
(day (+ (- (date-year-day date1) (date-year-day date2))
(if (< hour 0) -1 0)))
(year (+ (- (date-year date1) (date-year date2))
(if (< day 0) -1 0)))
(fixup (lambda (s x) (if (< s 0) (+ s x) s))))
(make-date-offset (fixup second 60)
(fixup minute 60)
(fixup hour 24)
(fixup day (if (leap-year? (date-year date1)) 366 365))
year))))
(define date-offset->string
(let ((first car)
(second cadr))
(case-lambda
[(date) (date-offset->string date #f)]
[(date seconds?)
(let* ((fields (list (list (date-offset-year date) "year")
(list (date-offset-day date) "day")
(list (date-offset-hour date) "hour")
(list (date-offset-minute date) "minute")
(list (if seconds? (date-offset-second date) 0) "second")))
(non-zero-fields (foldl (lambda (x l)
(if (= 0 (first x))
l
(cons x l)))
null
fields))
(one-entry (lambda (b)
(string-append
(number->string (first b))
" "
(second b)
(if (= 1 (first b)) "" "s")))))
(cond
[(null? non-zero-fields) ""]
[(null? (cdr non-zero-fields)) (one-entry (car non-zero-fields))]
[else (foldl (lambda (b string)
(cond
[(= 0 (first b)) string]
[(string=? string "")
(string-append "and "
(one-entry b)
string)]
[else (string-append (one-entry b) ", " string)]))
""
non-zero-fields)]))])))
(define days-per-month
(lambda (year month)
(cond
[(and (= month 2) (leap-year? year)) 29]
[(= month 2) 28]
[(<= month 7) (+ 30 (modulo month 2))]
[else (+ 30 (- 1 (modulo month 2)))])))
(define build-date
(lambda (second minute hour day month year dst?)
(letrec ([week-day 0]
[find-year-day
(lambda (m)
(if (= m 0)
(sub1 day)
(+ (days-per-month year m)
(find-year-day (sub1 m)))))])
(make-date second minute hour day month year
week-day (find-year-day (sub1 month)) dst?))))
(define find-extreme-date-seconds
(lambda (start offset)
(let/ec found
(letrec ([find-between
(lambda (lo hi)
(let ([mid (floor (/ (+ lo hi) 2))])
(if (or (and (positive? offset) (= lo mid))
(and (negative? offset) (= hi mid)))
(found lo)
(let ([mid-ok?
(with-handlers ([void (lambda (exn) #f)])
(seconds->date mid)
#t)])
(if mid-ok?
(find-between mid hi)
(find-between lo mid))))))])
(let loop ([lo start][offset offset])
(let ([hi (+ lo offset)])
(with-handlers ([void
(lambda (exn)
; failed - must be between lo & hi
(find-between lo hi))])
(seconds->date hi))
; succeeded; double offset again
(loop hi (* 2 offset))))))))
(define get-min-seconds
(let ([d (delay (find-extreme-date-seconds (current-seconds) -1))])
(lambda ()
(force d))))
(define get-max-seconds
(let ([d (delay (find-extreme-date-seconds (current-seconds) 1))])
(lambda ()
(force d))))
(define find-seconds
(lambda (sec min hour day month year)
(let ([signal-error
(lambda (msg)
(error 'find-secs (string-append
msg
" (inputs: ~a ~a ~a ~a ~a ~a)")
sec min hour day month year))])
(let loop ([below-secs (get-min-seconds)]
[secs (floor (/ (+ (get-min-seconds) (get-max-seconds)) 2))]
[above-secs (get-max-seconds)])
(let* ([date (seconds->date secs)]
[compare
(let loop ([inputs (list year month day
hour min sec)]
[tests (list (date-year date)
(date-month date)
(date-day date)
(date-hour date)
(date-minute date)
(date-second date))])
(cond
[(null? inputs) 'equal]
[else (let ([input (car inputs)]
[test (car tests)])
(if (= input test)
(loop (cdr inputs) (cdr tests))
(if (<= input test)
'input-smaller
'test-smaller)))]))])
; (printf "~a ~a ~a~n" compare secs (date->string date))
(cond
[(eq? compare 'equal) secs]
[(or (= secs below-secs) (= secs above-secs))
(signal-error "non-existant date")]
[(eq? compare 'input-smaller)
(loop below-secs (floor (/ (+ secs below-secs) 2)) secs)]
[(eq? compare 'test-smaller)
(loop secs (floor (/ (+ above-secs secs) 2)) above-secs)]))))))
;; date->julian/scalinger :
;; date -> number [julian-day]
;; Note: This code is correct until 2099 CE Gregorian
(define (date->julian/scalinger date)
(let ((day (date-day date))
(month (date-month date))
(year (date-year date)))
(let ((year (+ 4712 year)))
(let ((year (if (< month 3) (sub1 year) year)))
(let ((cycle-number (quotient year 4))
(cycle-position (remainder year 4)))
(let ((base-day (+ (* 1461 cycle-number) (* 365 cycle-position))))
(let ((month-day-number (case month
((3) 0)
((4) 31)
((5) 61)
((6) 92)
((7) 122)
((8) 153)
((9) 184)
((10) 214)
((11) 245)
((12) 275)
((1) 306)
((2) 337))))
(let ((total-days (+ base-day month-day-number day)))
(let ((total-days/march-adjustment (+ total-days 59)))
(let ((gregorian-adjustment (cond
((< year 1700) 11)
((< year 1800) 12)
(else 13))))
(let ((final-date (- total-days/march-adjustment
gregorian-adjustment)))
final-date)))))))))))
;; julian/scalinger->string :
;; number [julian-day] -> string [julian-day-format]
(define (julian/scalinger->string julian-day)
(apply string-append
(cons "JD "
(reverse
(let loop ((reversed-digits (map number->string
(let loop ((jd julian-day))
(if (zero? jd) null
(cons (remainder jd 10)
(loop (quotient jd 10))))))))
(cond
((or (null? reversed-digits)
(null? (cdr reversed-digits))
(null? (cdr (cdr reversed-digits))))
(list (apply string-append reversed-digits)))
(else (cons (apply string-append
(list " "
(caddr reversed-digits)
(cadr reversed-digits)
(car reversed-digits)))
(loop (cdr (cdr (cdr reversed-digits))))))))))))
)

11
collects/mzlib/dates.ss Normal file
View File

@ -0,0 +1,11 @@
(begin-elaboration-time
(require-library "functios.ss"))
(define-signature mzlib:date^
(date->string
date-display-format
find-seconds
date->julian/scalinger
julian/scalinger->string))

7
collects/mzlib/dateu.ss Normal file
View File

@ -0,0 +1,7 @@
(require-library "dates.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:date@ (require-library-unit/sig "dater.ss"))

61
collects/mzlib/defstru.ss Normal file
View File

@ -0,0 +1,61 @@
(define-macro define-structure
(lambda rest
`(define-const-structure ,@rest)))
(define-macro define-const-structure
(lambda (name-and-fields . fields-with-defaults-list)
(let ([fields-with-defaults
(if (null? fields-with-defaults-list)
fields-with-defaults-list
(if (and (pair? fields-with-defaults-list)
(null? (cdr fields-with-defaults-list)))
(car fields-with-defaults-list)
(error 'define-const-structure "bad specification: ~s"
(cons name-and-fields fields-with-defaults-list))))]
[strip-id
(lambda (id)
(cond
[(symbol? id) id]
[(and (pair? id)
(pair? (cdr id))
(null? (cddr id))
(eq? (car id) '!)
(symbol? (cadr id)))
(cadr id)]
[else
(error 'define-const-structure "bad field name: ~a" id)]))]
[check-id
(lambda (x)
(if (not (symbol? x))
(error 'define-const-structure "bad structure name: ~a" x)
x))])
(if (not (list? name-and-fields))
(error 'define-const-structure "bad structure form: ~a" name-and-fields))
(if (not (list? fields-with-defaults))
(error 'define-const-structure "bad defaults structure form: ~a"
fields-with-defaults))
(if (null? fields-with-defaults)
`(define-struct ,(check-id (car name-and-fields))
,(map strip-id (cdr name-and-fields)))
(let ([gs (gensym)]
[maker (string->symbol
(string-append "make-"
(symbol->string (check-id (car name-and-fields)))))]
[args (map strip-id (cdr name-and-fields))])
`(begin
(define-struct ,(car name-and-fields)
,(append args
(map (lambda (x)
(if (and (pair? x)
(pair? (cdr x))
(null? (cddr x)))
(strip-id (car x))
(error 'define-const-structure "bad name-value pair: ~s"
x)))
fields-with-defaults)))
(let ([,gs ,maker])
(set! ,maker
(lambda ,args
(,gs ,@args ,@(map cadr fields-with-defaults)))))))))))

13
collects/mzlib/file.ss Normal file
View File

@ -0,0 +1,13 @@
(require-library "fileu.ss")
(require-library "functio.ss")
(require-library "string.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:file^
mzlib:file@
#f
mzlib:string^
mzlib:function^)

218
collects/mzlib/filer.ss Normal file
View File

@ -0,0 +1,218 @@
(unit/sig
mzlib:file^
(import (s : mzlib:string^) (f : mzlib:function^))
(define build-relative-path
(lambda (p . args)
(if (relative-path? p)
(apply build-path p args)
(error 'build-relative-path "base path ~s is absolute" p))))
(define build-absolute-path
(lambda (p . args)
(if (relative-path? p)
(error 'build-absolute-path "base path ~s is relative" p)
(apply build-path p args))))
; Note that normalize-path does not normalize the case
(define normalize-path
(letrec ([resolve-all
(lambda (path wrt)
(let ([orig-path (if (and wrt (not (complete-path? path)))
(path->complete-path path wrt)
path)])
(let loop ([full-path orig-path])
(let ([resolved (resolve-path full-path)])
(if (string=? resolved full-path)
(do-normalize-path resolved #f)
(let ([path (if (relative-path? resolved)
(build-path
(let-values ([(base name dir?) (split-path full-path)])
base)
resolved)
resolved)])
(if (string=? path orig-path)
(error 'normalize-path "circular reference at ~s" path)
(loop path))))))))]
[resolve
(lambda (path)
(if (string=? path (resolve-path path))
path
(resolve-all path #f)))]
[normalize-path
(case-lambda
[(orig-path) (do-normalize-path orig-path (current-directory))]
[(orig-path wrt)
(unless (complete-path? wrt)
(raise-type-error 'normalize-path "complete path" wrt))
(do-normalize-path orig-path wrt)])]
[error-not-a-dir
(lambda (path)
(error 'normalize-path
"~s (within the input path) is not a directory or does not exist"
path))]
[do-normalize-path
(lambda (orig-path wrt)
(let normalize ([path (expand-path orig-path)])
(let-values ([(base name dir?) (split-path path)])
(cond
[(eq? name 'up)
(let up ([base (if (eq? base 'relative)
wrt
(resolve-all base wrt))])
(if (directory-exists? base)
(let-values ([(prev name dir?) (split-path base)])
(cond
[(not prev)
(error 'normalize-path
"root has no parent directory: ~s"
orig-path)]
[else
(let ([prev
(if (eq? prev 'relative)
wrt
(normalize prev))])
(cond
[(eq? name 'same) (up prev)]
[(eq? name 'up) (up (up prev))]
[else prev]))]))
(error-not-a-dir base)))]
[(eq? name 'same)
(cond
[(eq? base 'relative) wrt]
[else (let ([n (normalize base)])
(if (directory-exists? n)
n
(error-not-a-dir n)))])]
[else
(cond
[(not base) (path->complete-path path)]
[else (let* ([base (if (eq? base 'relative)
(normalize wrt)
(normalize base))]
[path (if (directory-exists? base)
(build-path base name)
(error-not-a-dir base))]
[resolved (expand-path (resolve path))])
(cond
[(relative-path? resolved)
(normalize (build-path base resolved))]
[(complete-path? resolved)
resolved]
[else (path->complete-path resolved base)]))])]))))])
normalize-path))
; Argument must be in normal form
(define explode-path
(lambda (orig-path)
(let loop ([path orig-path][rest '()])
(let-values ([(base name dir?) (split-path path)])
(if (or (and base
(not (string? base)))
(not (string? name)))
(error 'explode-path "input was not in normal form: ~s" orig-path))
(if base
(loop base (cons name rest))
(cons name rest))))))
; Arguments must be in normal form
(define find-relative-path
(lambda (directory filename)
(let ([dir (explode-path directory)]
[file (explode-path filename)])
(if (not (string=? (car dir) (car file)))
filename
(let loop ([dir (cdr dir)][file (cdr file)])
(cond
[(null? dir) (if (null? file) filename (apply build-path file))]
[(null? file) (apply build-path (map (lambda (x) 'up) dir))]
[(string=? (car dir) (car file))
(loop (cdr dir) (cdr file))]
[else
(apply build-path
(append (map (lambda (x) 'up) dir)
file))]))))))
(define file-name-from-path
(lambda (name)
(let-values ([(base file dir?) (split-path name)])
(if (and (not dir?) (string? file))
file
#f))))
(define path-only
(lambda (name)
(let-values ([(base file dir?) (split-path name)])
(cond
[dir? name]
[(string? base) base]
[else #f]))))
; name can be any string; we just look for a dot
(define filename-extension
(lambda (name)
(let* ([len (string-length name)]
[extension
(let loop ([p (sub1 len)])
(cond
[(negative? p) #f]
[(char=? (string-ref name p) #\.)
(substring name (add1 p) len)]
[else (loop (sub1 p))]))])
(if extension
(s:string-lowercase! extension))
extension)))
(define (delete-directory/files path)
(cond
[(or (link-exists? path) (file-exists? path))
(unless (delete-file path)
(error 'delete-directory/files
"error deleting file or link: ~a" path))]
[(directory-exists? path)
(for-each (lambda (e) (delete-directory/files (build-path path e)))
(directory-list path))
(unless (delete-directory path)
(error 'delete-directory/files
"error deleting a directory: ~a" path))]
[else (error 'delete-directory/files
"encountered ~a, neither a file nor a directory"
path)]))
(define (make-directory* dir)
(let-values ([(base name dir?) (split-path dir)])
(when (and (string? base)
(not (directory-exists? base)))
(make-directory* base))
(make-directory dir)))
(define make-temporary-file
(case-lambda
[(template)
(let ([tmpdir (find-system-path 'temp-dir)])
(let loop ([s (current-seconds)][ms (current-milliseconds)])
(let ([name (build-path tmpdir (format template (format "~a~a" s ms)))])
(with-handlers ([exn:i/o:filesystem? (lambda (x)
(if (file-exists? name)
;; too slow
(loop s (add1 ms))
;; It's something else; give up
(raise x)))])
(close-output-port (open-output-file name))
name))))]
[() (make-temporary-file "mztmp~a")]))
(define find-library
(case-lambda
[(name) (find-library name "mzlib")]
[(name collection . cp)
(let ([dir (with-handlers ([void (lambda (exn) #f)])
(apply collection-path collection cp))])
(if dir
(let ([file (build-path dir name)])
(if (file-exists? file)
file
#f))
#f))])))

18
collects/mzlib/files.ss Normal file
View File

@ -0,0 +1,18 @@
(begin-elaboration-time
(require-library "functios.ss")
(require-library "strings.ss"))
(define-signature mzlib:file^
(find-relative-path
explode-path
normalize-path
build-absolute-path
build-relative-path
filename-extension
file-name-from-path
path-only
delete-directory/files
make-directory*
make-temporary-file
find-library))

8
collects/mzlib/fileu.ss Normal file
View File

@ -0,0 +1,8 @@
(require-library "files.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:file@ (require-library-unit/sig "filer.ss"))

View File

@ -0,0 +1,8 @@
(require-library "functiou.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:function^
mzlib:function@)

View File

@ -0,0 +1,2 @@
(require-library "functio.ss")

317
collects/mzlib/functior.ss Normal file
View File

@ -0,0 +1,317 @@
(unit/sig
mzlib:function^
(import)
(define true #t)
(define false #f)
(define identity (polymorphic (lambda (x) x)))
(define compose
(polymorphic
(case-lambda
[(f) (if (procedure? f) f (raise-type-error 'compose "procedure" f))]
[(f g)
(let ([f (compose f)]
[g (compose g)])
(if (eqv? 1 (arity f)) ; optimize: don't use call-w-values
(if (eqv? 1 (arity g)) ; optimize: single arity everywhere
(lambda (x) (f (g x)))
(lambda args (f (apply g args))))
(if (eqv? 1 (arity g)) ; optimize: single input
(lambda (a)
(call-with-values
(lambda () (g a))
f))
(lambda args
(call-with-values
(lambda () (apply g args))
f)))))]
[(f . more)
(let ([m (apply compose more)])
(compose f m))])))
(define quicksort
(polymorphic
(lambda (l less-than)
(let* ([v (list->vector l)]
[count (vector-length v)])
(let loop ([min 0][max count])
(if (< min (sub1 max))
(let ([pval (vector-ref v min)])
(let pivot-loop ([pivot min]
[pos (add1 min)])
(if (< pos max)
(let ([cval (vector-ref v pos)])
(if (less-than cval pval)
(begin
(vector-set! v pos (vector-ref v pivot))
(vector-set! v pivot cval)
(pivot-loop (add1 pivot) (add1 pos)))
(pivot-loop pivot (add1 pos))))
(if (= min pivot)
(loop (add1 pivot) max)
(begin
(loop min pivot)
(loop pivot max))))))))
(vector->list v)))))
(define ignore-errors
(polymorphic
(lambda (thunk)
(let/ec escape
(with-handlers ([void (lambda (x) (escape (void)))])
(thunk))))))
(define remove
(polymorphic
(letrec ([rm (case-lambda
[(item list) (rm item list equal?)]
[(item list equal?)
(let loop ([list list])
(cond
[(null? list) ()]
[(equal? item (car list)) (cdr list)]
[else (cons (car list)
(loop (cdr list)))]))])])
rm)))
(define remq
(polymorphic
(lambda (item list)
(remove item list eq?))))
(define remv
(polymorphic
(lambda (item list)
(remove item list eqv?))))
(define remove*
(polymorphic
(case-lambda
[(l r equal?)
(if (null? l)
r
(remove* (cdr l) (remove (car l) r equal?) equal?))]
[(l r) (remove* l r equal?)])))
(define remq*
(polymorphic
(lambda (l r)
(remove* l r eq?))))
(define remv*
(polymorphic
(lambda (l r)
(remove* l r eqv?))))
;; fold : ((A B -> B) B (listof A) -> B)
;; fold : ((A1 ... An B -> B) B (listof A1) ... (listof An) -> B)
;; foldl builds "B" from the beginning of the list to the end of the
;; list and foldr builds the "B" from the end of the list to the
;; beginning of the list.
(define mapadd
(polymorphic
(lambda (f l last)
(letrec ((helper
(lambda (l)
(cond
[(null? l) (list last)]
[else (cons (f (car l)) (helper (cdr l)))]))))
(helper l)))))
(define foldl
(polymorphic
(letrec ((fold-one
(lambda (f init l)
(letrec ((helper
(lambda (init l)
(cond
[(null? l) init]
[else (helper (f (car l) init) (cdr l))]))))
(helper init l))))
(fold-n
(lambda (f init l)
(cond
[(ormap null? l)
(if (andmap null? l)
init
(error 'foldl "received non-equal length input lists"))]
[else (fold-n
f
(apply f (mapadd car l init))
(map cdr l))]))))
(case-lambda
[(f init l) (fold-one f init l)]
[(f init l . ls) (fold-n f init (cons l ls))]))))
(define foldr
(polymorphic
(letrec ((fold-one
(lambda (f init l)
(letrec ((helper
(lambda (init l)
(cond
[(null? l) init]
[else (f (car l) (helper init (cdr l)))]))))
(helper init l))))
(fold-n
(lambda (f init l)
(cond
[(ormap null? l)
(if (andmap null? l)
init
(error 'foldr "received non-equal length input lists"))]
[else (apply f
(mapadd car l
(fold-n f init (map cdr l))))]))))
(case-lambda
[(f init l) (fold-one f init l)]
[(f init l . ls) (fold-n f init (cons l ls))]))))
(define make-find
(lambda (name whole-list?)
(polymorphic
(lambda (f list)
(unless (and (procedure? f)
(procedure-arity-includes? f 1))
(raise-type-error name "procedure (arity 1)" f))
(let loop ([l list])
(cond
[(null? l) #f]
[(not (pair? l))
(raise (make-exn:application:mismatch
(format "~a: second argument must be a (proper) list; given ~e" name list)
(current-continuation-marks)
list))]
[(f (car l)) (if whole-list? l (car l))]
[else (loop (cdr l))]))))))
(define assf
(make-find 'assf #f))
(define memf
(make-find 'memf #t))
(define filter
(polymorphic
(lambda (f list)
(unless (and (procedure? f)
(procedure-arity-includes? f 1))
(raise-type-error 'filter "procedure (arity 1)" f))
(let loop ([l list])
(cond
[(null? l) null]
[(pair? l)
(let* ([keep? (f (car l))]
[frest (loop (cdr l))])
(if keep?
(cons (car l) frest)
frest))]
[else (raise (make-exn:application:mismatch
(format "filter: second argument must be a (proper) list; given ~e" list)
(current-continuation-marks)
list))])))))
(define first (polymorphic (lambda (x)
(unless (pair? x)
(raise-type-error 'first "non-empty list" x))
(car x))))
(define second (polymorphic cadr))
(define third (polymorphic caddr))
(define fourth (polymorphic cadddr))
(define fifth (polymorphic (compose fourth cdr)))
(define sixth (polymorphic (compose fourth cddr)))
(define seventh (polymorphic (compose fourth cdddr)))
(define eighth (polymorphic (compose fourth cddddr)))
(define rest (polymorphic (lambda (x)
(unless (pair? x)
(raise-type-error 'rest "non-empty list" x))
(cdr x))))
(define build-string
(lambda (n fcn)
(unless (and (integer? n) (exact? n) (>= n 0))
(error 'build-string "~s must be an exact integer >= 0" n))
(unless (procedure? fcn)
(error 'build-string "~s must be a procedure" fcn))
(let ((str (make-string n)))
(let loop ((i 0))
(if (= i n)
str
(begin
(string-set! str i (fcn i))
(loop (add1 i))))))))
;; (build-vector n f) returns a vector 0..n-1 where the ith element is (f i).
;; The eval order is guaranteed to be: 0, 1, 2, ..., n-1.
;; eg: (build-vector 4 (lambda (i) i)) ==> #4(0 1 2 3)
(define build-vector
(polymorphic
(lambda (n fcn)
(unless (and (integer? n) (exact? n) (>= n 0))
(error 'build-vector "~s must be an exact integer >= 0" n))
(unless (procedure? fcn)
(error 'build-vector "~s must be a procedure" fcn))
(let ((vec (make-vector n)))
(let loop ((i 0))
(if (= i n) vec
(begin
(vector-set! vec i (fcn i))
(loop (add1 i)))))))))
(define build-list
(polymorphic
(lambda (n fcn)
(unless (and (integer? n) (exact? n) (>= n 0))
(error 'build-list "~s must be an exact integer >= 0" n))
(unless (procedure? fcn)
(error 'build-list "~s must be a procedure" fcn))
(if (zero? n) '()
(let ([head (list (fcn 0))])
(let loop ([i 1] [p head])
(if (= i n) head
(begin
(set-cdr! p (list (fcn i)))
(loop (add1 i) (cdr p))))))))))
(define loop-until
(polymorphic
(lambda (start done? next body)
(let loop ([i start])
(unless (done? i)
(body i)
(loop (next i)))))))
(define last-pair
(polymorphic
(lambda (l)
(if (pair? l)
(if (pair? (cdr l))
(last-pair (cdr l))
l)
(raise-type-error 'last-pair "pair" l)))))
(define boolean=?
(lambda (x y)
(unless (and (boolean? x)
(boolean? y))
(raise-type-error 'boolean=?
"boolean"
(if (boolean? x) y x)))
(eq? x y)))
(define (symbol=? x y)
(unless (and (symbol? x)
(symbol? y))
(raise-type-error 'symbol=? "symbol"
(if (symbol? x) y x)))
(eq? x y))
(define cons? (lambda (x) (pair? x)))
(define empty? (lambda (x) (null? x)))
(define empty '()))

View File

@ -0,0 +1,54 @@
(begin-elaboration-time
(require-relative-library "spidey.ss"))
(define-signature mzlib:function^
(true
false
first
second
third
fourth
fifth
sixth
seventh
eighth
rest
cons?
empty
empty?
boolean=?
symbol=?
identity
compose
foldl
foldr
last-pair
remv
remq
remove
remv*
remq*
remove*
assf
memf
filter
build-string
build-vector
build-list
quicksort
loop-until
ignore-errors))

View File

@ -0,0 +1,8 @@
(require-library "functios.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:function@ (require-library-unit/sig "functior.ss"))

11
collects/mzlib/inflate.ss Normal file
View File

@ -0,0 +1,11 @@
(require-library "inflateu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:inflate^
mzlib:inflate@)

888
collects/mzlib/inflater.ss Normal file
View File

@ -0,0 +1,888 @@
(unit/sig mzlib:inflate^
(import)
#|
/* inflate.c -- Not copyrighted 1992 by Mark Adler
version c10p1, 10 January 1993 */
; Taken from the gzip source distribution
; Translated directly from C (obviously) by Matthew, April 1997
/* You can do whatever you like with this source file, though I would
prefer that if you modify it and redistribute it that you include
comments to that effect with your name and the date. Thank you.
[The history has been moved to the file ChangeLog.]
; ChangeLog is distributed with the gzip source.
*/
/*
Inflate deflated (PKZIP's method 8 compressed) data. The compression
method searches for as much of the current string of bytes (up to a
length of 258) in the previous 32K bytes. If it doesn't find any
matches (of at least length 3), it codes the next byte. Otherwise, it
codes the length of the matched string and its distance backwards from
the current position. There is a single Huffman code that codes both
single bytes (called "literals") and match lengths. A second Huffman
code codes the distance information, which follows a length code. Each
length or distance code actually represents a base value and a number
of "extra" (sometimes zero) bits to get to add to the base value. At
the end of each deflated block is a special end-of-block (EOB) literal/
length code. The decoding process is basically: get a literal/length
code; if EOB then done; if a literal, emit the decoded byte; if a
length then get the distance and emit the referred-to bytes from the
sliding window of previously emitted data.
There are (currently) three kinds of inflate blocks: stored, fixed, and
dynamic. The compressor deals with some chunk of data at a time, and
decides which method to use on a chunk-by-chunk basis. A chunk might
typically be 32K or 64K. If the chunk is uncompressible, then the
"stored" method is used. In this case, the bytes are simply stored as
is, eight bits per byte, with none of the above coding. The bytes are
preceded by a count, since there is no longer an EOB code.
If the data is compressible, then either the fixed or dynamic methods
are used. In the dynamic method, the compressed data is preceded by
an encoding of the literal/length and distance Huffman codes that are
to be used to decode this block. The representation is itself Huffman
coded, and so is preceded by a description of that code. These code
descriptions take up a little space, and so for small blocks, there is
a predefined set of codes, called the fixed codes. The fixed method is
used if the block codes up smaller that way (usually for quite small
chunks), otherwise the dynamic method is used. In the latter case, the
codes are customized to the probabilities in the current block, and so
can code it much better than the pre-determined fixed codes.
The Huffman codes themselves are decoded using a mutli-level table
lookup, in order to maximize the speed of decoding plus the speed of
building the decoding tables. See the comments below that precede the
lbits and dbits tuning parameters.
*/
/*
Notes beyond the 1.93a appnote.txt:
1. Distance pointers never point before the beginning of the output
stream.
2. Distance pointers can point back across blocks, up to 32k away.
3. There is an implied maximum of 7 bits for the bit length table and
15 bits for the actual data.
4. If only one code exists, then it is encoded using one bit. (Zero
would be more efficient, but perhaps a little confusing.) If two
codes exist, they are coded using one bit each (0 and 1).
5. There is no way of sending zero distance codes--a dummy must be
sent if there are none. (History: a pre 2.0 version of PKZIP would
store blocks with no distance codes, but this was discovered to be
too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
zero distance codes, which is sent as one code of zero bits in
length.
6. There are up to 286 literal/length codes. Code 256 represents the
end-of-block. Note however that the static length tree defines
288 codes just to fill out the Huffman codes. Codes 286 and 287
cannot be used though, since there is no length base or extra bits
defined for them. Similarly, there are up to 30 distance codes.
However, static trees define 32 codes (all 5 bits) to fill out the
Huffman codes, but the last two had better not show up in the data.
7. Unzip can check dynamic Huffman blocks for complete code sets.
The exception is that a single code would not be complete (see #4).
8. The five bits following the block type is really the number of
literal codes sent minus 257.
9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
(1+6+6). Therefore, to output three times the length, you output
three codes (1+1+1), whereas to output four times the same length,
you only need two codes (1+3). Hmm.
10. In the tree reconstruction algorithm, Code = Code + Increment
only if BitLength(i) is not zero. (Pretty obvious.)
11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
12. Note: length code 284 can represent 227-258, but length code 285
really is 258. The last length deserves its own, short code
since it gets used a lot in very redundant files. The length
258 is special since 258 - 3 (the min match length) is 255.
13. The literal/length and distance code bit lengths are read as a
single stream of lengths. It is possible (and advantageous) for
a repeat code (16, 17, or 18) to go across the boundary between
the two sets of lengths.
*/
|#
#|
/* Huffman code lookup table entry--this entry is four bytes for machines
that have 16-bit pointers (e.g. PC's in the small or medium model).
Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
means that v is a literal, 16 < e < 32 means that v is a pointer to
the next table, which codes e - 16 bits, and lastly e == 99 indicates
an unused code. If a code with e == 99 is looked up, this implies an
error in the data. */
|#
(define-struct huft (e b v))
(define (huft-copy dest src)
(set-huft-e! dest (huft-e src))
(set-huft-b! dest (huft-b src))
(set-huft-v! dest (huft-v src)))
(define (step start < end add1 f)
(let loop ([i start])
(when (< i end)
(f i)
(loop (add1 i)))))
(define (subvector v offset)
(let* ([len (- (vector-length v) offset)]
[new (make-vector len)])
(step 0 < len add1
(lambda (i)
(vector-set! new i (vector-ref v (+ i offset)))))
new))
(define (build-vector n p)
(let ([v (make-vector n)])
(step 0 < n add1 (lambda (i) (vector-set! v i (p i))))
v))
#|
/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
stream to find repeated byte strings. This is implemented here as a
circular buffer. The index is updated simply by incrementing and then
and'ing with 0x7fff (32K-1). */
|#
(define WSIZE 32768)
(define border
(vector
16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15))
(define cplens
(vector
3 4 5 6 7 8 9 10 11 13 15 17 19 23 27 31
35 43 51 59 67 83 99 115 131 163 195 227 258 0 0))
; /* note: see note #13 above about the 258 in this list. */
(define cplext
(vector
0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2
3 3 3 3 4 4 4 4 5 5 5 5 0 99 99)) ; /* 99==invalid */
(define cpdist
(vector
1 2 3 4 5 7 9 13 17 25 33 49 65 97 129 193
257 385 513 769 1025 1537 2049 3073 4097 6145
8193 12289 16385 24577))
(define cpdext
(vector
0 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6
7 7 8 8 9 9 10 10 11 11
12 12 13 13))
(define mask_bits
(vector
#x0000
#x0001 #x0003 #x0007 #x000f #x001f #x003f #x007f #x00ff
#x01ff #x03ff #x07ff #x0fff #x1fff #x3fff #x7fff #xffff))
(define lbits 9) ; /* bits in base literal/length lookup table */
(define dbits 6) ; /* bits in base distance lookup table */
; /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
(define BMAX 16) ; /* maximum bit length of any code (16 for explode) */
(define N_MAX 288) ; /* maximum number of codes in any set */
(define (inflate input-port output-port)
(define slide (make-string WSIZE))
(define wp 0)
(define (flush-output len)
; write out the data
(if (= len WSIZE)
(display slide output-port)
(display (substring slide 0 len) output-port)))
(define (check-flush)
(when (= wp WSIZE)
(flush-output WSIZE)
(set! wp 0)))
#|
/* Macros for inflate() bit peeking and grabbing.
The usage is:
NEEDBITS(j)
x = b & mask_bits[j];
DUMPBITS(j)
where NEEDBITS makes sure that b has at least j bits in it, and
DUMPBITS removes the bits from b. The macros use the variable k
for the number of bits in b. Normally, b and k are register
variables for speed, and are initialized at the beginning of a
routine that uses these macros from a global bit buffer and count.
If we assume that EOB will be the longest code, then we will never
ask for bits with NEEDBITS that are beyond the end of the stream.
So, NEEDBITS should not read any more bytes than are needed to
meet the request. Then no bytes need to be "returned" to the buffer
at the end of the last block.
However, this assumption is not true for fixed blocks--the EOB code
is 7 bits, but the other literal/length codes can be 8 or 9 bits.
(The EOB code is shorter than other codes because fixed blocks are
generally short. So, while a block always has an EOB, many other
literal/length codes have a significantly lower probability of
showing up at all.) However, by making the first table have a
lookup of seven bits, the EOB code will be found in that first
lookup, and so will not require that too many bits be pulled from
the stream.
*/
|#
(define bb 0) ; /* bit buffer */
(define bk 0) ; /* bits in bit buffer */
(define (NEEDBITS n)
(when (< bk n)
(set! bb (+ bb (arithmetic-shift (char->integer (read-char input-port)) bk)))
(set! bk (+ bk 8))
(NEEDBITS n)))
(define (DUMPBITS n)
(set! bb (arithmetic-shift bb (- n)))
(set! bk (- bk n)))
(define (GETBITS n)
(NEEDBITS n)
(begin0
bb
(DUMPBITS n)))
#|
/*
Huffman code decoding is performed using a multi-level table lookup.
The fastest way to decode is to simply build a lookup table whose
size is determined by the longest code. However, the time it takes
to build this table can also be a factor if the data being decoded
is not very long. The most common codes are necessarily the
shortest codes, so those codes dominate the decoding time, and hence
the speed. The idea is you can have a shorter table that decodes the
shorter, more probable codes, and then point to subsidiary tables for
the longer codes. The time it costs to decode the longer codes is
then traded against the time it takes to make longer tables.
This results of this trade are in the variables lbits and dbits
below. lbits is the number of bits the first level table for literal/
length codes can decode in one step, and dbits is the same thing for
the distance codes. Subsequent tables are also less than or equal to
those sizes. These values may be adjusted either when all of the
codes are shorter than that, in which case the longest code length in
bits is used, or when the shortest code is *longer* than the requested
table size, in which case the length of the shortest code in bits is
used.
There are two different values for the two tables, since they code a
different number of possibilities each. The literal/length table
codes 286 possible values, or in a flat code, a little over eight
bits. The distance table codes 30 possible values, or a little less
than five bits, flat. The optimum values for speed end up being
about one bit more than those, so lbits is 8+1 and dbits is 5+1.
The optimum values may differ though from machine to machine, and
possibly even between compilers. Your mileage may vary.
*/
|#
(define (huft_build
b ; int vector /* code lengths in bits (all assumed <= BMAX) */
n ; /* number of codes (assumed <= N_MAX) */
s ; /* number of simple-valued codes (0..s-1) */
d ; int vector /* list of base values for non-simple codes */
e ; int vector /* list of extra bits for non-simple codes */
m ; int /* maximum lookup bits, returns actual */
incomp-ok?)
; return: new-t new-m ok?
#|
/* Given a list of code lengths and a maximum table size, make a set of
tables to decode that set of codes. Return zero on success, one if
the given code set is incomplete (the tables are still built in this
case), two if the input is invalid (all zero length codes or an
oversubscribed set of lengths), and three if not enough memory. */
|#
(define c (make-vector (add1 BMAX) 0))
(define x (make-vector (add1 BMAX)))
(define v (make-vector N_MAX))
(define final-y 0)
(define t-result #f)
; (printf "n: ~s~n" n)
(let/ec return
#|
(if (= n 270)
(step 0 < n add1
(lambda (i) (printf "b[~a] = ~a~n" i (vector-ref b i)))))
|#
(step 0 < n add1
(lambda (i)
(let ([pos (vector-ref b i)])
(vector-set! c pos (add1 (vector-ref c pos))))))
(when (= n (vector-ref c 0))
; (printf "zero~n")
(return #f 0 #t))
#|
(when (= n 270)
(step 0 <= BMAX add1
(lambda (i)
(printf "c[~s]: ~s~n" i (vector-ref c i)))))
|#
; /* Find minimum and maximum length, bound m-result by those */
(let* ([j ; min-code-length
(let loop ([j 1])
(cond
[(> j BMAX) j]
[(positive? (vector-ref c j)) j]
[else (loop (add1 j))]))]
[k j]
[i ; max-code-length
(let loop ([i BMAX])
(cond
[(zero? i) 0]
[(positive? (vector-ref c i)) i]
[else (loop (sub1 i))]))]
[g i]
[l (min (max m j) i)]
[m-result l])
; (printf "min: ~s max: ~s~n" k g)
; /* Adjust last length count to fill out codes, if needed */
(let-values ([(y j)
(let loop ([y (arithmetic-shift 1 j)][j j])
(if (>= j i)
(values y j)
(let ([new-y (- y (vector-ref c j))])
(if (negative? new-y)
(begin
(error 'inflate
"bad input: more codes than bits")
(return null m-result #f))
(loop (* new-y 2) (add1 j))))))])
; (printf "loop y: ~s~n" y)
(let ([y (- y (vector-ref c i))])
(when (negative? y)
(error 'inflate "bad input: more codes than bits")
(return #f m-result #f))
; (printf "set c[~s] ~s + ~s~n" i (vector-ref c i) y)
(vector-set! c i (+ (vector-ref c i) y))
(set! final-y y)))
; /* Generate starting offsets into the value table for each length */
(vector-set! x 1 0)
(let* ([j (let loop ([i (sub1 i)][x-pos 2][c-pos 1][j 0])
(if (zero? i)
j
(let ([v (vector-ref c c-pos)])
(vector-set! x x-pos (+ j v))
(loop (sub1 i) (add1 x-pos) (add1 c-pos) (+ j v)))))])
; /* Make a table of values in order of bit lengths */
(let loop ([i 0][b-pos 0])
(let ([j (vector-ref b b-pos)])
(unless (zero? j)
(let ([xj (vector-ref x j)])
(vector-set! x j (add1 xj))
(vector-set! v xj i)))
(let ([new-i (add1 i)])
(when (< new-i n)
(loop new-i (add1 b-pos))))))
; /* Generate the Huffman codes and for each, make the table entries */
(vector-set! x 0 0) ; /* first Huffman code is zero */
(let ([v-pos 0] ; /* grab values in bit order */
[i 0] ; /* the Huffman code of length k bits for value *p */
[h -1] ; /* no tables yet--level -1 */
[w (- l)] ; /* bits decoded == (l * h) */
[u (make-vector BMAX)] ; /* table stack */
[q null] ; /* points to current table */
[z 0] ; /* number of entries in current table */
[r (make-huft 0 0 0)]) ; /* table entry for structure assignment */
; /* go through the bit lengths (k already is bits in shortest code) */
(let k-loop ([k k])
; (printf "k: ~s~n" k)
(when (<= k g)
(let ([a (vector-ref c k)])
(let a-loop ([a (sub1 a)])
(unless (negative? a)
; (printf "a: ~s~n" a)
; /* here i is the Huffman code of length k bits for value *p */
; /* make tables up to required level */
(let kwl-loop ()
(when (> k (+ w l))
(set! h (add1 h))
(set! w (+ w l)) ; /* previous table always l bits */
; /* compute minimum size table less than or equal to l bits */
(set! z (min (- g w) l)) ; /* upper limit on table size */
; (printf "z: ~s k: ~s w: ~s~n" z k w)
(let* ([j (- k w)]
[f (arithmetic-shift 1 j)])
(when (> f (add1 a)) ; /* try a k-w bit table */
; /* too few codes for k-w bit table */
(set! f (- f a 1)) ; /* deduct codes from patterns left */
; /* try smaller tables up to z bits */
(let loop ([c-pos k])
(set! j (add1 j))
(when (< j z)
(set! f (* f 2))
(let* ([c-pos (add1 c-pos)]
[cv (vector-ref c c-pos)])
(if (<= f cv)
(void) ; /* enough codes to use up j bits */
(begin
(set! f (- f cv)) ; /* else deduct codes from patterns */
(loop c-pos)))))))
(set! z (arithmetic-shift 1 j)) ; /* table entries for j-bit table */
; /* allocate and link in new table */
; (printf "alloc: ~a~n" z)
(set! q (build-vector z (lambda (i) (make-huft 0 0 0))))
(when (not t-result)
(set! t-result q))
(vector-set! u h q)
; /* connect to last table, if there is one */
(unless (zero? h)
(vector-set! x h i) ; /* save pattern for backing up */
(set-huft-b! r l) ; /* bits to dump before this table */
(set-huft-e! r (+ j 16)); /* bits in this table */
(set-huft-v! r q) ; /* pointer to this table */
(set! j (arithmetic-shift i (- l w)))
; /* connect to last table: */
(huft-copy (vector-ref (vector-ref u (sub1 h)) j) r)))
(kwl-loop)))
(set-huft-b! r (- k w)) ; cast uch (- k w) if needed
(if (>= v-pos n)
(set-huft-e! r 99) ; /* out of values--invalid code */
(let ([vv (vector-ref v v-pos)])
; (printf "*p: ~s s: ~s~n" vv s)
(if (< vv s)
(begin
(set-huft-e! r (if (< vv 256) 16 15)) ; /* 256 is end-of-block code */
(set-huft-v! r vv)) ; /* simple code is just the value */
(begin
(set-huft-e! r (vector-ref e (- vv s))) ; /* non-simple--look up in lists */
(set-huft-v! r (vector-ref d (- vv s)))))
(set! v-pos (add1 v-pos))))
; /* fill code-like entries with r */
; (printf "i: ~s w: ~s k: ~s~n" i w k)
(let ([f (arithmetic-shift 1 (- k w))]) ; /* i repeats in table every f entries */
(let loop ([j (arithmetic-shift i (- w))])
(when (< j z)
(huft-copy (vector-ref q j) r)
(loop (+ j f)))))
; /* backwards increment the k-bit code i */
(let loop ([j (arithmetic-shift 1 (sub1 k))])
(if (positive? (bitwise-and i j))
(begin
(set! i (bitwise-xor i j))
(loop (arithmetic-shift j -1)))
(set! i (bitwise-xor i j))))
; /* backup over finished tables */
(let loop ()
(unless (= (vector-ref x h) (bitwise-and i (sub1 (arithmetic-shift 1 w))))
(set! h (sub1 h)) ; /* don't need to update q */
(set! w (- w l))
(loop)))
(a-loop (sub1 a))))
(k-loop (add1 k)))))
; /* Return #f as third if we were given an incomplete table */
; (printf "done: ~s ~s~n" final-y g)
(let ([ok? (or incomp-ok?
(not (and (not (zero? final-y))
(not (= g 1)))))])
(unless ok?
(error 'inflate "incomplete table"))
(values t-result m-result ok?)))))))
(define (inflate_codes
tl ; vector of hufts ; /* literal/length tables */
td ; vector of hufts ; /* distance decoder tables */
bl ; /* number of bits decoded by tl */
bd) ; /* number of bits decoded by td[] */
; /* inflate (decompress) the codes in a deflated (compressed) block.
; Return an error code or zero if it all goes ok. */
; /* inflate the coded data */
; /* precompute masks for speed */
(define ml (vector-ref mask_bits bl))
(define md (vector-ref mask_bits bd))
(define t (void))
(define e 0)
(define n 0)
(define d 0)
(let/ec return
(define (jump-to-next)
(let loop ()
(when (= e 99)
(error 'inflate "bad inflate code")
(return #f))
(DUMPBITS (huft-b t))
(set! e (- e 16))
(NEEDBITS e)
(set! t (vector-ref (huft-v t) (bitwise-and bb (vector-ref mask_bits e))))
(set! e (huft-e t))
(when (> e 16)
(loop))))
(let loop () ; /* do until end of block */
(NEEDBITS bl)
(set! t (vector-ref tl (bitwise-and bb ml)))
; (printf "t->e: ~s t->b: ~s~n" (huft-e t) (huft-b t))
(set! e (huft-e t))
(if (> e 16)
(jump-to-next))
(DUMPBITS (huft-b t))
; (printf "e: ~s~n" e)
(if (= e 16) ; /* then it's a literal */
(begin
(string-set! slide wp (integer->char (huft-v t)))
(set! wp (add1 wp))
(check-flush))
(begin ; /* it's an EOB or a length */
; /* exit if end of block */
(when (= e 15)
(return #t))
; /* get length of block to copy */
(NEEDBITS e)
(set! n (+ (huft-v t) (bitwise-and bb (vector-ref mask_bits e))))
(DUMPBITS e)
; (printf "n: ~s bb: ~s md: ~s~n" n bb md)
; /* decode distance of block to copy */
(NEEDBITS bd)
(set! t (vector-ref td (bitwise-and bb md)))
; (printf "t->e: ~s t->b: ~s~n" (huft-e t) (huft-b t))
(set! e (huft-e t))
; (printf "e: ~s~n" e)
(when (> e 16)
(jump-to-next))
(DUMPBITS (huft-b t))
; (printf "e: ~s~n" e)
(NEEDBITS e)
(set! d (modulo (- wp (huft-v t) (bitwise-and bb (vector-ref mask_bits e))) WSIZE))
(DUMPBITS e)
; (printf "wp: ~s t->v: ~s d: ~s~n" wp (huft-v t) d)
; /* do the copy */
(let loop ()
(set! d (bitwise-and d (sub1 WSIZE)))
(set! e (min n (- WSIZE (max d wp))))
(set! n (- n e))
(let loop ()
(string-set! slide wp (string-ref slide d))
(set! wp (add1 wp))
(set! d (add1 d))
(set! e (sub1 e))
(unless (zero? e)
(loop)))
(check-flush)
(unless (zero? n)
(loop)))))
(loop))))
(define (inflate_stored)
; /* "decompress" an inflated type 0 (stored) block. */
(let/ec return
; /* go to byte boundary */
(DUMPBITS (bitwise-and bk 7))
; /* get the length and its complement */
(NEEDBITS 16)
(let ([n (bitwise-and bb #xffff)])
(DUMPBITS 16)
(NEEDBITS 16)
(unless (= n (bitwise-and bb #xffff))
(error 'inflate "error in compressed data")
(return #f)) ; /* error in compressed data */
(DUMPBITS 16)
; /* read and output the compressed data */
(let loop ([n n])
(when (positive? n)
(NEEDBITS 8)
(string-set! slide wp (integer->char (bitwise-and bb #xff)))
(set! wp (add1 wp))
(check-flush)
(DUMPBITS 8)
(loop (sub1 n))))
#t)))
(define (inflate_fixed)
; /* decompress an inflated type 1 (fixed Huffman codes) block. We should
; either replace this with a custom decoder, or at least precompute the
; Huffman tables. */
(define l (make-vector 288))
(step 0 < 144 add1 (lambda (i) (vector-set! l i 8)))
(step 144 < 256 add1 (lambda (i) (vector-set! l i 9)))
(step 256 < 280 add1 (lambda (i) (vector-set! l i 7)))
(step 280 < 288 add1 (lambda (i) (vector-set! l i 8)))
(let-values ([(tl bl ok?)
(huft_build l 288 257 cplens cplext 7 #f)])
(if (not ok?)
#f
(begin
(step 0 < 30 add1 (lambda (i) (vector-set! l i 5)))
(let-values ([(td bd ok?)
(huft_build l 30 0 cpdist cpdext 5 #t)])
(if (not ok?)
#f
; /* decompress until an end-of-block code */
(inflate_codes tl td bl bd)))))))
(define (inflate_dynamic)
; /* decompress an inflated type 2 (dynamic Huffman codes) block. */
(let/ec return
; /* read in table lengths */
; (define junk1 (begin (NEEDBITS 5) (printf "~s ~s~n" bb bk)))
(define nl (+ 257 (bitwise-and (GETBITS 5) #x1f)))
; (define junk2 (begin (NEEDBITS 5) (printf "~s ~s~n" bb bk)))
(define nd (+ 1 (bitwise-and (GETBITS 5) #x1f)))
; (define junk3 (begin (NEEDBITS 4) (printf "~s ~s~n" bb bk)))
(define nb (+ 4 (bitwise-and (GETBITS 4) #xf)))
; (define junk8 (printf "~s ~s ~s~n" nl nd nb))
(define ll (make-vector (+ 286 30)))
(define i 0)
(define l 0)
(if (or (> nl 286) (> nd 30))
(begin
(error 'inflate "bad lengths")
#f) ; /* bad lengths */
(begin
; /* read in bit-length-code lengths */
(step 0 < nb add1
(lambda (j)
(vector-set! ll (vector-ref border j) (bitwise-and (GETBITS 3) 7))))
(step nb < 19 add1
(lambda (j)
(vector-set! ll (vector-ref border j) 0)))
; /* build decoding table for trees--single level, 7 bit lookup */
(let-values ([(tl bl ok?)
(huft_build ll 19 19 null null 7 #f)])
(if (not ok?)
#f
(begin
; /* read in literal and distance code lengths */
(let ([n (+ nl nd)]
[m (vector-ref mask_bits bl)])
; (printf "bl: ~s~n" bl)
(set! i 0)
(set! l 0)
(let loop ()
(when (< i n)
(NEEDBITS bl)
(let* ([pos (bitwise-and bb m)]
[td (vector-ref tl pos)]
[dmp (huft-b td)]
[j (huft-v td)]
[set-lit
(lambda (j l)
(when (> (+ i j) n)
(error 'inflate "bad hop")
(return #f))
(let loop ([j j])
(unless (zero? j)
(vector-set! ll i l)
(set! i (add1 i))
(loop (sub1 j)))))])
(DUMPBITS dmp)
; (printf "pos: ~s j: ~s l: ~s i: ~s~n" pos j l i)
(cond
[(< j 16) ; /* length of code in bits (0..15) */
(vector-set! ll i j)
(set! l j) ; /* save last length in l */
(set! i (add1 i))]
[(= j 16) ; /* repeat last length 3 to 6 times */
(let ([j (+ 3 (bitwise-and (GETBITS 2) 3))])
(set-lit j l))]
[(= j 17) ; /* 3 to 10 zero length codes */
(let ([j (+ 3 (bitwise-and (GETBITS 3) 7))])
(set-lit j 0)
(set! l 0))]
[else ; /* j == 18: 11 to 138 zero length codes */
(let ([j (+ 11 (bitwise-and (GETBITS 7) #x7f))])
(set-lit j 0)
(set! l 0))]))
(loop)))
; /* build the decoding tables for literal/length and distance codes */
(let-values ([(tl bl ok?)
(huft_build ll nl 257 cplens cplext lbits #f)])
(if (not ok?)
(begin
(error 'inflate "incomplete code set")
#f) ; /* incomplete code set */
(let-values ([(td bd ok?)
(huft_build (subvector ll nl) nd 0 cpdist cpdext dbits #f)])
(if (not ok?)
(begin
(error 'inflate "incomplete code set")
#f) ; /* incomplete code set */
; /* decompress until an end-of-block code */
(inflate_codes tl td bl bd)))))))))))))
(define (inflate_block)
; return values: /* last block flag */ ok?
; /* decompress an inflated block */
(define e-result (bitwise-and (GETBITS 1) 1))
; /* read in block type */
(define t (bitwise-and (GETBITS 2) 3))
(values e-result
(case t
[(2) (inflate_dynamic)]
[(0) (inflate_stored)]
[(1) (inflate_fixed)]
[else (error 'inflate "unknown inflate type")
#f])))
;;;;;;;;;;;;;;;;;;;;;;;;
; inflate starts here
;;;;;;;;;;;;;;;;;;;;;;;;
; /* decompress an inflated entry */
; /* initialize window, bit buffer */
(set! wp 0)
(set! bk 0)
(set! bb 0)
; /* decompress until the last block */
(let loop ()
(let-values ([(e ok?) (inflate_block)])
(if ok?
(if (zero? e)
(loop)
(begin
; /* Undo too much lookahead. The next read will be byte aligned so we
; * can discard unused bits in the last meaningful byte.
; */
(let loop ()
(when (> bk 8)
(set! bk (- bk 8))
; do something: inptr--
(loop)))
(flush-output wp)
#t = (void)))
#f))))
(define (make-small-endian . chars)
(let loop ([chars chars][n 0][mult 1])
(if (null? chars)
n
(loop (cdr chars)
(+ n (* mult (char->integer (car chars))))
(* mult 256)))))
(define (do-gunzip in out name-filter)
(let ([header1 (read-char in)]
[header2 (read-char in)])
(unless (and (char=? header1 #\037) (char=? header2 #\213))
(error 'gnu-unzip "bad header")))
(let ([compression-type (read-char in)])
(unless (char=? compression-type #\010)
(error 'gnu-unzip "unknown compression type")))
(let* ([flags (char->integer (read-char in))]
[ascii? (positive? (bitwise-and flags #b1))]
[continuation? (positive? (bitwise-and flags #b10))]
[has-extra-field? (positive? (bitwise-and flags #b100))]
[has-original-filename? (positive? (bitwise-and flags #b1000))]
[has-comment? (positive? (bitwise-and flags #b10000))]
[encrypted? (positive? (bitwise-and flags #b100000))])
(when encrypted?
(error 'gnu-unzip "cannot unzip encrypted file"))
(when continuation?
(error 'gnu-unzip "cannot handle multi-part files"))
(let ([unix-mod-time (make-small-endian (read-char in) (read-char in)
(read-char in) (read-char in))]
[extra-flags (read-char in)]
[source-os (read-char in)])
(when continuation?
(let ([part-number (make-small-endian (read-char in) (read-char in))])
'ok))
(when has-extra-field?
(let ([len (make-small-endian (read-char in) (read-char in))])
(let loop ([len len])
(unless (zero? len)
(read-char in)
(loop (sub1 len))))))
(let* ([read-null-term-string
(lambda ()
(let loop ([s null])
(let ([r (read-char in)])
(if (char=? #\null r)
(list->string (reverse! s))
(loop (cons r s))))))]
[original-filename (and has-original-filename?
(read-null-term-string))]
[comment (and has-comment? (read-null-term-string))])
(when encrypted?
(let loop ([n 12])
(unless (zero? n)
(read-char in)
(loop (sub1 n)))))
(let-values ([(out close?) (if out
(values out #f)
(let-values ([(fn orig?)
(if original-filename
(values original-filename #t)
(values "unzipped" #f))])
(values (open-output-file (name-filter fn orig?) 'truncate)
#t)))])
(dynamic-wind
void
(lambda () (inflate in out))
(lambda () (when close? (close-output-port out)))))))))
(define (gunzip-through-ports in out)
(do-gunzip in out void))
(define gunzip
(case-lambda
[(src) (gunzip src (lambda (name from-file?) name))]
[(src name-filter)
(let ([in (open-input-file src 'binary)])
(dynamic-wind
void
(lambda () (do-gunzip in #f name-filter))
(lambda () (close-input-port in))))]))
)

View File

@ -0,0 +1,4 @@
(define-signature mzlib:inflate^
(inflate
gunzip-through-ports
gunzip))

View File

@ -0,0 +1,7 @@
(require-library "inflates.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:inflate@ (require-library-unit/sig "inflater.ss"))

21
collects/mzlib/info.ss Normal file
View File

@ -0,0 +1,21 @@
(let ([elaboration-time-files
(list "awk.ss" "compatm.ss" "defstru.ss"
"macro.ss" "match.ss"
"shared.ss" "restarts.ss" "cmdlinem.ss"
"spidey.ss" "synrule.ss" "trace.ss"
"cmdlines.ss" "dates.ss" "strings.ss"
"compats.ss" "files.ss" "threads.ss" "transcrs.ss"
"compiles.ss" "functios.ss" "pconvers.ss"
"inflates.ss" "prettys.ss" "maths.ss"
"cores.ss" "coreflats.ss" "invoke.ss"
"mzlibs.ss" "mzlibflats.ss")])
(lambda (request failure)
(case request
[(name) "MzLib"]
[(compile-prefix) '(begin
(require-library "mzlibflats.ss"))]
[(compile-omit-files) (append elaboration-time-files
(list "refer.ss" "letplsrc.ss"))]
[(compile-elaboration-zos) elaboration-time-files]
[else (failure)])))

14
collects/mzlib/invoke.ss Normal file
View File

@ -0,0 +1,14 @@
(begin-elaboration-time
(define-values (define-values/invoke-unit
define-values/invoke-unit/sig
global-define-values/invoke-unit
global-define-values/invoke-unit/sig)
(invoke-unit (require-library "invoker.ss"))))
(define-macro define-values/invoke-unit define-values/invoke-unit)
(define-macro define-values/invoke-unit/sig define-values/invoke-unit/sig)
(define-macro global-define-values/invoke-unit global-define-values/invoke-unit)
(define-macro global-define-values/invoke-unit/sig global-define-values/invoke-unit/sig)

179
collects/mzlib/invoker.ss Normal file
View File

@ -0,0 +1,179 @@
; For shadowing (during compile):
(let ([define-values/invoke-unit void]
[define-values/invoke-unit/sig void]
[global-define-values/invoke-unit void]
[global-define-values/invoke-unit/sig void])
(unit
(import)
(export)
(define (extract-signature sig badsyntax)
; A cheesy way of expanding the saignature: use the compound-unit/sig
; macro implementation. Construct an expression, expand it, and
; then pull the result back apart.
(with-handlers ([(lambda (x) (not (exn:misc:user-break? x)))
(lambda (x) (badsyntax sig "bad signature"))])
(let ([expr (local-expand-defmacro `(#%compound-unit/sig
(import)
(link [A : ,sig (0)]
[B : () (0 A)])
(export)))]
[find-expr (lambda (l v)
(let loop ([l l][queue null])
(cond
[(and (pair? l) (eq? (car l) v))
l]
[(pair? l)
; breadth first:
(loop (cdr l) (cons (car l) queue))]
[(pair? queue)
(loop (car queue) (cdr queue))]
[else #f])))])
(let* ([verify (find-expr expr '#%verify-linkage-signature-match)]
[exploded (car (cadr (list-ref verify 4)))]
[link (find-expr (find-expr expr '#%make-unit-with-signature)
'link)]
[b-line (caddr link)]
[a-import (cadr (cadr b-line))]
[flattened (cdr a-import)])
(values exploded flattened)))))
(define (extract-named-signature sig badsyntax)
(let-values ([(prefix sig) (if (and (list? sig)
(= 3 (length sig))
(eq? (cadr sig) ':))
(values (car sig) (caddr sig))
(values #f sig))])
(let-values ([(exploded flattened) (extract-signature sig badsyntax)])
(if prefix
(values (cons prefix exploded)
(let ([p (string-append (symbol->string prefix) ":")])
(map (lambda (s)
(string->symbol
(string-append
p
(symbol->string s))))
flattened)))
(values (cons 'name exploded) flattened)))))
(define (do-define-values/invoke-unit global? exports unit prefix imports)
(let* ([badsyntax (lambda (s why)
(raise-syntax-error
(if global?
'global-define-values/invoke-unit
'define-values/invoke-unit)
(format "bad syntax (~a)" why)
`(,(if global?
'global-define-values/invoke-unit
'define-values/invoke-unit)
,exports
,unit ,prefix ,@imports)
s))]
[symcheck (lambda (s)
(or (symbol? s)
(badsyntax s "not an identifier")))])
(unless (list? exports)
(badsyntax exports "not a sequence of identifiers"))
(for-each symcheck exports)
(when prefix
(unless (symbol? prefix)
(badsyntax prefix "prefix is not an identifier")))
(for-each symcheck imports)
(let* ([tagged-exports (if prefix
(let ([prefix (string-append
(symbol->string prefix)
":")])
(map (lambda (s)
(string->symbol
(string-append
prefix
(symbol->string s))))
exports))
exports)]
[extract-unit `(#%unit
(import ,@exports)
(export)
(#%values ,@exports))]
[invoke-unit
`(#%invoke-unit
(#%compound-unit
(import ,@imports)
(link [unit-to-invoke (,unit ,@imports)]
[export-extractor (,extract-unit (unit-to-invoke ,@exports))])
(export))
,@imports)])
(if global?
`(#%let-values ([,tagged-exports ,invoke-unit])
,@(map
(lambda (x)
`(#%global-defined-value ',x ,x))
tagged-exports))
`(#%define-values ,tagged-exports ,invoke-unit)))))
(define define-values/invoke-unit
(case-lambda
[(exports unit name . imports) (do-define-values/invoke-unit #f exports unit name imports)]
[(exports unit) (do-define-values/invoke-unit #f exports unit #f null)]))
(define global-define-values/invoke-unit
(case-lambda
[(exports unit name . imports) (do-define-values/invoke-unit #t exports unit name imports)]
[(exports unit) (do-define-values/invoke-unit #t exports unit #f null)]))
(define (do-define-values/invoke-unit/sig global? signame unit prefix imports)
(let* ([formname (if global?
'global-define-values/invoke-unit/sig
'define-values/invoke-unit/sig)]
[badsyntax (lambda (s why)
(raise-syntax-error
formname
(format "bad syntax (~a)" why)
`(,formname
,signame ,unit ,prefix ,@imports)
s))]
[unit-var (gensym)])
(let-values ([(ex-exploded ex-flattened) (extract-signature signame badsyntax)]
[(im-explodeds im-flatteneds)
(let loop ([l imports][el null][fl null])
(if (null? l)
(values (reverse! el) (reverse! fl))
(let-values ([(e f) (extract-named-signature (car l) badsyntax)])
(loop (cdr l) (cons e el) (cons f fl)))))])
`(,(if global?
'global-define-values/invoke-unit
'define-values/invoke-unit)
,ex-flattened
(let ([,unit-var ,unit])
(#%verify-linkage-signature-match
',formname
'(invoke)
(#%list ,unit-var)
'(,ex-exploded)
'(,im-explodeds))
(#%unit/sig->unit ,unit-var))
,(if (or (eq? prefix #f)
(symbol? prefix))
prefix
(badsyntax prefix "prefix is not #f or a symbol"))
,@(apply append im-flatteneds)))))
(define define-values/invoke-unit/sig
(case-lambda
[(signame unit prefix . imports)
(do-define-values/invoke-unit/sig #f signame unit prefix imports)]
[(signame unit)
(do-define-values/invoke-unit/sig #f signame unit #f null)]))
(define global-define-values/invoke-unit/sig
(case-lambda
[(signame unit prefix . imports)
(do-define-values/invoke-unit/sig #t signame unit prefix imports)]
[(signame unit)
(do-define-values/invoke-unit/sig #t signame unit #f null)]))
(values define-values/invoke-unit
define-values/invoke-unit/sig
global-define-values/invoke-unit
global-define-values/invoke-unit/sig)))

426
collects/mzlib/letplsrc.ss Normal file
View File

@ -0,0 +1,426 @@
(require-library "macro.ss")
(require-library "match.ss")
(define-macro rmatch
(local [(define-struct child (destruct values traversal))
(define-struct traversal (children))
(define-struct id (id))
(define-struct prepeat (pattern))
(define-struct trepeat (traversal))
(define parse-pattern
(lambda (pattern)
(cond
[(pair? pattern)
(let ([p1 (car pattern)]
[p2 (cdr pattern)])
(let*-values ([(left left-values left-names) (parse-pattern p1)]
[(right right-values right-names) (parse-pattern p2)])
(values
(make-traversal (list (make-child '#%car left-values left) (make-child '#%cdr right-values right)))
(+ left-values right-values)
(append left-names right-names))))]
[(box? pattern)
(let ([p (unbox pattern)])
(let*-values ([(sub-pat sub-values sub-names) (parse-pattern p)])
(values
(make-traversal (list (make-child '#%unbox sub-values sub-pat)))
sub-values
sub-names)))]
[(vector? pattern)
(let ([pats (vector->list pattern)])
(let loop ([pats pats]
[index 0]
[l null]
[vals 0]
[names null])
(cond
[(null? pats) (values (make-traversal (reverse l))
vals
(reverse names))]
[else (let-values ([(sub-pat sub-values sub-names) (parse-pattern (car pats))])
(loop (cdr pats)
(+ index 1)
(cons (make-child `(#%lambda (v) (#%vector-ref v ,index)) sub-values sub-pat)
l)
(+ vals sub-values)
(append sub-names names)))])))]
[(prepeat? pattern)
(let-values ([(sub-traversal sub-values sub-names)
(parse-pattern (prepeat-pattern pattern))])
(values (make-trepeat sub-traversal)
sub-values
sub-names))]
[(id? pattern)
(values pattern
1
(list (id-id pattern)))]
[(or (symbol? pattern)
(null? pattern)
(number? pattern)
(char? pattern)
(string? pattern))
(values pattern 0 null)]
[else (error 'parse-pattern "unrecognized pattern: ~a" pattern)])))
(define n-names
(lambda (n prefix)
(cond
[(zero? n) null]
[else (cons (gensym prefix) (n-names (sub1 n) prefix))])))
(define traverse-traversal
(lambda (t above-name)
(cond
[(traversal? t)
(let* ([children (traversal-children t)])
(let ([child-namess (map (lambda (c) (n-names (child-values c) "child")) children)]
[piece-names (map (lambda (c) (gensym "destruct")) children)]
[build-piece
(lambda (name child)
`[,name (,(child-destruct child) ,above-name)])]
[recur (lambda (child piece-name child-names)
`[,child-names ,(traverse-traversal (child-traversal child) piece-name)])])
`(let ,(map build-piece piece-names children)
(let-values ,(map recur children piece-names child-namess)
(values ,@(apply append child-namess))))))]
[(trepeat? t)
(let* ([sub-t (trepeat-traversal t)]
[l (gensym "...l")]
[hd (gensym "...hd")]
[loop (gensym "...loop")]
[value-count
(cond
[(traversal? sub-t) (apply + (map child-values (traversal-children sub-t)))]
[(id? sub-t) 1]
[else 0])]
[n-list (lambda (n f)
(let loop ([n n])
(cond
[(zero? n) null]
[else (cons (f (- n 1)) (loop (- n 1)))])))]
[sub-names (n-list value-count
(lambda (n) (gensym (format "...sub~a" n))))]
[rec-sub-names (n-list value-count
(lambda (n) (gensym (format "...rec~a" n))))])
`(let ,loop ([,l ,above-name])
(cond
[(null? ,l) (values ,@(n-list value-count (lambda (i) 'null)))]
[(pair? ,l) (let ([,hd (car ,l)])
(let-values ([,sub-names ,(traverse-traversal sub-t hd)]
[,rec-sub-names (,loop (cdr ,l))])
(values ,@(map (lambda (sub rec) `(cons ,sub ,rec))
sub-names
rec-sub-names))))]
[else (error 'rmatch "didn't find a list: found: ~a" ,above-name)])))]
[(id? t) above-name]
[(number? t) `(if (= ,t ,above-name)
(values)
(error 'rmatch "didn't find number: ~a, found: ~a" ,t ,above-name))]
[(symbol? t) `(if (eq? ,above-name ',t)
(values)
(error 'rmatch "didn't find symbol: ~a, found: ~a" ',t ,above-name))]
[(null? t) `(if (null? ,above-name)
(values)
(error 'rmatch "expected null, found: ~a" ,above-name))]
[(string? t) `(if (and (string? ,above-name) (string=? ,above-name ,t))
(values)
(error 'rmatch "expected ~s, found: ~s" ,t ,above-name))]
[(char? t) `(if (eq? ,above-name ,t)
(values)
(error 'rmatch "expected ~s, found: ~s" ,t ,above-name))]
[else (error 'traverse-traversal "unknown input: ~s~n" t)])))
(define generate-code
(lambda (traversal names body)
(let ([input (gensym "input")])
`(lambda (,input)
(let-values ([,names ,(traverse-traversal traversal input)])
,body)))))
;; takes the text of a pattern
;; and translates it into an example pattern
;; with symbols at the positions
;; where identifers go
;; eg '(cons x y) becomes (cons 'x 'y)
;; and `(,x ,y) becomse (list 'x 'y)
(define translation-namespace (make-namespace 'empty))
(define _1
(let* ([tmp-namespace (make-namespace)]
[add-already-macro
(lambda (m-name)
(let ([m-value
(parameterize ([current-namespace tmp-namespace])
(global-defined-value m-name))])
(parameterize ([current-namespace translation-namespace])
(global-defined-value m-name m-value))))]
[add-not-yet-macro
(lambda (m-name function)
(parameterize ([current-namespace tmp-namespace])
(eval `(define-macro ,m-name ,function)))
(add-already-macro m-name))])
(global-defined-value 'translation-namespace translation-namespace)
(add-already-macro 'quasiquote)
(add-already-macro '#%quasiquote)
(add-already-macro 'quote)
(add-already-macro '#%quote)
(add-not-yet-macro 'list
(lambda in
(let loop ([l in])
(cond
[(null? l) null]
[else `(#%cons ,(car l) ,(loop (cdr l)))]))))
(add-not-yet-macro '... (lambda (x) `(#%repeat ,x)))
(add-not-yet-macro 'repeat (lambda (x) `(#%repeat ,x)))
(add-not-yet-macro 'box (lambda (x) `(#%box ,x)))
(add-not-yet-macro 'cons (lambda (x y) `(#%cons ,x ,y)))
(add-not-yet-macro 'vector (lambda x `(#%vector ,@x)))))
(define translate-pattern
(lambda (pattern)
(let ([expanded (parameterize ([current-namespace translation-namespace])
(expand-defmacro pattern))]
[dups (make-hash-table)])
(values
dups
(let loop ([in expanded])
(match in
[`(#%repeat ,p) (make-prepeat (loop p))]
[`(#%cons ,p1 ,p2) (cons (loop p1) (loop p2))]
[`(#%box ,p) (box (loop p))]
[`(#%vector ,@ps) (apply vector (map loop ps))]
[`(#%quote ,p) p]
[`null null]
[(? symbol? in)
(let/ec k
(let ([new-id (gensym "rmatch:dup")])
(hash-table-put!
dups
in
(cons
new-id
(hash-table-get
dups
in (lambda ()
(hash-table-put! dups in null)
(k (make-id in))))))
(make-id new-id)))]
[(or (? number? in) (? char? in) (? string? in)) in]
[(? null? in) null]
[x (error 'translate-pattern "unrecognized pattern: ~s, in ~s"
x pattern)]))))))
(define main
(lambda (expression pattern-body-pairs)
(let*-values ([(main) (gensym "main")]
[(inner-k) (gensym "inner-k")]
[(outer-k) (gensym "outer-k")])
(unless (and (list? pattern-body-pairs)
(andmap (lambda (x) (and (list? x) (<= 2 (length x))))
pattern-body-pairs))
(error 'rmatch
"expected body of lists of length at least two, patterns and results, got: ~a"
pattern-body-pairs))
`(let ([,main ,expression])
(let/ec ,outer-k
,@(map (lambda (pattern-body-pair)
(let*-values ([(pattern) (car pattern-body-pair)]
[(bodies) (cdr pattern-body-pair)]
[(dups translation) (translate-pattern pattern)]
[(traversal names-count names)
(parse-pattern translation)]
[(code) (traverse-traversal traversal main)]
[(dup-vars) (let loop ([dups (hash-table-map dups cons)])
(cond
[(null? dups) null]
[else (if (= (length (car dups)) 1)
(loop (cdr dups))
(cons (car dups) (loop (cdr dups))))]))])
`(let/ec ,inner-k
(let-values ([,names
(parameterize ([current-exception-handler
(lambda (exn)
;(display (exn-message exn))
;(newline)
(,inner-k #f))])
,code)])
(unless (and ,@(map (lambda (vars) `(equal? ,@vars))
dup-vars))
(,inner-k #f))
(call-with-values (lambda () (begin ,@bodies))
,outer-k)))))
pattern-body-pairs)
(error 'rmatch "no patterns matched"))))))]
(lambda (x y) (main x y))))
(define-macro let+
(lambda (bindings . bodies)
(let* ([syn-error
(lambda (msg expr)
(raise-syntax-error 'let+ msg
`(let+ ,bindings ,@bodies)
expr))]
[expand-pattern
(lambda (x)
(match x
[`(values ,(? symbol? x) ...) x]
[(? symbol? x) `(,x)]
[x (syn-error "invalid pattern" x)]))]
[get-patterns
(lambda (x)
(match x
[`(values ,x ...) x]
[else `(,x)]))]
[single-binding
(lambda (binding E body)
(let* ([patterns (get-patterns binding)]
[gensyms (map (lambda (x) (gensym "pattern")) patterns)])
`(let-values ([,gensyms ,E])
,(let loop ([patterns patterns]
[gensyms gensyms])
(cond
[(null? patterns) body]
[else `(rmatch ,(car gensyms)
([,(car patterns)
,(loop (cdr patterns) (cdr gensyms))]))])))))]
[multiple-bindings
(lambda (binding E body)
`(let-values ,(map list (map expand-pattern binding) E)
,body))]
[recursive-single-binding
(lambda (binding E body)
`(letrec-values ([,(expand-pattern binding) ,E])
,body))]
[recursive-multiple-bindings
(lambda (binding E body)
`(letrec-values ,(map (lambda (x y) `(,x ,y))
(map expand-pattern binding)
E)
,body))]
[translate-binding
(lambda (binding body)
(match binding
[`(val ,B ,E) (single-binding B E body)]
[`(vals (,B ,E) ...) (multiple-bindings B E body)]
[`(rec ,B ,E) (recursive-single-binding B E body)]
[`(recs (,B ,E) ...) (recursive-multiple-bindings B E body)]
[`(_ ,E ...) `(begin ,@E ,body)]
[x (syn-error "invalid binding" x)]))])
(unless (and (list? bindings)
(andmap (lambda (x) (and (list? x)
(<= 2 (length x))
(symbol? (car x))))
bindings))
(syn-error "invalid syntax" bindings))
(let loop ([l bindings])
(cond
[(null? l) `(begin ,@bodies)]
[else (translate-binding (car l) (loop (cdr l)))])))))
#|
(define (test)
(define (test-at-x result name)
(lambda (pattern value)
(let ([test-result (with-handlers ([(lambda (x) 'EXCEPTION-RAISED)
(lambda (x)
(display
(if (exn? x)
(exn-message x)
x))
(newline)
#f)])
(eval `(rmatch ,value
([,pattern x]))))])
(unless (equal? result test-result)
(error name "failed with pattern: ~s and value ~s, got: ~s" pattern value test-result)))))
(define (test-equal ans expr)
(let ([got (with-handlers ([(lambda (x) #T)
(lambda (x)
(display
(if (exn? x)
(exn-message x)
x))
(newline)
'DIFFERENT-FROM-IT-ALL)])
(eval expr))])
(unless (equal? ans got)
(error 'test-equal "~s:~nexpected ~s~n got:~s~n" expr ans got))))
(define 3-at-x (test-at-x 3 '3-at-x))
(define 33s-at-x (test-at-x (list 3 3 3) '33s-at-x))
(define (plus-val-xy bindings)
(unless (equal? (cons 1 3)
(with-handlers ([(lambda (x) #t)
(lambda (x)
(printf "~a~n"
(if (exn? x)
(exn-message x)
x))
#f)])
(eval `(let+ ,bindings
(cons x y)))))
(error 'plus-val-xy "failed with bindings: ~s" bindings)))
(printf "starting test suite~n")
(plus-val-xy '([val x 1] [val y 3]))
(plus-val-xy '([val (values x y) (values 1 3)]))
(plus-val-xy '([val (values (box x) (list y)) (values (box 1) (list 3))]))
(plus-val-xy '([vals [x 1] [y 3]]))
(plus-val-xy '([vals [(values x y) (values 1 3)]]))
;(plus-val-xy '([vals [(values (box x) (list y)) (values (box 3) (list 3))]]))
(3-at-x 'x 3)
(3-at-x '(cons x y) '(cons 3 2))
(3-at-x '(list x) '(list 3))
(3-at-x '(list 2 x) '(list 2 3))
(3-at-x '(vector x) '(vector 3))
(3-at-x '(vector x 2) '(vector 3 2))
(3-at-x '(vector 2 x) '(vector 2 3))
(3-at-x '(box x) '(box 3))
(3-at-x '(box (box x)) '(box (box 3)))
(3-at-x '(vector 'x `(3) `(,x)) '(vector 'x (list 3) (list 3)))
(3-at-x '(vector 'x "abc" #\f `(3) `(,x)) '(vector 'x "abc" #\f (list 3) (list 3)))
(3-at-x '`(box ,x) ''(box 3))
(test-equal 3 '(rmatch (list 3 4) ([(list x x) x] [(list x 4) x])))
(test-equal 3 '(rmatch (list 3 3) ([(list x x) x])))
(test-equal (list 3) '(rmatch (list 3) ([(repeat x) x])))
(test-equal (list 'x 'z)
'(rmatch (list (list 'x 'y) (list 'z 'w)) ([(repeat `(,x ,y)) x])))
(test-equal
`(x 1 y)
'(rmatch '(letrec ([x 1]) y) ([`(letrec ([,x ,v]) ,b) (list x v b)])))
(test-equal
`((x) (1) y)
'(rmatch '(letrec ([x 1]) y) ([`(letrec ,(repeat `[,x ,v]) ,b) (list x v b)])))
(33s-at-x '(... (box x)) '(list (box 3) (box 3) (box 3)))
(test-equal 3 '(let ([x 3]) (let+ ([vals [x 1] [y x]]) y)))
(test-equal 3 '(let ([x 3]) (let+ ([val x 3] [vals [x 1] [y x]]) y)))
(test-equal 3 '(let+ ([rec (values x) (lambda (y) (if y 3 (x #t)))]) (x #f)))
(test-equal 3 '(let+ ([recs [x (lambda (y) (if y 3 (x #t)))]]) (x #f)))
(test-equal 3 '(let+ ([recs [(values x) (lambda (y) (if y 3 (x #t)))]]) (x #f)))
(test-equal 3 '(let+ ([rec a (lambda () a)] [val b (a)]) 3))
(printf "all tests passed~n")
)
(test)
|#

View File

@ -0,0 +1,2 @@
(unit (import) (export let+)
(#%define let+ (#%lambda (bindings . bodies) (#%let-values (((syn-error) (#%lambda (msg expr) (raise-syntax-error (#%quote let+) msg (#%cons (#%quote let+) (#%cons bindings bodies)) expr)))) (#%let-values (((expand-pattern) (#%lambda (x) (#%let-values (((g71) (#%lambda (x) (syn-error "invalid pattern" x)))) (#%if (pair? x) (#%if (#%if (equal? (car x) (#%quote values)) (list? (cdr x)) #f) (#%letrec-values (((g66) (#%lambda (g67 g68) (#%if (null? g67) ((#%lambda (x) x) (reverse g68)) (#%if (symbol? (car g67)) (g66 (cdr g67) (cons (car g67) g68)) (g71 x)))))) (g66 (cdr x) (#%quote ()))) (g71 x)) (#%if (symbol? x) ((#%lambda (x) (#%cons x ())) x) (g71 x))))))) (#%let-values (((single-binding) (#%lambda (sym binding e body) (#%cons sym (#%cons (#%cons (#%cons (expand-pattern binding) (#%cons e ())) ()) (#%cons body ())))))) (#%let-values (((multiple-bindings) (#%lambda (sym binding e body) (#%cons sym (#%cons (map list (map expand-pattern binding) e) (#%cons body ())))))) (#%let-values (((translate-binding) (#%lambda (binding body) (#%let-values (((g90) (#%lambda (x) (syn-error "invalid binding" x)))) (#%if (pair? binding) (#%if (equal? (car binding) (#%quote val)) (#%if (#%if (pair? (cdr binding)) (#%if (pair? (cddr binding)) (null? (cdddr binding)) #f) #f) ((#%lambda (b e) (single-binding (#%quote let-values) b e body)) (cadr binding) (caddr binding)) (g90 binding)) (#%if (equal? (car binding) (#%quote vals)) (#%if (list? (cdr binding)) (#%letrec-values (((g75) (#%lambda (g76 g77 g78) (#%if (null? g76) ((#%lambda (b e) (multiple-bindings (#%quote let-values) b e body)) (reverse g78) (reverse g77)) (#%if (#%if (pair? (car g76)) (#%if (pair? (cdar g76)) (null? (cddar g76)) #f) #f) (g75 (cdr g76) (cons (cadar g76) g77) (cons (caar g76) g78)) (g90 binding)))))) (g75 (cdr binding) (#%quote ()) (#%quote ()))) (g90 binding)) (#%if (equal? (car binding) (#%quote rec)) (#%if (#%if (pair? (cdr binding)) (#%if (pair? (cddr binding)) (null? (cdddr binding)) #f) #f) ((#%lambda (b e) (single-binding (#%quote letrec-values) b e body)) (cadr binding) (caddr binding)) (g90 binding)) (#%if (equal? (car binding) (#%quote recs)) (#%if (list? (cdr binding)) (#%letrec-values (((g81) (#%lambda (g82 g83 g84) (#%if (null? g82) ((#%lambda (b e) (multiple-bindings (#%quote letrec-values) b e body)) (reverse g84) (reverse g83)) (#%if (#%if (pair? (car g82)) (#%if (pair? (cdar g82)) (null? (cddar g82)) #f) #f) (g81 (cdr g82) (cons (cadar g82) g83) (cons (caar g82) g84)) (g90 binding)))))) (g81 (cdr binding) (#%quote ()) (#%quote ()))) (g90 binding)) (#%if (#%if (equal? (car binding) (#%quote _)) (list? (cdr binding)) #f) ((#%lambda (e) (#%cons (#%quote begin) (#%append e (#%cons body ())))) (cdr binding)) (g90 binding)))))) (g90 binding)))))) (#%let-values () (#%if (#%if (list? bindings) (andmap (#%lambda (x) (#%if (list? x) (#%if (<= 2 (length x)) (symbol? (car x)) #f) #f)) bindings) #f) (#%void) (syn-error "invalid syntax" bindings)) (#%letrec-values (((loop) (#%lambda (l) (#%if (null? l) (#%cons (#%quote begin) bodies) (translate-binding (car l) (loop (cdr l))))))) (loop bindings)))))))))))

33
collects/mzlib/macro.ss Normal file
View File

@ -0,0 +1,33 @@
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (class-asi
class*-asi
opt-lambda
send*
local
recur
rec
evcase
nor
nand
signature->symbols)
(require-library "macror.ss"))
(define-values/invoke-unit (let+)
(require-library "letplusr.ss")))
(define-macro class-asi class-asi)
(define-macro class*-asi class*-asi)
(define-macro opt-lambda opt-lambda)
(define-macro let+ let+)
(define-macro send* send*)
(define-macro local local)
(define-macro recur recur)
(define-macro rec rec)
(define-macro evcase evcase)
(define-macro nor nor)
(define-macro nand nand)
(define-macro signature->symbols signature->symbols)

265
collects/mzlib/macror.ss Normal file
View File

@ -0,0 +1,265 @@
(unit
(import)
(export class-asi
class*-asi
opt-lambda
send*
local
recur
rec
evcase
nor
nand
signature->symbols)
(define class*-asi
(lambda (super interfaces . body)
(let ([args (gensym)]
[super-init 'super-init])
`(class* ,super ,interfaces ,args
,@body
(sequence
(apply ,super-init ,args))))))
(define class-asi
(lambda (super . rest)
`(class*-asi ,super () ,@rest)))
(define opt-lambda
(lambda (args . body)
(let* ([mk-code (lambda () (list* 'opt-lambda args body))]
[f (gensym 'opt-lambda-procedure)]
[required
(let loop ([args args])
(if (and (pair? args)
(symbol? (car args)))
(cons (car args) (loop (cdr args)))
'()))]
[not-required-with-defaults
(let loop ([args args])
(if (and (pair? args)
(symbol? (car args)))
(loop (cdr args))
args))]
[not-required
(let loop ([args not-required-with-defaults])
(if (pair? args)
(if (pair? (car args))
(let ([name (caar args)])
(if (symbol? name)
(cons name (loop (cdr args)))
(raise-syntax-error
'opt-lambda
"all argument names must be symbols"
(mk-code))))
(raise-syntax-error 'opt-lambda
"all required args must come first"
(mk-code)))
(if (or (null? args) (symbol? args))
args
(raise-syntax-error 'opt-lambda
"all argument names must be symbols"
(mk-code)))))]
[defaults
(let loop ([args not-required-with-defaults])
(if (pair? args)
(let ([v (cdar args)])
(if (and (pair? v) (null? (cdr v)))
(cons (car v) (loop (cdr args)))
(raise-syntax-error
'opt-lambda
"only one default value allowed per argument"
(mk-code))))
()))])
`(letrec ([,f
(case-lambda
,@(let loop ([required required]
[not-required not-required]
[defaults defaults])
(if (not (pair? not-required))
(list `(,(append required not-required) ,@body))
(cons `(,required
,(cons f (append required
(list (car defaults)))))
(loop (append required (list (car not-required)))
(cdr not-required)
(cdr defaults))))))])
,f))))
(define send*
(lambda (x . rest)
(let ([g (gensym "send*")])
`(let ([,g ,x])
,@(map (lambda (x) `(send ,g ,@x))
rest)))))
;; Another let-like form.
(define local
(lambda (defines expr1 . body)
(unless (list? defines)
(raise-syntax-error
'local
"bad definition sequence"
(list* 'local defines expr1 body)
defines))
(let* ([symilist? (lambda (l)
(let loop ([l l])
(or (null? l)
(symbol? l)
(and (pair? l)
(symbol? (car l))
(loop (cdr l))))))]
[defs
(map
(lambda (def)
(unless (and (list? def)
(pair? def)
(case (car def)
[(#%define-values define-values)
(and (= 3 (length def))
(list? (cadr def))
(andmap symbol? (cadr def))
(let-values ([(d kind) (local-expand-body-expression `(,(car def) (,(gensym)) 1))])
(eq? kind '#%define-values)))]
[(#%define define)
(and (or (and (= 3 (length def))
(symbol? (cadr def)))
(and (<= 3 (length def))
(pair? (cadr def))
(symilist? (cadr def))))
(let-values ([(d kind) (local-expand-body-expression `(,(car def) ,(gensym) 1))])
(eq? kind '#%define-values)))]
[(#%define-struct define-struct)
(and (= 3 (length def))
(or (symbol? (cadr def))
(and (list? (cadr def))
(= 2 (length (cadr def)))
(symbol? (caadr def))))
(list? (caddr def))
(andmap symbol? (caddr def))
(let-values ([(d kind) (local-expand-body-expression `(,(car def) ,(gensym) ()))])
(eq? kind '#%define-values)))]
[else #f]))
(raise-syntax-error
'local
"bad definition"
(list* 'local defines expr1 body)
def))
(case (car def)
[(#%define-values define-values) (cadr def)]
[(#%define define) (list (if (symbol? (cadr def))
(cadr def)
(caadr def)))]
[else (let ([s `(#%define-struct
,(if (symbol? (cadr def))
(cadr def)
(caadr def))
,(caddr def))])
(cadr (expand-defmacro s)))]))
defines)]
[defined-names (apply append defs)])
; We wrap everything in an extra `let' to permit the shadowing
; of syntax by local definitions:
`(let ,(map (lambda (n) `(,n (#%void))) defined-names)
; We have to use #% forms for define, now:
,@(map (lambda (def)
(case (car def)
[(#%define-values define-values)
(cons '#%define-values (cdr def))]
[(#%define define)
(cons '#%define (cdr def))]
[(#%define-struct define-struct)
(cons '#%define-struct (cdr def))]))
defines)
; Another let, in case there were more embedded defines:
(let () ,expr1 ,@body)))))
;; recur is another name for 'let' in a named let
(define recur
(lambda (name args . body) `(let ,name ,args ,@body)))
;; define a recursive value
(define rec
(lambda (x rest)
(if (symbol? x)
`(letrec ([,x ,rest])
,x)
(raise-syntax-error 'rec "identifier must be a symbol"
(list 'rec x rest) x))))
(define evcase
(lambda (v . tests-in)
(let ([serror
(lambda (msg at)
(raise-syntax-error
'evcase
msg
(list* 'evcase v tests-in)
at))])
(let ([gen (gensym "evcase")])
`(let ([,gen ,v])
(cond
,@(let loop ([tests tests-in])
(cond
[(null? tests) `()]
[(pair? tests)
(let ([test-value (car tests)]
[rest (cdr tests)])
`(,(if (or (not (pair? test-value))
(not (pair? (cdr test-value))))
(serror
"bad syntax (clause is not a test-value pair)"
test-value)
(let ([test (car test-value)]
[body (cdr test-value)])
(if (and (pair? body) (list? body))
#t
(serror
"bad syntax (improper clause body)"
body))
(let ([condition
(cond
[(and (eq? test 'else)
(not (local-expansion-time-bound? 'else)))
(if (null? rest)
'else
(serror
"bad syntax (`else' clause must be last)"
test-value))]
[else `(eqv? ,gen ,test)])])
`(,condition
(begin ,@body)))))
.
,(loop rest)))]
[else (serror
"bad syntax (body must contain a list of pairs)"
tests)]))))))))
(define nor (lambda args `(#%not (#%or ,@args))))
(define nand (lambda args `(#%not (#%and ,@args))))
(define signature->symbols
(lambda (name)
(unless (symbol? name)
(raise-syntax-error 'signature->symbols
"not an identifier"
(list 'signature->symbols name)
name))
(let ([v (global-expansion-time-value name)])
(letrec ([sig? (lambda (v)
(and (vector? v)
(andmap
(lambda (s)
(or (and (pair? s)
(symbol? (car s))
(sig? (cdr s)))
(symbol? s)))
(vector->list v))))])
(unless (sig? v)
(raise-syntax-error 'signature->symbols
"expansion-time value is not a signature"
(list 'signature->symbols name)
name))
v)))))

18
collects/mzlib/macrox.ss Normal file
View File

@ -0,0 +1,18 @@
(begin-elaboration-time
(require-library "refer.ss"))
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (send*
local
recur
rec
evcase
nor
nand
signature->symbols)
(require-library "macroxr.ss")))

187
collects/mzlib/macroxr.ss Normal file
View File

@ -0,0 +1,187 @@
(unit
(import)
(export send*
local
recur
rec
evcase
nor
nand
signature->symbols)
(define send*
(lambda (x . rest)
(let ([g (gensym "send*")])
`(let ([,g ,x])
,@(map (lambda (x) `(send ,g ,@x))
rest)))))
;; Another let-like form.
(define local
(lambda (defines expr1 . body)
(unless (list? defines)
(raise-syntax-error
'local
"bad definition sequence"
(list* 'local defines expr1 body)
defines))
(let* ([symilist? (lambda (l)
(let loop ([l l])
(or (null? l)
(symbol? l)
(and (pair? l)
(symbol? (car l))
(loop (cdr l))))))]
[defs
(map
(lambda (def)
(unless (and (list? def)
(pair? def)
(case (car def)
[(#%define-values define-values)
(and (= 3 (length def))
(list? (cadr def))
(andmap symbol? (cadr def))
(let-values ([(d kind) (local-expand-body-expression `(,(car def) (,(gensym)) 1))])
(eq? kind '#%define-values)))]
[(#%define define)
(and (or (and (= 3 (length def))
(symbol? (cadr def)))
(and (<= 3 (length def))
(pair? (cadr def))
(symilist? (cadr def))))
(let-values ([(d kind) (local-expand-body-expression `(,(car def) ,(gensym) 1))])
(eq? kind '#%define-values)))]
[(#%define-struct define-struct)
(and (= 3 (length def))
(or (symbol? (cadr def))
(and (list? (cadr def))
(= 2 (length (cadr def)))
(symbol? (caadr def))))
(list? (caddr def))
(andmap symbol? (caddr def))
(let-values ([(d kind) (local-expand-body-expression `(,(car def) ,(gensym) ()))])
(eq? kind '#%define-values)))]
[else #f]))
(raise-syntax-error
'local
"bad definition"
(list* 'local defines expr1 body)
def))
(case (car def)
[(#%define-values define-values) (cadr def)]
[(#%define define) (list (if (symbol? (cadr def))
(cadr def)
(caadr def)))]
[else (let ([s `(#%define-struct
,(if (symbol? (cadr def))
(cadr def)
(caadr def))
,(caddr def))])
(cadr (expand-defmacro s)))]))
defines)]
[defined-names (apply append defs)])
; We wrap everything in an extra `let' to permit the shadowing
; of syntax by local definitions:
`(let ,(map (lambda (n) `(,n (#%void))) defined-names)
; We have to use #% forms for define, now:
,@(map (lambda (def)
(case (car def)
[(#%define-values define-values)
(cons '#%define-values (cdr def))]
[(#%define define)
(cons '#%define (cdr def))]
[(#%define-struct define-struct)
(cons '#%define-struct (cdr def))]))
defines)
; Another let, in case there were more embedded defines:
(let () ,expr1 ,@body)))))
;; recur is another name for 'let' in a named let
(define recur
(lambda (name args . body) `(let ,name ,args ,@body)))
;; define a recursive value
(define rec
(lambda (x rest)
(if (symbol? x)
`(letrec ([,x ,rest])
,x)
(raise-syntax-error 'rec "identifier must be a symbol"
(list 'rec x rest) x))))
(define evcase
(lambda (v . tests-in)
(let ([serror
(lambda (msg at)
(raise-syntax-error
'evcase
msg
(list* 'evcase v tests-in)
at))])
(let ([gen (gensym "evcase")])
`(let ([,gen ,v])
(cond
,@(let loop ([tests tests-in])
(cond
[(null? tests) `()]
[(pair? tests)
(let ([test-value (car tests)]
[rest (cdr tests)])
`(,(if (or (not (pair? test-value))
(not (pair? (cdr test-value))))
(serror
"bad syntax (clause is not a test-value pair)"
test-value)
(let ([test (car test-value)]
[body (cdr test-value)])
(if (and (pair? body) (list? body))
#t
(serror
"bad syntax (improper clause body)"
body))
(let ([condition
(cond
[(and (eq? test 'else)
(not (local-expansion-time-bound? 'else)))
(if (null? rest)
'else
(serror
"bad syntax (`else' clause must be last)"
test-value))]
[else `(eqv? ,gen ,test)])])
`(,condition
(begin ,@body)))))
.
,(loop rest)))]
[else (serror
"bad syntax (body must contain a list of pairs)"
tests)]))))))))
(define nor (lambda args `(#%not (#%or ,@args))))
(define nand (lambda args `(#%not (#%and ,@args))))
(define signature->symbols
(lambda (name)
(unless (symbol? name)
(raise-syntax-error 'signature->symbols
"not an identifier"
(list 'signature->symbols name)
name))
(let ([v (global-expansion-time-value name)])
(letrec ([sig? (lambda (v)
(and (vector? v)
(andmap
(lambda (s)
(or (and (pair? s)
(symbol? (car s))
(sig? (cdr s)))
(symbol? s)))
(vector->list v))))])
(unless (sig? v)
(raise-syntax-error 'signature->symbols
"expansion-time value is not a signature"
(list 'signature->symbols name)
name))
v)))))

17
collects/mzlib/match.ss Normal file
View File

@ -0,0 +1,17 @@
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (match:set-error
match:set-error-control match:error-control-param
match:error match match-lambda match-lambda*
match-letrec match-let match-let*)
(require-library "matchr.ss")))
(define-macro match match)
(define-macro match-lambda match-lambda)
(define-macro match-lambda* match-lambda*)
(define-macro match-letrec match-letrec)
(define-macro match-let match-let)
(define-macro match-let* match-let*)

1936
collects/mzlib/matchr.ss Normal file

File diff suppressed because it is too large Load Diff

8
collects/mzlib/math.ss Normal file
View File

@ -0,0 +1,8 @@
(require-library "mathu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:math^
mzlib:math@)

39
collects/mzlib/mathr.ss Normal file
View File

@ -0,0 +1,39 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; math.ss: some extra math routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unit/sig mzlib:math^
(import)
;; circular constants and aliases
(define e (exp 1.0))
(define pi (atan 0 -1))
;; sgn function
(define sgn
(lambda (x)
(cond
((< x 0) -1)
((> x 0) 1)
(else 0))))
;; complex conjugate
(define conjugate
(lambda (z)
(make-rectangular
(real-part z)
(- (imag-part z)))))
;; real hyperbolic functions
(define sinh
(lambda (x)
(/
(- (exp x) (exp (- x)))
2.0)))
(define cosh
(lambda (x)
(/
(+ (exp x) (exp (- x)))
2.0))))

7
collects/mzlib/maths.ss Normal file
View File

@ -0,0 +1,7 @@
(define-signature mzlib:math^
(e
pi
sgn conjugate
sinh cosh))

7
collects/mzlib/mathu.ss Normal file
View File

@ -0,0 +1,7 @@
(require-library "maths.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:math@ (require-library-unit/sig "mathr.ss"))

12
collects/mzlib/mzlib.ss Normal file
View File

@ -0,0 +1,12 @@
; Load all of mzlib
(require-library "core.ss")
(require-library "compat.ss")
(require-library "pconvert.ss")
(require-library "date.ss")
(require-library "inflate.ss")
(require-library "cmdline.ss")
(require-library "restart.ss")
(require-library "transcr.ss")

View File

@ -0,0 +1,25 @@
(compound-unit/sig
(import)
(link [core : mzlib:core-flat^ ((require-library-unit/sig "coreflatr.ss"))]
[compat : mzlib:compat^ ((require-library-unit/sig "compatr.ss") (core : mzlib:function^))]
[convert : mzlib:print-convert^
((require-library-unit/sig "pconverr.ss")
(core : mzlib:string^)
(core : mzlib:function^))]
[date : mzlib:date^ ((require-library-unit/sig "dater.ss")
(core : mzlib:function^))]
[inflate : mzlib:inflate^ ((require-library-unit/sig "inflater.ss"))]
[command-line : mzlib:command-line^ ((require-library-unit/sig "cmdliner.ss"))]
[restart : mzlib:restart^ ((require-library-unit/sig "restartr.ss")
command-line)]
[transcript : mzlib:transcript^ ((require-library-unit/sig "transcrr.ss"))])
(export (open core)
(open compat)
(open convert)
(open date)
(open inflate)
(open command-line)
(open restart)
(open transcript)))

View File

@ -0,0 +1,14 @@
(require-library "mzlibs.ss")
(require-library "coreflats.ss")
(define-signature mzlib:flat^
((open mzlib:core^)
(open mzlib:compat^)
(open mzlib:print-convert^)
(open mzlib:date^)
(open mzlib:inflate^)
(open mzlib:command-line^)
(open mzlib:restart^)
(open mzlib:transcript^)))

4
collects/mzlib/mzlibm.ss Normal file
View File

@ -0,0 +1,4 @@
(require-library "corem.ss")
(require-library "synrule.ss")

25
collects/mzlib/mzlibr.ss Normal file
View File

@ -0,0 +1,25 @@
(compound-unit/sig
(import)
(link [core : mzlib:core^ ((require-library-unit/sig "corer.ss"))]
[compat : mzlib:compat^ ((require-library-unit/sig "compatr.ss") (core function))]
[convert : mzlib:print-convert^
((require-library-unit/sig "pconverr.ss")
(core string)
(core function))]
[date : mzlib:date^ ((require-library-unit/sig "dater.ss")
(core function))]
[inflate : mzlib:inflate^ ((require-library-unit/sig "inflater.ss"))]
[command-line : mzlib:command-line^ ((require-library-unit/sig "cmdliner.ss"))]
[restart : mzlib:restart^ ((require-library-unit/sig "restartr.ss")
command-line)]
[transcript : mzlib:transcript^ ((require-library-unit/sig "transcrr.ss"))])
(export (open core)
(open compat)
(unit convert)
(unit date)
(unit inflate)
(unit command-line)
(unit restart)
(unit transcript)))

20
collects/mzlib/mzlibs.ss Normal file
View File

@ -0,0 +1,20 @@
(begin-elaboration-time
(require-library "cores.ss")
(require-library "compats.ss")
(require-library "pconvers.ss")
(require-library "dates.ss")
(require-library "inflates.ss")
(require-library "cmdlines.ss")
(require-library "restarts.ss")
(require-library "transcrs.ss"))
(define-signature mzlib^
((open mzlib:core^)
(unit compat : mzlib:compat^)
(unit print-convert : mzlib:print-convert^)
(unit date : mzlib:date^)
(unit inflate : mzlib:inflate^)
(unit command-line : mzlib:command-line^)
(unit restart : mzlib:restart^)
(unit transcript : mzlib:transcript^)))

21
collects/mzlib/mzlibu.ss Normal file
View File

@ -0,0 +1,21 @@
; Load all of mzlib
(require-library "coreu.ss")
(require-library "synrule.ss")
(require-library "spidey.ss")
(require-library "pconveru.ss")
(require-library "dateu.ss")
(require-library "inflateu.ss")
(require-library "cmdlineu.ss")
(require-library "restartu.ss")
(require-library "transcru.ss")
(require-library "mzlibs.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib@ (require-library-unit/sig "mzlibr.ss"))

13
collects/mzlib/pconver.ss Normal file
View File

@ -0,0 +1,13 @@
(require-library "pconveru.ss")
(require-library "string.ss")
(require-library "functio.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:print-convert^
mzlib:print-convert@
#f
mzlib:string^
mzlib:function^)

438
collects/mzlib/pconverr.ss Normal file
View File

@ -0,0 +1,438 @@
(unit/sig mzlib:print-convert^
(import (s : mzlib:string^)
(f : mzlib:function^))
(define undefined-val (letrec ([x x]) x))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the value stored in the hash table. Contains the name
;; <which is a number unless we are in donkey and it already has a name>
;; and whether or not it is shared in the expr.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-struct share-info (name shared?))
(define boolean-filter (lambda (x) (and x #t)))
(define show-sharing (make-parameter #t boolean-filter))
(define constructor-style-printing (make-parameter #f boolean-filter))
(define quasi-read-style-printing (make-parameter #t boolean-filter))
(define abbreviate-cons-as-list (make-parameter #t boolean-filter))
(define whole/fractional-exact-numbers (make-parameter #t boolean-filter))
(define booleans-as-true/false (make-parameter #t boolean-filter))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; share-hash is the hash-table containing info on what cons cells
;; of the expression are shared.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; sometimes you want to go ahead and start displaying a shared
;; expression rather than just showing its name. For instance, in
;; the shared list, you want (shared ((-1- (list 1 2))... not
;; (shared ((-1- -1-) ...
;; expand-shared? controls this
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-struct convert-share-info (share-hash expand-shared?))
(define current-build-share-name-hook (make-parameter (lambda (e) #f)
(lambda (f)
(unless (procedure-arity-includes? f 1)
(raise-type-error 'current-build-share-name-hook "procedure of arity 1" f))
f)))
(define current-build-share-hook (make-parameter (lambda (e base sub) (base e))
(lambda (f)
(unless (procedure-arity-includes? f 3)
(raise-type-error 'current-build-share-hook "procedure of arity 3" f))
f)))
(define current-print-convert-hook (make-parameter (lambda (e base sub) (base e))
(lambda (f)
(unless (procedure-arity-includes? f 3)
(raise-type-error 'current--hook "procedure of arity 3" f))
f)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; builds the hash table
;; --------- THIS PROCEDURE IS EXPORTED ----------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define build-share
(lambda (expr)
(letrec
([share-cnt 0]
[share-hash (make-hash-table)]
[csi (make-convert-share-info share-hash #f)]
[hash
(lambda (obj)
(let ([name ((current-build-share-name-hook) obj)])
(hash-table-put! share-hash obj
(make-share-info (if name (car name) share-cnt) #f)))
(set! share-cnt (add1 share-cnt)))]
[build-sub
(lambda (expr)
(let/ec k
(let ([val (hash-table-get share-hash expr
(lambda () (hash expr) (k #f)))])
(when val
(set-share-info-shared?! val #t))
val)))]
[build
(lambda (expr)
((current-build-share-hook)
expr
(lambda (expr)
(cond
[(or (number? expr)
(symbol? expr)
(boolean? expr)
(char? expr) (void? expr)
(null? expr)
(eq? expr undefined-val) ; #<undefined> test - yuck
; (regexp? expr)
; (port? expr)
; (promise? expr)
; (object? expr) (class? expr) (interface? exp)
; (unit? expr)
; (procedure? expr)
)
'atomic]
[(inferred-name expr) 'atomic]
[(box? expr) (unless (build-sub expr)
(build (unbox expr)))]
[(hash-table? expr) (unless (build-sub expr)
(hash-table-for-each
expr
(lambda (key value)
(build value))))]
[(pair? expr) (unless (build-sub expr)
(build (car expr))
(build (cdr expr)))]
[(vector? expr) (unless (build-sub expr)
(for-each build (vector->list expr)))]
[(struct? expr) (unless (build-sub expr)
(for-each build (vector->list (struct->vector expr))))]
[else (build-sub expr)]))
build-sub))])
(build expr)
csi)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; creates a distinctive symbol out of a name (usually just a number)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define map-share-name
(lambda (name)
(string->symbol
(string-append "-" (s:expr->string name) "-"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; prints an expression given that it has already been hashed. This
;; does not include the list of shared items.
;; --------- THIS PROCEDURE IS EXPORTED ----------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define print-convert-expr
(lambda (csi expr unroll-once?)
(letrec
([share-hash (convert-share-info-share-hash csi)]
[find-hash
(lambda (expr)
(hash-table-get share-hash expr (lambda () #f)))]
[shared?
(lambda (expr)
(let* ([info (find-hash expr)]
[ans (and info
(share-info-shared? info))])
ans))]
[make-list
(lambda (f n)
(letrec ([helper
(lambda (n l)
(cond [(zero? n) l]
[else (helper (sub1 n) (cons (f n) l))]))])
(helper n null)))]
[make-lambda-helper
(lambda (arity)
(cond
[(arity-at-least? arity)
(let ([v (arity-at-least-value arity)])
(if (zero? v)
'args
(append (make-lambda-helper v) 'args)))]
[(list? arity)
(map (lambda (x)
(list (make-lambda-helper x) '...))
arity)]
[else (make-list
(lambda (x)
(string->symbol
(string-append "a" (number->string x))))
arity)]))]
[use-quasi-quote? (not (constructor-style-printing))]
[use-read-syntax (quasi-read-style-printing)]
[doesnt-contain-shared-conses
(lambda (input-expr)
(letrec ([doesnt-contain-shared-conses
(lambda (expr)
(cond
[(and (pair? expr)
(shared? expr))
#f]
[(pair? expr)
(doesnt-contain-shared-conses (cdr expr))]
[else #t]))])
(let ([answer (doesnt-contain-shared-conses input-expr)])
answer)))]
[get-whole/frac
(lambda (exact-num)
(let ([split
(lambda (real)
(let* ([num (numerator real)]
[den (denominator real)])
(values (quotient num den)
(* (if (negative? num) -1 1)
(/ (modulo num den) den)))))])
(let-values ([(whole frac) (split (real-part exact-num))]
[(whole-i frac-i) (split (imag-part exact-num))])
(values whole frac whole-i frac-i))))]
[print
(lambda (in-quasiquote? first-time)
(lambda (expr)
(letrec
([lookup (find-hash expr)]
[recur (print in-quasiquote? #f)]
[self-quoting?
(lambda (expr)
(or (and (number? expr)
(or (inexact? expr)
(not (whole/fractional-exact-numbers))
(and (real? expr)
(or (let-values ([(whole frac whole-i frac-i) (get-whole/frac expr)])
(and (or (zero? whole)
(zero? frac))))))))
(and (symbol? expr)
(not (eq? expr 'quasiquote))
(not (eq? expr 'quote))
(not (eq? expr 'unquote)))
(char? expr)
(string? expr)
(not expr)
(eq? #t expr)))]
[quasi-read-style
(lambda ()
(cond
[(box? expr) (box (recur (unbox expr)))]
[(vector? expr) (apply vector (map recur (vector->list expr)))]
[else (quasi-style)]))]
[quasi-style
(lambda ()
(cond
[(null? expr) '()]
[(and (list? expr)
(doesnt-contain-shared-conses expr))
(map recur expr)]
[(pair? expr)
(cons (recur (car expr)) (recur (cdr expr)))]
[(self-quoting? expr) expr]
[else `(,'unquote ,((print #f first-time) expr))]))]
[guard
(lambda (f)
(cond
[use-quasi-quote?
`(,'quasiquote ,(if use-read-syntax
((print #t first-time) expr)
((print #t first-time) expr)))]
[else
(f)]))]
[constructor-style
(let* ([build-named
(lambda (expr build-unnamed)
(let ([answer (inferred-name expr)])
(if answer
(if (eq? (with-handlers ([(lambda (x) #t)
(lambda (x) #f)])
(global-defined-value answer))
expr)
answer
(build-unnamed))
(build-unnamed))))])
(lambda ()
((current-print-convert-hook)
expr
(lambda (expr)
(cond
[(null? expr) (guard (lambda () 'empty))]
[(and (list? expr)
(abbreviate-cons-as-list)
(or (and first-time
(doesnt-contain-shared-conses (cdr expr)))
(doesnt-contain-shared-conses expr)))
(guard (lambda ()
`(list ,@(map recur expr))))]
[(pair? expr)
(guard
(lambda ()
`(cons ,(recur (car expr)) ,(recur (cdr expr)))))]
[(weak-box? expr) `(make-weak-box ,(recur (weak-box-value expr)))]
[(box? expr) `(box ,(recur (unbox expr)))]
[(hash-table? expr) `(make-hash-table)]
[(vector? expr) `(vector ,@(map recur (vector->list expr)))]
[(symbol? expr) `',expr]
[(string? expr) expr]
[(primitive? expr) (string->symbol (primitive-name expr))]
[(procedure? expr)
(build-named
expr
(lambda ()
(let ([arity (arity expr)])
(if (list? arity)
`(case-lambda . ,(make-lambda-helper arity))
`(lambda ,(make-lambda-helper arity) ...)))))]
[(regexp? expr) `(regexp ...)]
[(interface? expr) `(interface ...)]
[(class? expr)
(build-named
expr
(lambda () '(class ...)))]
[(object? expr) `(make-object
,(build-named
(object-interface expr)
(lambda () '(class ...)))
...)]
[(void? expr) '(void)]
[(promise? expr) '(delay ...)]
[(struct? expr)
(let ([name (symbol->string
(vector-ref (struct->vector expr) 0))])
(cons (string->symbol
(string-append
"make-" (substring name
(string-length "struct:")
(string-length name))))
(map recur (cdr (vector->list
(struct->vector expr))))))]
[(unit? expr) (build-named
expr
(lambda ()
'(unit ...)))]
[(and (number? expr) (exact? expr))
(let-values ([(whole frac whole-i frac-i) (get-whole/frac expr)])
(cond
[(not (whole/fractional-exact-numbers)) expr]
[(and (or (zero? whole)
(zero? frac))
(zero? whole-i)
(zero? frac-i))
expr]
[(real? expr) `(+ ,whole ,frac)]
[(and (or (zero? whole) (zero? frac))
(or (zero? whole-i) (zero? frac-i)))
`(+ ,(real-part expr) (* +1i ,(imag-part expr)))]
[(or (zero? whole-i) (zero? frac-i))
`(+ (+ ,whole ,frac) (* +1i ,(imag-part expr)))]
[(or (zero? whole) (zero? frac))
`(+ ,(real-part expr) (* +1i (+ ,whole-i ,frac-i)))]
[else `(+ (+ ,whole ,frac) (* +1i (+ ,whole-i ,frac-i)))]))]
[(eq? expr #f) (if (booleans-as-true/false) 'false #f)]
[(eq? expr #t) (if (booleans-as-true/false) 'true #t)]
[else expr]))
recur)))])
(let ([es (convert-share-info-expand-shared? csi)])
(set-convert-share-info-expand-shared?! csi #f)
(if (and lookup
(not es)
(not first-time)
(share-info-shared? lookup))
(let ([name (map-share-name (share-info-name lookup))])
(if in-quasiquote?
`(,'unquote ,name)
name))
(if in-quasiquote?
(if use-read-syntax
(quasi-read-style)
(quasi-style))
(constructor-style)))))))])
((print #f unroll-once?) expr))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; these functions get the list of shared items. If just-circular is
;; true, then it will modify the hash table so that the only shared
;; items are those that are circular.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define get-shared-helper
(lambda (csi)
(let ([shared '()]
[share-hash (convert-share-info-share-hash csi)])
(hash-table-for-each share-hash
(lambda (key val)
(when (share-info-shared? val)
(set! shared (cons (list key val) shared)))))
(map (lambda (s)
(set-convert-share-info-expand-shared?! csi #t)
(let* ([info (cadr s)]
[name (share-info-name info)])
(list info
(map-share-name name)
(print-convert-expr csi (car s) #t))))
shared))))
;; --------- THIS PROCEDURE IS EXPORTED ----------
(define get-shared
(case-lambda
[(csi) (get-shared csi #f)]
[(csi just-circular)
(let ([shared-listss
(if just-circular
(let ([shared (get-shared-helper csi)])
(for-each (lambda (x)
(unless (member* (cadr x) (caddr x))
(set-share-info-shared?! (car x) #f)))
shared)
(get-shared-helper csi))
(get-shared-helper csi))]
[cmp
(lambda (x y)
(string<? (s:expr->string (share-info-name (car x)))
(s:expr->string (share-info-name (car y)))))])
(map cdr (f:quicksort shared-listss cmp)))]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; helper function for determining if an item is circular. In the
;; shared list: (shared ((-1- (list 1 2)) (-2- (list -2- 2 3)))), you
;; can tell by doing a member* of the first item on the second. In this
;; case, the second item in the shared list is circular because -2- appears
;; in the value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define member*
(lambda (a l)
(cond [(or (not (pair? l)) (null? l)) #f]
[(eq? a (car l)) #t]
[else (or (member* a (car l)) (member* a (cdr l)))])))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; takes an expression and completely converts it to show sharing
;; (or if just-circular, just circularity) and special forms.
;; --------- THIS PROCEDURE IS EXPORTED ----------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define print-convert
(case-lambda
[(expr) (print-convert expr (not (show-sharing)))]
[(expr just-circ)
(let* ([csi (build-share expr)])
(let ([shared (get-shared csi just-circ)]
[body (print-convert-expr csi expr #f)])
(if (null? shared)
body
`(shared ,shared ,body))))]))
(define current-read-eval-convert-print-prompt
(make-parameter "|- "))
(define install-converting-printer
(lambda ()
(let ([print (current-print)])
(current-print (lambda (v)
(unless (void? v)
(print (print-convert v))))))
(current-prompt-read (lambda ()
(display (current-read-eval-convert-print-prompt))
(read))))))
;; TEST SUITE MOVED to mzscheme command test suite area.
;; plt/tests/mzscheme/pconvert.ss

View File

@ -0,0 +1,24 @@
(begin-elaboration-time
(require-library "strings.ss")
(require-library "functios.ss"))
(define-signature mzlib:print-convert^
(show-sharing
constructor-style-printing
quasi-read-style-printing
abbreviate-cons-as-list
whole/fractional-exact-numbers
booleans-as-true/false
print-convert
print-convert-expr
build-share
get-shared
current-read-eval-convert-print-prompt
install-converting-printer
current-build-share-name-hook
current-build-share-hook
current-print-convert-hook))

View File

@ -0,0 +1,2 @@
(require-library "pconver.ss")

View File

@ -0,0 +1,21 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Gann Bierner -=)
;; gbierner@owlnet.rice.edu (=- \ O
;; _O \_-)---
;; File: pconveru.ss (=-_/ /\
;; /\
;;
;; This file contains code which formats an expression to show all sharing
;; within it. Call `print-convert' to convert a value.
;; It takes 2 optional arguments. The first is a boolean value, just-circular.
;; If true, sharing will only be shown for circularity. The default is #f
;; where all sharing is shown. The first argument to share:print-all is, of
;; course, the expression to convert.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require-library "pconvers.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:print-convert@ (require-library-unit/sig "pconverr.ss"))

10
collects/mzlib/pretty.ss Normal file
View File

@ -0,0 +1,10 @@
(require-library "prettyu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:pretty-print^
mzlib:pretty-print@)

838
collects/mzlib/prettyr.ss Normal file
View File

@ -0,0 +1,838 @@
; Originally:
;"genwrite.scm" generic write used by pp.scm
;;copyright (c) 1991, marc feeley
; Pretty-printer for MzScheme
; Handles structures, cycles, and graphs
;
; Procedures:
;
; (pretty-print v) - pretty-prints v (like `write')
; (pretty-print v port) - pretty-prints v to port
;
; (pretty-display ...) - like pretty-print, but prints like `display'
; instead of like `write'
;
; pretty-print-columns - parameter for the default number of columns
; or 'infinity; initial setting: 79
;
; pretty-print-print-line - parameter of a procedure that prints
; to separate each line; 0 indicate before the first line, #f after the
; last line
;
; pretty-print-depth - parameter for the default print depth
; initial setting: #f (= infinity)
;
; pretty-print-size-hook - parameter for the print size hook; returns #f to
; let pretty-printer handle it, number otherwise
; initial setting: (lambda (x display? port) #f)
;
; pretty-print-print-hook - parameter for the print hook, called when the
; size-hook returns a non-#f value
; initial setting: (lambda (x display? port) (void))
;
; pretty-print-display-string-handler - parameter for the string display
; procedure, called to finally write text
; to the port
;
; pretty-print-pre-print-hook - parameter for a procedure that is called
; just before each object is printed
; initial setting: (lambda (x port) (void))
;
; pretty-print-post-print-hook - parameter for a procedure that is called
; just after each object is printed
; initial setting: (lambda (x port) (void))
;
; pretty-print-show-inexactness - parameter for printing #i before an
; inexact number
; initial setting: #f
;
; pretty-print-exact-as-decimal - parameter for printing exact numbers
; with decimal representations in decimal
; notation instead of fractions
; initial setting: #f
;
; (pretty-print-handler v) - pretty-prints v if v is not #<void>
;
; TO INSTALL this pretty-printer into a MzScheme's read-eval-print loop,
; load this file and evaluate:
; (current-print pretty-print-handler)
;; Matthew's changes:
;; Modified original for MrEd Spring/95
;; Added check for cyclic structures 11/9/95
;; Better (correct) graph printing, support boxes and structures 11/26/95
;; Support for print depth 2/28/96
;; functor 4/22/96
;; unit/s 6/13/96
;; size- and print-hook 8/22/96
;; real parameters 9/27/96
;; print-line parameter 8/18/97
(unit/sig
mzlib:pretty-print^
(import)
(define pretty-print-show-inexactness
(make-parameter #f
(lambda (x) (and x #t))))
(define pretty-print-exact-as-decimal
(make-parameter #f
(lambda (x) (and x #t))))
(define pretty-print-columns
(make-parameter 79
(lambda (x)
(unless (or (eq? x 'infinity)
(integer? x))
(raise-type-error
'pretty-print-columns
"integer or 'infinity"
x))
x)))
(define pretty-print-depth
(make-parameter #f
(lambda (x)
(unless (or (not x) (number? x))
(raise-type-error
'pretty-print-depth
"number or #f"
x))
x)))
(define can-accept-n?
(lambda (n x)
(procedure-arity-includes? x n)))
(define pretty-print-size-hook
(make-parameter (lambda (x display? port) #f)
(lambda (x)
(unless (can-accept-n? 3 x)
(raise-type-error
'pretty-print-size-hook
"procedure of 3 arguments"
x))
x)))
(define pretty-print-print-hook
(make-parameter void
(lambda (x)
(unless (can-accept-n? 3 x)
(raise-type-error
'pretty-print-print-hook
"procedure of 3 arguments"
x))
x)))
(define pretty-print-display-string-handler
(make-parameter (let ([dh (port-display-handler (open-output-string))])
; dh is primitive port display handler
dh)
(lambda (x)
(unless (can-accept-n? 2 x)
(raise-type-error
'pretty-print-display-string-handler
"procedure of 2 arguments"
x))
x)))
(define pretty-print-print-line
(make-parameter (lambda (line port offset width)
(when (and (number? width)
(not (eq? 0 line)))
(newline port))
0)
(lambda (x)
(unless (can-accept-n? 4 x)
(raise-type-error
'pretty-print-print-line
"procedure of 4 arguments"
x))
x)))
(define pretty-print-pre-print-hook
(make-parameter void
(lambda (x)
(unless (can-accept-n? 2 x)
(raise-type-error
'pretty-print-pre-print-hook
"procedure of 2 arguments"
x))
x)))
(define pretty-print-post-print-hook
(make-parameter void
(lambda (x)
(unless (can-accept-n? 2 x)
(raise-type-error
'pretty-print-post-print-hook
"procedure of 2 arguments"
x))
x)))
(define make-pretty-print
(lambda (display?)
(letrec ([pretty-print
(case-lambda
[(obj port)
(let ([width (pretty-print-columns)]
[size-hook (pretty-print-size-hook)]
[print-hook (pretty-print-print-hook)]
[pre-hook (pretty-print-pre-print-hook)]
[post-hook (pretty-print-post-print-hook)])
(generic-write obj display?
width
(let ([display (pretty-print-display-string-handler)])
(lambda (s)
(display s port)
#t))
(lambda (s l)
(print-hook s display? port)
#t)
(print-graph) (print-struct)
(and (not display?) (print-vector-length))
(pretty-print-depth)
(lambda (o display?)
(size-hook o display? port))
(let ([print-line (pretty-print-print-line)])
(lambda (line offset)
(print-line line port offset width)))
(lambda (obj)
(pre-hook obj port))
(lambda (obj)
(post-hook obj port)))
(void))]
[(obj) (pretty-print obj (current-output-port))])])
pretty-print)))
(define pretty-print (make-pretty-print #f))
(define pretty-display (make-pretty-print #t))
(define (generic-write obj display? width output output-hooked
print-graph? print-struct? print-vec-length?
depth size-hook print-line
pre-print post-print)
(define line-number 0)
(define table (make-hash-table)) ; Hash table for looking for loops
(define show-inexactness? (pretty-print-show-inexactness))
(define exact-as-decimal? (pretty-print-exact-as-decimal))
(define-struct mark (str def))
(define found-cycle
(or print-graph?
(let loop ([obj obj])
(and (or (vector? obj)
(pair? obj)
(box? obj)
(and (struct? obj) print-struct?))
(or (hash-table-get table obj (lambda () #f))
(begin
(hash-table-put! table obj #t)
(let ([cycle
(cond
[(vector? obj)
(ormap loop (vector->list obj))]
[(pair? obj)
(or (loop (car obj))
(loop (cdr obj)))]
[(box? obj) (loop (unbox obj))]
[(struct? obj)
(ormap loop
(vector->list (struct->vector obj)))])])
(hash-table-remove! table obj)
cycle)))))))
(define :::dummy:::
(if found-cycle
(let loop ([obj obj])
(if (or (vector? obj)
(pair? obj)
(box? obj)
(and (struct? obj) print-struct?))
; A little confusing: use #t for not-found
(let ([p (hash-table-get table obj (lambda () #t))])
(when (not (mark? p))
(if p
(begin
(hash-table-put! table obj #f)
(cond
[(vector? obj)
(loop (vector->list obj))]
[(pair? obj)
(loop (car obj))
(loop (cdr obj))]
[(box? obj) (loop (unbox obj))]
[(struct? obj)
(for-each loop
(vector->list (struct->vector obj)))]))
(begin
(hash-table-put! table obj
(make-mark #f (box #f)))))))))))
(define cycle-counter 0)
(define found (if found-cycle
table
#f))
(define dsub1 (lambda (d)
(if d
(sub1 d)
#f)))
(print-line
#f
(let generic-write ([obj obj] [display? display?]
[width width]
[output output] [output-hooked output-hooked]
[depth depth] [def-box (box #t)]
[startpos (print-line 0 0)]
[pre-print pre-print] [post-print post-print])
(define (read-macro? l)
(define (length1? l) (and (pair? l) (null? (cdr l))))
(let ((head (car l)) (tail (cdr l)))
(case head
((quote quasiquote unquote unquote-splicing) (length1? tail))
(else #f))))
(define (read-macro-body l)
(cadr l))
(define (read-macro-prefix l)
(let ((head (car l)))
(case head
((quote) "'")
((quasiquote) "`")
((unquote) ",")
((unquote-splicing) ",@"))))
(define (drop-repeated l)
(if (null? l)
null
(let ([rest (drop-repeated (cdr l))])
(cond
[(and (pair? rest)
(null? (cdr rest))
(eq? (car l) (car rest)))
rest]
[(eq? rest (cdr l)) l]
[else (cons (car l) rest)]))))
(define (out str col)
(and col (output str) (+ col (string-length str))))
(define expr-found
(lambda (ref col)
(let ([n cycle-counter])
(set! cycle-counter (add1 cycle-counter))
(set-mark-str! ref
(string-append "#"
(number->string n)
"#"))
(set-mark-def! ref def-box)
(out (string-append "#"
(number->string n)
"=")
col))))
(define check-expr-found
(lambda (obj check? col c-k d-k n-k)
(let ([ref (and check?
found
(hash-table-get found obj (lambda () #f)))])
(if (and ref (unbox (mark-def ref)))
(if c-k
(c-k (mark-str ref) col)
(out (mark-str ref) col))
(if (and ref d-k)
(d-k col)
(let ([col (if ref
(expr-found ref col)
col)])
(n-k col)))))))
(define (wr obj col depth)
(define (wr-expr expr col depth)
(if (read-macro? expr)
(wr (read-macro-body expr) (out (read-macro-prefix expr) col) depth)
(wr-lst expr col #t depth)))
(define (wr-lst l col check? depth)
(if (pair? l)
(check-expr-found
l check? col
#f #f
(lambda (col)
(if (and depth (zero? depth))
(out "(...)" col)
(let loop ((l (cdr l)) (col (wr (car l) (out "(" col) (dsub1 depth))))
(check-expr-found
l (and check? (pair? l)) col
(lambda (s col) (out ")" (out s (out " . " col))))
(lambda (col)
(out ")" (wr-lst l (out " . " col) check? (dsub1 depth))))
(lambda (col)
(and col
(cond
((pair? l)
(if (and (eq? (car l) 'unquote)
(pair? (cdr l))
(null? (cddr l)))
(out ")" (wr (cadr l) (out " . ," col) (dsub1 depth)))
(loop (cdr l) (wr (car l) (out " " col) (dsub1 depth)))))
((null? l) (out ")" col))
(else
(out ")" (wr l (out " . " col) (dsub1 depth))))))))))))
(out "()" col)))
(pre-print obj)
(begin0
(if (and depth (negative? depth))
(out "..." col)
(cond ((size-hook obj display?)
=> (lambda (len)
(and col
(output-hooked obj len)
(+ len col))))
((pair? obj) (wr-expr obj col depth))
((null? obj) (wr-lst obj col #f depth))
((vector? obj) (check-expr-found
obj #t col
#f #f
(lambda (col)
(wr-lst (let ([l (vector->list obj)])
(if print-vec-length?
(drop-repeated l)
l))
(let ([col (out "#" col)])
(if print-vec-length?
(out (number->string (vector-length obj)) col)
col))
#f depth))))
((box? obj) (check-expr-found
obj #t col
#f #f
(lambda (col)
(wr (unbox obj) (out "#&" col)
(dsub1 depth)))))
((struct? obj) (if (and print-struct?
(not (and depth
(zero? depth))))
(check-expr-found
obj #t col
#f #f
(lambda (col)
(wr-lst (vector->list
(struct->vector obj))
(out "#" col) #f
depth)))
(out
(let ([p (open-output-string)]
[p-s (print-struct)])
(when p-s
(print-struct #f))
((if display? display write) obj p)
(when p-s
(print-struct p-s))
(get-output-string p))
col)))
((boolean? obj) (out (if obj "#t" "#f") col))
((number? obj)
(when (and show-inexactness?
(inexact? obj))
(out "#i" col))
(out ((if exact-as-decimal?
number->decimal-string
number->string)
obj) col))
;; Let symbol get printed by default case to get proper quoting
;; ((symbol? obj) (out (symbol->string obj) col))
((string? obj) (if display?
(out obj col)
(let loop ((i 0) (j 0) (col (out "\"" col)))
(if (and col (< j (string-length obj)))
(let ((c (string-ref obj j)))
(if (or (char=? c #\\)
(char=? c #\"))
(loop j
(+ j 1)
(out "\\"
(out (substring obj i j)
col)))
(loop i (+ j 1) col)))
(out "\""
(out (substring obj i j) col))))))
((char? obj) (if display?
(out (make-string 1 obj) col)
(out (case obj
((#\space) "space")
((#\newline) "newline")
((#\linefeed) "linefeed")
((#\return) "return")
((#\rubout) "rubout")
((#\backspace)"backspace")
((#\nul) "nul")
((#\page) "page")
((#\tab) "tab")
((#\vtab) "vtab")
((#\newline) "newline")
(else (make-string 1 obj)))
(out "#\\" col))))
(else (out (let ([p (open-output-string)])
((if display? display write) obj p)
(get-output-string p))
col))))
(post-print obj)))
(define (pp obj col depth)
(define (spaces n col)
(if (> n 0)
(if (> n 7)
(spaces (- n 8) (out " " col))
(out (substring " " 0 n) col))
col))
(define (indent to col)
(and col
(if (< to col)
(and col
(begin
(set! line-number (add1 line-number))
(let ([col (print-line line-number col)])
(spaces (- to col) col))))
(spaces (- to col) col))))
(define (pr obj col extra pp-pair depth)
; may have to split on multiple lines
(let* ([can-multi (or (pair? obj) (vector? obj)
(box? obj) (and (struct? obj) print-struct?))]
[ref (if can-multi
(and found (hash-table-get found obj (lambda () #f)))
#f)])
(if (and can-multi
(or (not ref) (not (unbox (mark-def ref)))))
(let* ((result '())
(result-tail #f)
(new-def-box (box #t))
(left (+ (- (- width col) extra) 1))
(snoc (lambda (s len)
(let ([v (cons s null)])
(if result-tail
(set-cdr! result-tail v)
(set! result v))
(set! result-tail v))
(set! left (- left len))
(> left 0))))
(generic-write obj display? #f
(lambda (s)
(snoc s (string-length s)))
(lambda (s l)
(snoc (cons s l) l))
depth
new-def-box
0
(lambda (obj)
(snoc (cons 'pre obj) 0))
(lambda (obj)
(snoc (cons 'post obj) 0)))
(if (> left 0) ; all can be printed on one line
(let loop ([result result][col col])
(if (null? result)
col
(loop (cdr result)
(+ (let ([v (car result)])
(if (pair? v)
(cond
[(eq? (car v) 'pre)
(pre-print (cdr v))
col]
[(eq? (car v) 'post)
(post-print (cdr v))
col]
[else
(output-hooked (car v) (cdr v))
(+ col (cdr v))])
(out (car result) col)))))))
(begin
(set-box! new-def-box #f)
(let ([col
(if ref
(expr-found ref col)
col)])
(pre-print obj)
(begin0
(cond
[(pair? obj) (pp-pair obj col extra depth)]
[(vector? obj)
(pp-list (let ([l (vector->list obj)])
(if print-vec-length?
(drop-repeated l)
l))
(let ([col (out "#" col)])
(if print-vec-length?
(out (number->string (vector-length obj)) col)
col))
extra pp-expr #f depth)]
[(struct? obj)
(pp-list (vector->list (struct->vector obj))
(out "#" col) extra pp-expr #f depth)]
[(box? obj)
(pr (unbox obj) (out "#&" col) extra pp-pair depth)])
(post-print obj))))))
(wr obj col depth))))
(define (pp-expr expr col extra depth)
(if (read-macro? expr)
(pr (read-macro-body expr)
(out (read-macro-prefix expr) col)
extra
pp-expr
depth)
(let ((head (car expr)))
(if (symbol? head)
(let ((proc (style head)))
(if proc
(proc expr col extra depth)
(if (> (string-length (symbol->string head))
max-call-head-width)
(pp-general expr col extra #f #f #f pp-expr depth)
(pp-list expr col extra pp-expr #t depth))))
(pp-list expr col extra pp-expr #t depth)))))
; (head item1
; item2
; item3)
(define (pp-call expr col extra pp-item depth)
(let ((col* (wr (car expr) (out "(" col) (dsub1 depth))))
(and col
(pp-down (cdr expr) col* (+ col* 1) extra pp-item #t #t depth))))
; (head item1 item2
; item3
; item4)
(define (pp-two-up expr col extra pp-item depth)
(let ((col* (wr (car expr) (out "(" col) (dsub1 depth)))
(col*2 (wr (cadr expr) (out " " col) (dsub1 depth))))
(and col
(pp-down (cddr expr) (+ col 1) (+ col 2) extra pp-item #t #t depth))))
; (head item1
; item2
; item3)
(define (pp-one-up expr col extra pp-item depth)
(let ((col* (wr (car expr) (out "(" col) (dsub1 depth))))
(and col
(pp-down (cdr expr) (+ col 1) (+ col 2) extra pp-item #t #t depth))))
; (item1
; item2
; item3)
(define (pp-list l col extra pp-item check? depth)
(let ((col (out "(" col)))
(pp-down l col col extra pp-item #f check? depth)))
(define (pp-down l col1 col2 extra pp-item check-first? check-rest? depth)
(let loop ((l l) (col col1) (check? check-first?))
(and col
(check-expr-found
l (and check? (pair? l)) col
(lambda (s col)
(out ")" (out s (indent col2 (out "." (indent col2 col))))))
(lambda (col)
(out ")" (pr l (indent col2 (out "." (indent col2 col)))
extra pp-item depth)))
(lambda (col)
(cond ((pair? l)
(let ((rest (cdr l)))
(let ((extra (if (null? rest) (+ extra 1) 0)))
(loop rest
(pr (car l) (indent col2 col)
extra pp-item
(dsub1 depth))
check-rest?))))
((null? l)
(out ")" col))
(else
(out ")"
(pr l
(indent col2 (out "." (indent col2 col)))
(+ extra 1)
pp-item
(dsub1 depth))))))))))
(define (pp-general expr col extra named? pp-1 pp-2 pp-3 depth)
(define (tail1 rest col1 col2 col3)
(if (and pp-1 (pair? rest))
(let* ((val1 (car rest))
(rest (cdr rest))
(extra (if (null? rest) (+ extra 1) 0)))
(tail2 rest col1 (pr val1 (indent col3 col2) extra pp-1 depth) col3))
(tail2 rest col1 col2 col3)))
(define (tail2 rest col1 col2 col3)
(if (and pp-2 (pair? rest))
(let* ((val1 (car rest))
(rest (cdr rest))
(extra (if (null? rest) (+ extra 1) 0)))
(tail3 rest col1 (pr val1 (indent col3 col2) extra pp-2 depth)))
(tail3 rest col1 col2)))
(define (tail3 rest col1 col2)
(pp-down rest col2 col1 extra pp-3 #f #t depth))
(let* ((head (car expr))
(rest (cdr expr))
(col* (wr head (out "(" col) (dsub1 depth))))
(if (and named? (pair? rest))
(let* ((name (car rest))
(rest (cdr rest))
(col** (wr name (out " " col*) (dsub1 depth))))
(tail1 rest (+ col indent-general) col** (+ col** 1)))
(tail1 rest (+ col indent-general) col* (+ col* 1)))))
(define (pp-expr-list l col extra depth)
(pp-list l col extra pp-expr #t depth))
(define (pp-lambda expr col extra depth)
(pp-general expr col extra #f pp-expr-list #f pp-expr depth))
(define (pp-if expr col extra depth)
(pp-general expr col extra #f pp-expr #f pp-expr depth))
(define (pp-cond expr col extra depth)
(pp-list expr col extra pp-expr-list #t depth))
(define (pp-class expr col extra depth)
(pp-two-up expr col extra pp-expr-list depth))
(define (pp-make-object expr col extra depth)
(pp-one-up expr col extra pp-expr-list depth))
(define (pp-case expr col extra depth)
(pp-general expr col extra #f pp-expr #f pp-expr-list depth))
(define (pp-and expr col extra depth)
(pp-call expr col extra pp-expr depth))
(define (pp-let expr col extra depth)
(let* ((rest (cdr expr))
(named? (and (pair? rest) (symbol? (car rest)))))
(pp-general expr col extra named? pp-expr-list #f pp-expr depth)))
(define (pp-begin expr col extra depth)
(pp-general expr col extra #f #f #f pp-expr depth))
(define (pp-do expr col extra depth)
(pp-general expr col extra #f pp-expr-list pp-expr-list pp-expr depth))
; define formatting style (change these to suit your style)
(define indent-general 2)
(define max-call-head-width 5)
(define (style head)
(case head
((lambda let* letrec define shared
unless #%unless
when #%when
'|$\spadesuit$|
#%lambda #%let* #%letrec #%define
define-macro #%define-macro)
pp-lambda)
((if set! #%if #%set!)
pp-if)
((cond #%cond public private import export)
pp-cond)
((case #%case)
pp-case)
((and or #%and #%or link)
pp-and)
((let #%let)
pp-let)
((begin #%begin)
pp-begin)
((do #%do)
pp-do)
((send class #%class) pp-class)
((send make-object) pp-make-object)
(else #f)))
(pr obj col 0 pp-expr depth))
(if (and width (not (eq? width 'infinity)))
(pp obj startpos depth)
(wr obj startpos depth)))))
(define pretty-print-handler
(lambda (v)
(unless (void? v)
(pretty-print v))))
(define (number->decimal-string x)
(cond
[(or (inexact? x)
(integer? x))
(number->string x)]
[(not (real? x))
(let ([r (real-part x)]
[i (imag-part x)])
(format "~a~a~ai"
(number->decimal-string r)
(if (negative? i)
""
"+")
(number->decimal-string i)))]
[else
(let ([n (numerator x)]
[d (denominator x)])
;; Count powers of 2 in denomintor
(let loop ([v d][2-power 0])
(if (and (positive? v)
(even? v))
(loop (arithmetic-shift v -1) (add1 2-power))
;; Count powers of 5 in denominator
(let loop ([v v][5-power 0])
(if (zero? (remainder v 5))
(loop (quotient v 5) (add1 5-power))
;; No more 2s or 5s. Anything left?
(if (= v 1)
;; Denominator = (* (expt 2 2-power) (expt 5 5-power)).
;; Print number as decimal.
(let* ([10-power (max 2-power 5-power)]
[scale (* (expt 2 (- 10-power 2-power))
(expt 5 (- 10-power 5-power)))]
[s (number->string (* (abs n) scale))]
[orig-len (string-length s)]
[len (max (add1 10-power) orig-len)]
[padded-s (if (< orig-len len)
(string-append
(make-string (- len orig-len) #\0)
s)
s)])
(format "~a~a.~a"
(if (negative? n) "-" "")
(substring padded-s 0 (- len 10-power))
(substring padded-s (- len 10-power) len)))
;; d has factor(s) other than 2 and 5.
;; Print as a fraction.
(number->string x)))))))]))
)

16
collects/mzlib/prettys.ss Normal file
View File

@ -0,0 +1,16 @@
(define-signature mzlib:pretty-print^
(pretty-print
pretty-display
pretty-print-columns
pretty-print-depth
pretty-print-handler
pretty-print-size-hook
pretty-print-print-hook
pretty-print-pre-print-hook
pretty-print-post-print-hook
pretty-print-display-string-handler
pretty-print-print-line
pretty-print-show-inexactness
pretty-print-exact-as-decimal))

View File

@ -0,0 +1,8 @@
(require-library "prettys.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:pretty-print@ (require-library-unit/sig "prettyr.ss"))

22
collects/mzlib/refer.ss Normal file
View File

@ -0,0 +1,22 @@
(define-macro begin-construction-time
(lambda body
`(#%begin-elaboration-time ,@body)))
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (require-unit reference-file)
(require-library "referf.ss")))
(define-macro require-library-unit/sig (require-unit #t #t #f #t 'require-library-unit/sig))
(define-macro require-library-unit (require-unit #t #t #f #f 'require-library-unit))
(define-macro require-relative-library-unit/sig (require-unit #t #t #t #t 'require-relative-library-unit/sig))
(define-macro require-relative-library-unit (require-unit #t #t #t #f 'require-relative-library-unit))
(define-macro require-unit/sig (require-unit #t #f #f #t 'require-unit/sig))
(define-macro require-unit (require-unit #t #f #f #f 'require-unit))
(define-macro reference-file (reference-file #t #f #f))
(require-library "spidey.ss")

76
collects/mzlib/referf.ss Normal file
View File

@ -0,0 +1,76 @@
(unit
(import)
(export (make-require-unit require-unit) (make-require reference-file))
(define make-require-unit
; require-unit, etc.
(lambda (must-string? require? reqrel? sig? sname)
(lambda names
(let ([len (length names)]
[expect (if require? +inf.0 1)])
(unless (and (positive? len) (<= len expect))
((raise-syntax-error sname
(format "expected ~a names; given ~a"
(if (= +inf.0 expect)
"some"
expect)
len)
(list* sname names)))))
(let ([names (if must-string?
(map local-expand-defmacro names)
names)])
(unless (or (not must-string?))
(for-each
(lambda (s)
(unless s
(raise-syntax-error sname
"name is not a string"
(list* sname names)
s)))
names))
`(#%let ([result (,(if require?
(if reqrel?
'#%require-relative-library/proc
'#%require-library/proc)
'#%load/use-compiled) ,@names)])
(#%unless (,(if sig?
'#%unit/sig?
'#%unit?)
result)
(#%raise
(#%make-exn:unit
,(format "~s: result from ~s is not a ~aunit"
sname names (if sig? "signed " ""))
(#%current-continuation-marks))))
result)))))
(define make-require
; require
(lambda (must-string? require? reqrel?)
(lambda names
(let ([sname (if require?
(if reqrel?
'require-relative-library
'require-library)
'require)]
[len (length names)]
[expect (if require? +inf.0 1)])
(unless (and (positive? len) (<= len expect))
((raise-syntax-error sname
(format "expected ~a names; given ~a"
expect len)
(list* sname names))))
(let ([names (if must-string?
(map local-expand-defmacro names)
names)])
(unless (or (not must-string?) (map string? names))
(raise-syntax-error sname
"filename is not a string"
(list* sname names)))
`(,(if require?
(if reqrel?
'require-relative-library/proc
'require-library/proc)
'#%load/use-compiled)
,@names)))))))

11
collects/mzlib/restart.ss Normal file
View File

@ -0,0 +1,11 @@
(require-library "cmdline.ss")
(require-library "restartu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:restart^
mzlib:restart@
#f
mzlib:command-line^)

178
collects/mzlib/restartr.ss Normal file
View File

@ -0,0 +1,178 @@
(unit/sig mzlib:restart^
(import mzlib:command-line^)
(define (restart-mzscheme init-argv adjust-flag-table argv init-namespace)
(let* ([args #f]
[mute-banner? #f]
[no-rep? #f]
[no-coll-paths? #f]
[no-init-file? #f]
[case-sensitive? #f]
[esc-cont-only? #f]
[allow-set!-undefined? #t]
[no-auto-else? #f]
[no-enforce-keywords? #f]
[hp-only? #f]
[print-error
(lambda (e)
(if (exn? e)
(fprintf (current-error-port) "~a~n" (exn-message e))
(fprintf (current-error-port) "Exception in init file: ~e~n" e)))]
[table
`([multi
[("-e")
,(lambda (f expr) expr)
("Evaluates <expr>" "expr")]
[("-f")
,(lambda (f file) (format "(load ~s)" file))
("Loads <file>" "file")]
[("-f")
,(lambda (f file) (format "(load/cd ~s)" file))
("Load/cds <file>" "file")]
[("-F")
,(lambda (f . files) (map (lambda (file)
(format "(load ~s)" file))
files))
("Loads all <file>s" "file")]
[("-D")
,(lambda (f . files) (map (lambda (file)
(format "(load/cd ~s)" file))
files))
("Load/cds all <file>s" "file")]
[("-l")
,(lambda (f file) (format "(require-library ~s)" file))
("Requires library <file>" "file")]
[("-L")
,(lambda (f file collection) (format "(require-library ~s ~s)" file collection))
("Requires library <file> in <collection>" "file" "collection")]
[("-r" "--script")
,(lambda (f file . rest)
(format "(load ~s)" file)
(set! mute-banner? #t)
(set! no-rep? #t)
(set! args rest))
("Same as -fmv-" "file" "arg")]
[("-i" "--script-cd")
,(lambda (f file . rest)
(format "(load/cd ~s)" file)
(set! mute-banner? #t)
(set! no-rep? #t)
(set! args rest))
("Same as -dmv-" "file" "arg")]
[("-w" "--awk")
,(lambda (f) "(require-library \"awk.ss\")")
("Same as -l awk.ss")]
[("-x" "--no-init-path")
,(lambda (f) (set! no-coll-paths? #t))
("Don't set current-library-collection-paths")]
[("-q" "--no-init-file")
,(lambda (f) (set! no-init-file? #t))
("Don't load \"~/.mzschemerc\" or \"mzscheme.rc\"")]
[("-g" "--case-sens")
,(lambda (f) (set! case-sensitive? #t))
("Identifiers and symbols are initially case-sensitive")]
[("-c" "--esc-cont")
,(lambda (f) (set! esc-cont-only? #t))
("Call/cc is replaced with call/ec")]
[("-s" "--set-undef")
,(lambda (f) (set! allow-set!-undefined? #t))
("Set! works on undefined identifiers")]
[("-a" "--no-auto-else")
,(lambda (f) (set! no-auto-else? #t))
("Fall-through cond or case is an error")]
[("-n" "--no-key")
,(lambda (f) (set! no-enforce-keywords? #t))
("Keywords are not enforced")]
[("-y" "--hash-percent-syntax")
,(lambda (f) (set! hp-only? #t))
("Only #% syntactic forms are present")]
[("-m" "--mute-banner")
,(lambda (f) (set! mute-banner? #t))
("Suppresses the startup banner text")]
[("-v" "--version")
,(lambda (f) (set! no-rep? #t))
("Suppresses the read-eval-print loop")]
[("--restore")
,(lambda (f) (error 'mzscheme "The --restore flag is not supported in this mode"))
("Not supported")]])])
(parse-command-line
"mzscheme"
argv
table
void
'("ignored"))
(set! args #f)
(parse-command-line
"mzscheme"
argv
(adjust-flag-table table)
(lambda (exprs . rest)
(unless (null? rest)
(set! args rest))
;(when args (set! rest args))
(let ([n (make-namespace
(if no-enforce-keywords? 'no-keywords 'keywords)
(if esc-cont-only? 'call/cc=call/ec 'call/cc!=call/ec)
(if hp-only? 'hash-percent-syntax 'all-syntax))])
(thread-wait
(thread
(lambda ()
(current-namespace n)
(let ([program (with-handlers ([void (lambda (x) "MzScheme")])
(global-defined-value 'program))])
(read-case-sensitive case-sensitive?)
(compile-allow-set!-undefined allow-set!-undefined?)
(compile-allow-cond-fallthrough (not no-auto-else?))
(unless mute-banner? (display (banner)))
(eval `(#%define-values (argv) (#%quote ,(if args (list->vector args) (vector)))))
(eval `(#%define-values (program) (#%quote ,program)))
(current-library-collection-paths
(if no-coll-paths?
#f
(path-list-string->path-list
(or (getenv "PLTCOLLECTS") "")
(or
(ormap
(lambda (f) (let ([p (f)]) (and p (directory-exists? p) (list p))))
(list
(lambda () (let ((v (getenv "PLTHOME")))
(and v (build-path v "collects"))))
(lambda () (find-executable-path program "collects"))
(lambda ()
(case (system-type)
[(unix beos) "/usr/local/lib/plt/collects"]
[(windows) "c:\\plt\\collects"]
[else #f]))))
null)))))
(init-namespace)
(unless no-init-file?
(let ([f (case (system-type)
[(unix beos) "~/.mzschemerc"]
[else "mzscheme.rc"])])
(when (file-exists? f)
(with-handlers ([void print-error])
(load f)))))
(let ([result
(let/ec escape
(for-each
(lambda (e)
(with-handlers ([void (lambda (e) (print-error e) (escape #f))])
(eval (read (open-input-string e)))))
exprs)
#t)])
(let/ec k
(exit-handler
(lambda (status)
(when result
(set! result (= status 0)))
(k #f)))
(unless no-rep? (read-eval-print-loop)))
result))))))
`("arg")))))

View File

@ -0,0 +1,6 @@
(begin-elaboration-time
(require-library "cmdlines.ss"))
(define-signature mzlib:restart^
(restart-mzscheme))

View File

@ -0,0 +1,7 @@
(require-library "restarts.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:restart@ (require-library-unit/sig "restartr.ss"))

14
collects/mzlib/shared.ss Normal file
View File

@ -0,0 +1,14 @@
(begin-elaboration-time
(require-library "functios.ss"))
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (shared)
(require-library "sharedr.ss")))
(define-macro shared shared)

146
collects/mzlib/sharedr.ss Normal file
View File

@ -0,0 +1,146 @@
(unit/sig->unit
(compound-unit/sig
(import)
(link [FUNCTION : mzlib:function^ ((require-library "functior.ss") )]
[SHARED : (shared) (
(unit/sig (shared)
(import mzlib:function^)
;; SHARED starts here
(define shared
(let ()
(define-struct twople (left right))
(define-struct cons-rhs (id car cdr))
(define-struct vector-rhs (id args))
(define-struct box-rhs (id arg))
(define-struct weak-box-rhs (id let arg))
(define-struct trans (rhs lets set!s))
(lambda (defns . body)
(letrec ([bad (lambda (s sexp)
(error 'shared (string-append s ": ~a") sexp))]
[build-args
(lambda (args howmany)
(cond
[(null? args) '()]
[(pair? args) (cons (car args)
(build-args (cdr args)
(if (number? howmany)
(sub1 howmany)
howmany)))]
[else (bad "args" args)]))]
[build-args1
(lambda (x)
(cond
[(and (pair? x) (null? (cdr x))) (list (car x))]
[else (bad "args" x)]))]
[build-args2
(lambda (x)
(if (pair? x)
(let ((xcdr (cdr x)))
(if (pair? xcdr)
(let ((xcdrcdr (cdr xcdr)))
(if (null? xcdrcdr)
(list (car x) (car xcdr))
(bad "args" x)))
(bad "args" x)))
(bad "args" x)))]
[build-defn
(lambda (x)
(unless (and (pair? x)
(symbol? (car x)))
(bad "bad binding" x))
(if (not (and (pair? (cdr x))
(pair? (cadr x))
(symbol? (caadr x))))
(make-trans x '() '())
(let ([id (car x)]
[constructor (caadr x)]
[args (cdadr x)])
(case constructor
[(list) (let ([args (build-args args 'whatever)])
(if (null? args)
(make-trans `(,id (list))
'()
'())
(make-cons-rhs id (car args) `(list ,@(cdr args)))))]
[(vector) (let ([args (build-args args 'whatever)])
(make-vector-rhs id args))]
[(box) (let ([args (build-args1 args)])
(make-box-rhs id (car args)))]
; [(make-weak-box) (let ([args (build-args1 args)])
; (make-weak-box-rhs id (car args)))]
[(cons) (let ([args (build-args2 args)])
(make-cons-rhs id (car args) (cadr args)))]
[else (make-trans x '() '())]))))]
[build-defns
(lambda (x)
(cond
[(null? x) '()]
[(pair? x) (cons (build-defn (car x))
(build-defns (cdr x)))]
[else (bad "defns list" x)]))]
[transform
(lambda (binding)
(cond
[(vector-rhs? binding)
(let ()
(define-struct b&s (bind set!))
(let* ([id (vector-rhs-id binding)])
(let ([elems
(twople-left
(foldl (lambda (x data)
(let ([list (twople-left data)]
[i (twople-right data)]
[eid (gensym)])
(make-twople (cons (make-b&s `(,eid ,x)
`(vector-set! ,id ,i ,eid))
list)
(+ i 1))))
(make-twople '() 0)
(vector-rhs-args binding)))])
(make-trans `(,id (vector ,@(map (lambda (x) '(void))
(vector-rhs-args binding))))
(map b&s-bind elems)
(map b&s-set! elems)))))]
[(box-rhs? binding)
(let ([id (box-rhs-id binding)]
[eid (gensym)])
(make-trans `(,id (box (void)))
(list `(,eid ,(box-rhs-arg binding)))
(list `(set-box! ,id ,eid))))]
[(weak-box-rhs? binding)
(let ([id (weak-box-rhs-id binding)]
[eid (gensym)])
(make-trans `(,id (make-weak-box (void)))
(list `(,eid ,(weak-box-rhs-arg binding)))
(list `(set-weak-box! ,id ,eid))))]
[(cons-rhs? binding)
(let ([id (cons-rhs-id binding)]
[car-id (gensym)]
[cdr-id (gensym)])
(make-trans `(,id (cons (void) (void)))
(list `(,car-id ,(cons-rhs-car binding))
`(,cdr-id ,(cons-rhs-cdr binding)))
(list `(set-car! ,id ,car-id)
`(set-cdr! ,id ,cdr-id))))]
[(trans? binding) binding]
[else (bad "internal error:" binding)]))]
[transformed-defns (map transform (build-defns defns))])
(list 'letrec
(map trans-rhs transformed-defns)
(list 'let (apply append (map trans-lets transformed-defns))
(cons 'begin
(append (apply append (map trans-set!s transformed-defns))
body)))))))))
;; SHARED ends here
FUNCTION)])
(export (var (SHARED shared)))))

15
collects/mzlib/spidey.ss Normal file
View File

@ -0,0 +1,15 @@
(define-macro define-constructor
(lambda args '(#%void)))
(define-macro define-type
(lambda args '(#%void)))
(define-macro :
(lambda (v . args) v))
(define-macro mrspidey:control
(lambda args '(#%void)))
(define-macro polymorphic
(lambda (arg) arg))

9
collects/mzlib/string.ss Normal file
View File

@ -0,0 +1,9 @@
(require-library "stringu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:string^
mzlib:string@)

104
collects/mzlib/stringr.ss Normal file
View File

@ -0,0 +1,104 @@
(unit/sig
mzlib:string^
(import)
(define make-string-do!
(lambda (translate)
(lambda (s)
(let loop ([n (sub1 (string-length s))])
(unless (negative? n)
(string-set! s n
(translate (string-ref s n)))
(loop (sub1 n)))))))
(define string-lowercase! (make-string-do! char-downcase))
(define string-uppercase! (make-string-do! char-upcase))
(define eval-string
(let ([do-eval
(lambda (str)
(let ([p (open-input-string str)])
(apply
values
(let loop ()
(let ([e (read p)])
(if (eof-object? e)
'()
(call-with-values
(lambda () (eval e))
(case-lambda
[() (loop)]
[(only) (cons only (loop))]
[multi
(append multi (loop))]))))))))])
(case-lambda
[(str) (eval-string str #f #f)]
[(str error-display) (eval-string str error-display #f)]
[(str error-display error-result)
(if (or error-display error-result)
(with-handlers ([void
(lambda (exn)
((or error-display (error-display-handler))
(exn-message exn))
(if error-result
(error-result)
#f))])
(do-eval str))
(do-eval str))])))
(define read-from-string-one-or-all
(case-lambda
[(k all? str) (read-from-string-one-or-all k all? str #f #f)]
[(k all? str error-display) (read-from-string-one-or-all k all? str error-display #f)]
[(k all? str error-display error-result)
(let* ([p (open-input-string str)]
[go (lambda ()
(let loop ()
(let ([v (read p)])
(if (eof-object? v)
'()
(cons v
(if all?
(loop)
'()))))))])
(if error-display
(with-handlers ([void
(lambda (exn)
((or error-display (error-display-handler))
(exn-message exn))
(k (if error-result
(error-result)
#f)))])
(go))
(go)))]))
(define read-from-string
(lambda args
(let/ec k
(let ([l (apply read-from-string-one-or-all k #f args)])
(if (null? l)
eof
(car l))))))
(define read-from-string-all
(lambda args
(let/ec k
(apply read-from-string-one-or-all k #t args))))
(define expr->string
(lambda (v)
(let* ([s ""]
[write-to-s
(lambda (str)
(set! s (string-append s str)))]
[port (make-output-port write-to-s (lambda () #f))])
(write v port)
s)))
(define newline-string (string #\newline))
(define regexp-match-exact?
(lambda (p s)
(let ([m (regexp-match p s)])
(and m
(string=? (car m) s)))))
)

11
collects/mzlib/strings.ss Normal file
View File

@ -0,0 +1,11 @@
(define-signature mzlib:string^
(string-lowercase!
string-uppercase!
eval-string
read-from-string
read-from-string-all
expr->string
newline-string
regexp-match-exact?))

View File

@ -0,0 +1,7 @@
(require-library "strings.ss")
(begin-elaboration-time
(require-library "refer.ss"))
(define mzlib:string@ (require-library-unit/sig "stringr.ss"))

22
collects/mzlib/synrule.ss Normal file
View File

@ -0,0 +1,22 @@
(begin-elaboration-time
(require-library "invoke.ss"))
(begin-elaboration-time
(define-values/invoke-unit (define-syntax
-:sr:tag
-:sr:untag
-:sr:flatten
-:sr:matches-pattern?
-:sr:get-bindings
-:sr:expand-pattern)
(require-library "synruler.ss")))
(define-macro define-syntax define-syntax)
(keyword-name '-:sr:tag)
(keyword-name '-:sr:untag)
(keyword-name '-:sr:flatten)
(keyword-name '-:sr:matches-pattern?)
(keyword-name '-:sr:get-bindings)
(keyword-name '-:sr:expand-pattern)

429
collects/mzlib/synruler.ss Normal file
View File

@ -0,0 +1,429 @@
; By Dorai Sitaram
; then Shriram Krishnamurthi
; then Matthew Flatt
(unit
(import)
(export define-syntax
-:sr:tag
-:sr:untag
-:sr:flatten
-:sr:matches-pattern?
-:sr:get-bindings
-:sr:expand-pattern)
(define -:sr:tag 'undefined--:sr:tag)
(define -:sr:untag 'undefined--:sr:untag)
(define -:sr:flatten 'undefined--:sr:flatten)
(letrec ([hyg:rassq
(lambda (k al)
(let loop ([al al])
(if (null? al)
#f
(let ([c (car al)])
(if (eq? (cdr c) k)
c
(loop (cdr al)))))))]
[hyg:tag
(lambda (e kk al)
(cond
[(pair? e)
(let* ((a-te-al (hyg:tag (car e) kk al))
(d-te-al (hyg:tag (cdr e) kk (cdr a-te-al))))
(cons (cons (car a-te-al) (car d-te-al))
(cdr d-te-al)))]
[(vector? e)
(let ([v-te-al (hyg:tag (vector->list e) kk al)])
(cons (list->vector (car v-te-al))
(cdr v-te-al)))]
[(symbol? e)
(cond
[(eq? e '...) (cons '... al)]
[(memq e kk) (cons e al)]
[(hyg:rassq e al)
=> (lambda (c)
(cons (car c) al))]
[else
(let ((te (gensym)))
(cons te (cons (cons te e) al)))])]
[else (cons e al)]))]
[hyg:untag
(lambda (e al tmps)
(if (pair? e)
(let ([a (hyg:untag (car e) al tmps)])
(if (list? e)
(case a
[(quote)
(hyg:untag-no-tags e al)]
[(quasiquote)
(list a (hyg:untag-quasiquote (cadr e) al tmps))]
[(if begin)
`(,a ,@(map (lambda (e1)
(hyg:untag e1 al tmps)) (cdr e)))]
[(set! define)
`(,a ,(hyg:untag-vanilla (cadr e) al tmps)
,@(map (lambda (e1)
(hyg:untag e1 al tmps)) (cddr e)))]
[(lambda)
(hyg:untag-lambda a (cadr e) (cddr e) al tmps)]
[(letrec)
(hyg:untag-letrec a (cadr e) (cddr e) al tmps)]
[(let)
(let ((e2 (cadr e)))
(if (symbol? e2)
(hyg:untag-named-let a e2 (caddr e) (cdddr e) al tmps)
(hyg:untag-let a e2 (cddr e) al tmps)))]
[(let*)
(hyg:untag-let* (cadr e) (cddr e) al tmps)]
[(do) (hyg:untag-do (cadr e) (caddr e) (cdddr e) al tmps)]
[(case)
`(case ,(hyg:untag-vanilla (cadr e) al tmps)
,@(map
(lambda (c)
`(,(hyg:untag-vanilla (car c) al tmps)
,@(hyg:untag-list (cdr c) al tmps)))
(cddr e)))]
[(cond)
`(cond ,@(map
(lambda (c)
(hyg:untag-list c al tmps))
(cdr e)))]
[else
; Must be an application:
(cons a (hyg:untag-list (cdr e) al tmps))])
(cons a (hyg:untag-list* (cdr e) al tmps))))
(hyg:untag-vanilla e al tmps)))]
[hyg:untag-list
(lambda (ee al tmps)
(map (lambda (e)
(hyg:untag e al tmps)) ee))]
[hyg:untag-list*
(lambda (ee al tmps)
(let loop ((ee ee))
(if (pair? ee)
(cons (hyg:untag (car ee) al tmps)
(loop (cdr ee)))
(hyg:untag ee al tmps))))]
[hyg:untag-no-tags
(lambda (e al)
(cond
[(pair? e)
(cons (hyg:untag-no-tags (car e) al)
(hyg:untag-no-tags (cdr e) al))]
[(vector? e)
(list->vector
(hyg:untag-no-tags (vector->list e) al))]
[(not (symbol? e)) e]
[(assq e al) => cdr]
[else e]))]
[hyg:untag-quasiquote
(lambda (form al tmps)
(let qq ([x form][level 0])
(cond
[(pair? x)
(let ([first (qq (car x) level)])
(cond
[(and (eq? first 'unquote) (list? x))
(let ([rest (cdr x)])
(if (or (not (pair? rest))
(not (null? (cdr rest))))
(raise-syntax-error
'unquote
"takes exactly one expression"
(list 'quasiquote (hyg:untag-no-tags form al)))
(if (zero? level)
(list 'unquote (hyg:untag (car rest) al tmps))
(cons first (qq rest (sub1 level))))))]
[(and (eq? first 'quasiquote) (list? x))
(cons 'quasiquote (qq (cdr x) (add1 level)))]
[(and (eq? first 'unquote-splicing) (list? x))
(raise-syntax-error
'unquote-splicing
"invalid context within quasiquote"
(list 'quasiquote (hyg:untag-no-tags form al)))]
[(pair? first)
(let ([car-first (qq (car first) level)])
(if (and (eq? car-first 'unquote-splicing)
(list? first))
(let ([rest (cdr first)])
(if (or (not (pair? rest))
(not (null? (cdr rest))))
(raise-syntax-error
'unquote-splicing
"takes exactly one expression"
(list 'quasiquote (hyg:untag-no-tags form al)))
(list (list 'unquote-splicing
(if (zero? level)
(hyg:untag (cadr rest) al tmps)
(qq (cadr rest) (sub1 level)))
(qq (cdr x) level)))))
(cons (cons car-first
(qq (cdr first) level))
(qq (cdr x) level))))]
[else
(cons first (qq (cdr x) level))]))]
[(vector? x)
(list->vector
(qq (vector->list x) level))]
[(box? x)
(box (qq (unbox x) level))]
[else (hyg:untag-no-tags x al)])))]
[hyg:untag-lambda
(lambda (formname bvv body al tmps)
(let ((tmps2 (append! (hyg:flatten bvv) tmps)))
`(,formname ,bvv
,@(hyg:untag-list body al tmps2))))]
[hyg:untag-letrec
(lambda (formname varvals body al tmps)
(let ((tmps (append! (map car varvals) tmps)))
`(,formname
,(map
(lambda (varval)
`(,(car varval)
,(hyg:untag (cadr varval) al tmps)))
varvals)
,@(hyg:untag-list body al tmps))))]
[hyg:untag-let
(lambda (formname varvals body al tmps)
(let ((tmps2 (append! (map car varvals) tmps)))
`(,formname
,(map
(lambda (varval)
`(,(car varval)
,(hyg:untag (cadr varval) al tmps)))
varvals)
,@(hyg:untag-list body al tmps2))))]
[hyg:untag-named-let
(lambda (formname lname varvals body al tmps)
(let ((tmps2 (cons lname (append! (map car varvals) tmps))))
`(,formname ,lname
,(map
(lambda (varval)
`(,(car varval)
,(hyg:untag (cadr varval) al tmps)))
varvals)
,@(hyg:untag-list body al tmps2))))]
[hyg:untag-let*
(lambda (varvals body al tmps)
(let ((tmps2 (append! (reverse! (map car varvals)) tmps)))
`(let*
,(let loop ((varvals varvals)
(i (length varvals)))
(if (null? varvals) '()
(let ((varval (car varvals)))
(cons `(,(car varval)
,(hyg:untag (cadr varval)
al (list-tail tmps2 i)))
(loop (cdr varvals) (- i 1))))))
,@(hyg:untag-list body al tmps2))))]
[hyg:untag-do
(lambda (varinistps exit-test body al tmps)
(let ((tmps2 (append! (map car varinistps) tmps)))
`(do
,(map
(lambda (varinistp)
(let ((var (car varinistp)))
`(,var ,@(hyg:untag-list (cdr varinistp) al
(cons var tmps)))))
varinistps)
,(hyg:untag-list exit-test al tmps2)
,@(hyg:untag-list body al tmps2))))]
[hyg:untag-vanilla
(lambda (e al tmps)
(cond
[(pair? e)
(cons (hyg:untag-vanilla (car e) al tmps)
(hyg:untag-vanilla (cdr e) al tmps))]
[(vector? e)
(list->vector
(hyg:untag-vanilla (vector->list e) al tmps))]
[(not (symbol? e)) e]
[(memq e tmps) e]
[(assq e al) => cdr]
[else e]))]
[hyg:flatten
(lambda (e)
(let loop ((e e) (r '()))
(cond
[(pair? e) (loop (car e)
(loop (cdr e) r))]
[(null? e) r]
[else (cons e r)])))])
(set! -:sr:tag hyg:tag)
(set! -:sr:untag hyg:untag)
(set! -:sr:flatten hyg:flatten))
(define -:sr:matches-pattern? 'undefined--:sr:matches-pattern?)
(define -:sr:get-bindings 'undefined--:sr:get-bindings)
(define -:sr:expand-pattern 'undefined--:sr:expand-pattern)
(letrec ([mbe:position
(lambda (x l)
(let loop ((l l) (i 0))
(cond ((not (pair? l)) #f)
((equal? (car l) x) i)
(else (loop (cdr l) (+ i 1))))))]
[mbe:append-map
(lambda (f l)
(let loop ((l l))
(if (null? l) '()
(append (f (car l)) (loop (cdr l))))))]
[mbe:matches-pattern?
(lambda (p e k)
(cond
[(mbe:ellipsis? p)
(and (or (null? e) (pair? e))
(let* ((p-head (car p))
(p-tail (cddr p))
(e-head=e-tail (mbe:split-at-ellipsis e p-tail)))
(and e-head=e-tail
(let ((e-head (car e-head=e-tail))
(e-tail (cdr e-head=e-tail)))
(and (andmap
(lambda (x) (mbe:matches-pattern? p-head x k))
e-head)
(mbe:matches-pattern? p-tail e-tail k))))))]
[(pair? p)
(and (pair? e)
(mbe:matches-pattern? (car p) (car e) k)
(mbe:matches-pattern? (cdr p) (cdr e) k))]
[(symbol? p) (if (memq p k) (eq? p e) #t)]
[else (equal? p e)]))]
[mbe:get-bindings
(lambda (p e k)
(cond
[(mbe:ellipsis? p)
(let* ((p-head (car p))
(p-tail (cddr p))
(e-head=e-tail (mbe:split-at-ellipsis e p-tail))
(e-head (car e-head=e-tail))
(e-tail (cdr e-head=e-tail)))
(cons (cons (mbe:get-ellipsis-nestings p-head k)
(map (lambda (x) (mbe:get-bindings p-head x k))
e-head))
(mbe:get-bindings p-tail e-tail k)))]
[(pair? p)
(append (mbe:get-bindings (car p) (car e) k)
(mbe:get-bindings (cdr p) (cdr e) k))]
[(symbol? p)
(if (memq p k) '() (list (cons p e)))]
[else '()]))]
[mbe:expand-pattern
(lambda (p r k)
(cond
[(mbe:ellipsis? p)
(append (let* ((p-head (car p))
(nestings (mbe:get-ellipsis-nestings p-head k))
(rr (mbe:ellipsis-sub-envs nestings r)))
(map (lambda (r1)
(mbe:expand-pattern p-head (append r1 r) k))
rr))
(mbe:expand-pattern (cddr p) r k))]
[(pair? p)
(cons (mbe:expand-pattern (car p) r k)
(mbe:expand-pattern (cdr p) r k))]
[(symbol? p)
(if (memq p k) p
(let ((x (assq p r)))
(if x (cdr x) p)))]
[else p]))]
[mbe:get-ellipsis-nestings
(lambda (p k)
(let sub ((p p))
(cond
[(mbe:ellipsis? p) (cons (sub (car p)) (sub (cddr p)))]
[(pair? p) (append (sub (car p)) (sub (cdr p)))]
[(symbol? p) (if (memq p k) '() (list p))]
[else '()])))]
[mbe:ellipsis-sub-envs
(lambda (nestings r)
(let ((sub-envs-list
(let loop ((r r) (sub-envs-list '()))
(if (null? r) (reverse! sub-envs-list)
(let ((c (car r)))
(loop (cdr r)
(if (mbe:contained-in? nestings (car c))
(cons (cdr c) sub-envs-list)
sub-envs-list)))))))
(case (length sub-envs-list)
((0) #f)
((1) (car sub-envs-list))
(else
(let loop ((sub-envs-list sub-envs-list) (final-sub-envs '()))
(if (ormap null? sub-envs-list) (reverse! final-sub-envs)
(loop (map cdr sub-envs-list)
(cons (mbe:append-map car sub-envs-list)
final-sub-envs))))))))]
[mbe:contained-in?
(lambda (v y)
(if (or (symbol? v) (symbol? y)) (eq? v y)
(ormap (lambda (v_i)
(ormap (lambda (y_j)
(mbe:contained-in? v_i y_j))
y))
v)))]
[mbe:split-at-ellipsis
(lambda (e p-tail)
(if (null? p-tail) (cons e '())
(let ((i (mbe:position (car p-tail) e)))
(if i (cons (comlist:butlast e (- (length e) i))
(list-tail e i))
(error 'mbe:split-at-ellipsis "bad argument in syntax-rules")))))]
[mbe:ellipsis?
(lambda (x)
(and (pair? x) (pair? (cdr x)) (eq? (cadr x) '...)))]
[comlist:butlast
(lambda (lst n)
(letrec ((l (- (length lst) n))
(bl (lambda (lst n)
(cond ((null? lst) lst)
((positive? n)
(cons (car lst) (bl (cdr lst) (+ -1 n))))
(else '())))))
(bl lst (if (negative? n)
(error 'butlast "negative argument in syntax-rules: ~s"
n)
l))))])
(set! -:sr:matches-pattern? mbe:matches-pattern?)
(set! -:sr:get-bindings mbe:get-bindings)
(set! -:sr:expand-pattern mbe:expand-pattern))
(define make-expander
(lambda (who macro-name syn-rules)
(if (or (not (pair? syn-rules))
(not (eq? (car syn-rules) 'syntax-rules)))
(error who "~s not an R5RS macro: ~s"
macro-name syn-rules)
(let ((keywords (cons macro-name (cadr syn-rules)))
(clauses (cddr syn-rules)))
`(lambda macro-arg
(let ((macro-arg (cons ',macro-name macro-arg))
(keywords ',keywords))
(cond ,@(map
(lambda (clause)
(let ([in-pattern (car clause)]
[out-pattern (cadr clause)])
`((-:sr:matches-pattern? ',in-pattern macro-arg
keywords)
(let ([tagged-out-pattern+alist
(-:sr:tag
',out-pattern
(append! (-:sr:flatten ',in-pattern)
keywords) '())])
(-:sr:untag
(-:sr:expand-pattern
(car tagged-out-pattern+alist)
(-:sr:get-bindings ',in-pattern macro-arg
keywords)
keywords)
(cdr tagged-out-pattern+alist)
'())))))
clauses)
(else (error ',macro-name "no matching clause: ~s"
',clauses)))))))))
(define define-syntax
(lambda (macro-name syn-rules)
(let ([expander (make-expander 'define-syntax macro-name syn-rules)])
`(define-macro ,macro-name ,expander)))))

8
collects/mzlib/thread.ss Normal file
View File

@ -0,0 +1,8 @@
(require-library "threadu.ss")
(begin-elaboration-time
(require-library "invoke.ss"))
(define-values/invoke-unit/sig mzlib:thread^
mzlib:thread@)

192
collects/mzlib/threadr.ss Normal file
View File

@ -0,0 +1,192 @@
(unit/sig mzlib:thread^
(import)
#|
t accepts a function, f, and creates a thread. It returns the thread and a
function, g. When g is applied it passes it's argument to f, and evaluates
the call of f in the time of the thread that was created. Calls to g do not
block.
|#
(define consumer-thread
(case-lambda
[(f) (consumer-thread f void)]
[(f init)
(unless (procedure? f) (raise-type-error 'consumer-thread "procedure" f))
(let ([sema (make-semaphore 0)]
[protect (make-semaphore 1)]
[front-state null]
[back-state null])
(values
(thread
(letrec ([loop
(lambda ()
(semaphore-wait sema)
(let ([local-state
(begin
(semaphore-wait protect)
(if (null? back-state)
(let ([new-front (reverse front-state)])
(set! back-state (cdr new-front))
(set! front-state null)
(semaphore-post protect)
(car new-front))
(begin0
(car back-state)
(set! back-state (cdr back-state))
(semaphore-post protect))))])
(apply f local-state))
(loop))])
(lambda ()
(init)
(loop))))
(lambda new-state
(let ([num (length new-state)])
(unless (procedure-arity-includes? f num)
(raise
(make-exn:application:arity
(format "<procedure-from-consumer-thread>: consumer procedure arity is ~e; provided ~s argument~a"
(arity f) num (if (= 1 num) "" "s"))
(current-continuation-marks)
num
(arity f)))))
(semaphore-wait protect)
(set! front-state (cons new-state front-state))
(semaphore-post protect)
(semaphore-post sema))))]))
(define (merge-input a b)
(or (input-port? a)
(raise-type-error 'merge-input "input-port" a))
(or (input-port? b)
(raise-type-error 'merge-input "input-port" b))
(let-values ([(rd wt) (make-pipe)])
(let* ([copy1-sema (make-semaphore 500)]
[copy2-sema (make-semaphore 500)]
[ready1-sema (make-semaphore)]
[ready2-sema (make-semaphore)]
[check-first? #t]
[close-sema (make-semaphore)]
[mk-copy (lambda (from to copy-sema ready-sema)
(lambda ()
(let loop ()
(semaphore-wait copy-sema)
(let ([c (read-char from)])
(unless (eof-object? c)
(semaphore-post ready-sema)
(write-char c to)
(loop))))
(semaphore-post close-sema)))])
(thread (mk-copy a wt copy1-sema ready1-sema))
(thread (mk-copy b wt copy2-sema ready2-sema))
(thread (lambda ()
(semaphore-wait close-sema)
(semaphore-wait close-sema)
(close-output-port wt)))
(make-input-port
(lambda () (let ([c (read-char rd)])
(unless (eof-object? c)
(if (and check-first? (semaphore-try-wait? ready1-sema))
(semaphore-post copy1-sema)
(if (not (semaphore-try-wait? ready2-sema))
; check-first? must be #f
(if (semaphore-try-wait? ready1-sema)
(semaphore-post copy1-sema)
(error 'join "internal error: char from nowhere!"))
(semaphore-post copy2-sema)))
(set! check-first? (not check-first?)))
c))
(lambda () (char-ready? rd))
(lambda () (close-input-port rd))))))
(define with-semaphore
(lambda (s f)
(semaphore-wait s)
(begin0 (f)
(semaphore-post s))))
(define semaphore-wait-multiple
(case-lambda
[(semaphores) (semaphore-wait-multiple semaphores #f #f)]
[(semaphores timeout) (semaphore-wait-multiple semaphores timeout #f)]
[(semaphores timeout allow-break?)
(let ([break-enabled? (or allow-break? (break-enabled))])
(parameterize ([break-enabled #f])
(for-each
(lambda (s)
(or (semaphore? s)
(raise-type-error 'semaphore-wait-multiple "list of semaphores" semaphores)))
semaphores)
(or (not timeout) (real? timeout) (>= timeout 0)
(raise-type-error 'semaphore-wait-multiple "positive real number" timeout))
(let* ([result-l null]
[ok? #f]
[set-l (make-semaphore 1)]
[one-done (make-semaphore)]
[threads (let loop ([l semaphores])
(if (null? l)
null
(cons (let ([s (car l)])
(thread (lambda ()
(let/ec
k
(current-exception-handler k)
(semaphore-wait/enable-break s)
(with-semaphore
set-l
(lambda () (set! result-l
(cons s result-l))))
(semaphore-post one-done)))))
(loop (cdr l)))))]
[timer-thread (if timeout
(thread (lambda () (sleep timeout) (semaphore-post one-done)))
#f)])
(dynamic-wind
void
(lambda ()
; wait until someone is done
((if break-enabled? semaphore-wait/enable-break semaphore-wait) one-done)
(set! ok? #t))
(lambda ()
; tell everyone to stop
(for-each (lambda (th) (break-thread th)) threads)
(when timer-thread (break-thread timer-thread))
; wait until everyone's done
(for-each thread-wait threads)
; If more that too manay suceeded, repost to the extras
(let ([extras (if ok?
(if (null? result-l)
null
(cdr result-l))
result-l)])
(for-each (lambda (s) (semaphore-post s)) extras))))
(if (null? result-l)
#f
(car result-l)))))]))
(define dynamic-enable-break
(polymorphic
(lambda (thunk)
(parameterize ([break-enabled #t])
(thunk)))))
(define dynamic-disable-break
(polymorphic
(lambda (thunk)
(parameterize ([break-enabled #f])
(thunk)))))
(define make-single-threader
(polymorphic
(lambda ()
(let ([sema (make-semaphore 1)])
(lambda (thunk)
(dynamic-wind
(lambda () (semaphore-wait sema))
thunk
(lambda () (semaphore-post sema))))))))
)

13
collects/mzlib/threads.ss Normal file
View File

@ -0,0 +1,13 @@
(begin-elaboration-time
(require-relative-library "spidey.ss"))
(define-signature mzlib:thread^
(consumer-thread
merge-input
with-semaphore
semaphore-wait-multiple
dynamic-disable-break
dynamic-enable-break
make-single-threader))

Some files were not shown because too many files have changed in this diff Show More