Merge remote branch 'origin/master' into samth/new-logic2

This commit is contained in:
Sam Tobin-Hochstadt 2010-04-23 18:36:46 -04:00
commit b173f70ad1
77 changed files with 3010 additions and 2773 deletions

5
.gitignore vendored
View File

@ -9,3 +9,8 @@
# a common convenient place to set the PLTADDON directory to
/add-on/
# common backups, autosaves, and lock files
*~
\#*
.#*

View File

@ -20,6 +20,7 @@
lang/posn
scheme/gui/base
"../../mrlib/image-core.ss"
(prefix-in cis: "../../mrlib/cache-image-snip.ss")
(for-syntax scheme/base
scheme/list))
@ -270,9 +271,26 @@
[else arg]))
(define (image-snip->image is)
(bitmap->image (send is get-bitmap)
(or (send is get-bitmap-mask)
(send (send is get-bitmap) get-loaded-mask))))
(let ([bm (send is get-bitmap)])
(cond
[(not bm)
;; this might mean we have a cache-image-snip%
;; or it might mean we have a useless snip.
(let-values ([(w h) (if (is-a? is cis:cache-image-snip%)
(send is get-size)
(values 0 0))])
(make-image (make-polygon
(list (make-point 0 0)
(make-point w 0)
(make-point w h)
(make-point 0 h))
'solid "black")
(make-bb w h h)
#f))]
[else
(bitmap->image bm
(or (send is get-bitmap-mask)
(send bm get-loaded-mask)))])))
(define (bitmap->image bm [mask-bm (send bm get-loaded-mask)])
(let ([w (send bm get-width)]

View File

@ -46,6 +46,7 @@
scheme/class
scheme/gui/base
schemeunit
(prefix-in 1: htdp/image)
(only-in lang/htdp-advanced equal~?))
(require (for-syntax scheme/base))
@ -202,6 +203,14 @@
(check-close (image-height (rotate 30 (ellipse 0 100 'solid 'blue)))
(ceiling (* (cos (* pi 1/6)) 100)))
;; zero-sized htdp/image images should also work
(test (image-width (1:text "" 18 "blue"))
=>
0)
(test (image-height (1:rectangle 10 0 'solid "red"))
=>
0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; polygon equality

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(provide get-general-acks
get-translating-acks

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(require scheme/class
scheme/math

View File

@ -1,4 +1,4 @@
(module default-code-style mzscheme
#lang racket/base
(provide color-default-code-styles
bw-default-code-styles
code-style-color
@ -24,4 +24,4 @@
(list 'unbound-variable (make-code-style "red" #f #f #f))
(list 'bound-variable (make-code-style "navy" #f #f #f))
(list 'primitive (make-code-style "navy" #f #f #f))
(list 'constant (make-code-style '(51 135 39) #f #f #f)))))
(list 'constant (make-code-style '(51 135 39) #f #f #f))))

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(require scheme/gui/base "private/key.ss")
(define debugging? (getenv "PLTDRDEBUG"))

View File

@ -1,4 +1,4 @@
(module installer mzscheme
#lang racket/base
(require mzlib/file
mzlib/etc
launcher)
@ -18,4 +18,4 @@
(mred-program-launcher-path "DrScheme")
(cons
`(exe-name . "DrScheme")
(build-aux-from-path (build-path (collection-path "drscheme") "drscheme")))))))
(build-aux-from-path (build-path (collection-path "drscheme") "drscheme"))))))

View File

@ -1,2 +1,2 @@
(module main scheme/base
(require "drscheme.ss"))
#lang racket/base
(require "drscheme.ss")

View File

@ -1,10 +1,8 @@
#lang scheme/unit
(require mzlib/class
mzlib/list
scheme/file
(require racket/class
string-constants
mred
racket/gui/base
framework
browser/external
setup/getinfo

View File

@ -1,4 +1,4 @@
#lang mzscheme
#lang racket/base
#|
CODE COPIED (with permission ...) from syntax-browser.ss
@ -9,13 +9,10 @@ Marshalling (and hence the 'read' method of the snipclass omitted for fast proto
|#
(require mzlib/pretty
mzlib/list
mzlib/class
mred
mzlib/match
mzlib/string
mzlib/contract)
(require racket/pretty
racket/class
racket/gui/base
racket/contract)
(provide render-bindings/snip)
@ -64,7 +61,7 @@ Marshalling (and hence the 'read' method of the snipclass omitted for fast proto
; how to enrich the notion of an output-port to get 'bold'ing to
; work otherwise...
(let* ([before (send output-text last-position)])
(pretty-print (syntax-object->datum stx))
(pretty-print (syntax->datum stx))
(let* ([post-newline (send output-text last-position)])
(send output-text delete post-newline) ; delete the trailing \n. yuck!
(send output-text insert " ")
@ -164,7 +161,7 @@ Marshalling (and hence the 'read' method of the snipclass omitted for fast proto
(define black-style-delta (make-object style-delta% 'change-normal-color))
(define green-style-delta (make-object style-delta%))
(send green-style-delta set-delta-foreground "forest green")
(void (send green-style-delta set-delta-foreground "forest green"))
(define turn-snip%
(class snip%

View File

@ -1,6 +1,6 @@
#lang scheme
#lang racket/base
(require mred/mred)
(require racket/gui/base racket/class)
(provide bitmap-message%)
(define bitmap-message%

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
#|
@ -10,11 +10,11 @@ profile todo:
(require errortrace/errortrace-key
scheme/unit
scheme/contract
racket/contract
errortrace/stacktrace
scheme/class
scheme/path
scheme/gui/base
racket/class
racket/path
racket/gui/base
string-constants
framework
framework/private/bday
@ -23,9 +23,9 @@ profile todo:
"bindings-browser.ss"
net/sendurl
net/url
scheme/match
racket/match
mrlib/include-bitmap
(for-syntax scheme/base))
(for-syntax racket/base))
(define orig (current-output-port))

View File

@ -1,12 +1,12 @@
#lang scheme/base
#lang racket/base
(require mred
scheme/class
scheme/cmdline
scheme/list
racket/class
racket/cmdline
racket/list
framework/private/bday
framework/splash
scheme/file
racket/file
"eb.ss")
(define files-to-open (command-line #:args filenames filenames))

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(require scheme/unit)
(provide drscheme:eval^

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require scheme/class
#lang racket/base
(require racket/class
framework/splash
scheme/gui/base)
racket/gui/base)
(provide install-eb)
(define (install-eb)

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require scheme/class
scheme/gui/base)
#lang racket/base
(require racket/class
racket/gui/base)
(provide get-enclosing-editor-frame)

View File

@ -1,9 +1,9 @@
#lang mzscheme
#lang racket/base
(require mred
mzlib/unit
mzlib/port
mzlib/class
scheme/unit
racket/port
racket/class
syntax/toplevel
framework
"drsig.ss")
@ -11,7 +11,7 @@
;; to ensure this guy is loaded (and the snipclass installed) in the drscheme namespace & eventspace
;; these things are for effect only!
(require mrlib/cache-image-snip
(prefix image-core: mrlib/image-core))
(prefix-in image-core: mrlib/image-core))
(define op (current-output-port))
(define (oprintf . args) (apply fprintf op args))
@ -173,7 +173,7 @@
(error-print-width 250)
(current-ps-setup (make-object ps-setup%))
(current-namespace (make-namespace 'empty))
(current-namespace (make-empty-namespace))
(for-each (λ (x) (namespace-attach-module drscheme:init:system-namespace x))
to-be-copied-module-names))

View File

@ -1,8 +1,8 @@
#lang mzscheme
(require mzlib/unit
mzlib/class
#lang racket/base
(require scheme/unit
racket/class
racket/gui/base
"drsig.ss"
mred
framework
string-constants)

View File

@ -1,9 +1,8 @@
#lang scheme/unit
(require string-constants
mzlib/match
mzlib/class
mzlib/string
mzlib/list
racket/match
racket/class
racket/string
"drsig.ss"
mred
framework
@ -11,7 +10,7 @@
net/head
setup/plt-installer
help/bug-report
scheme/file)
racket/file)
(import [prefix drscheme:unit: drscheme:unit^]
[prefix drscheme:app: drscheme:app^]

View File

@ -1,6 +1,6 @@
#lang scheme/unit
(require scheme/class
(require racket/class
"drsig.ss")
(import [prefix drscheme:unit: drscheme:unit^]

View File

@ -1,9 +1,9 @@
#lang scheme/unit
(require scheme/gui/base
(require racket/gui/base
browser/external
framework
scheme/class
racket/class
net/url
setup/dirs
help/search

View File

@ -1,8 +1,8 @@
#lang scheme/base
#lang racket/base
(provide draw-honu)
(require scheme/class
scheme/gui/base
(require racket/class
racket/gui/base
"palaka.ss")
(define pi (atan 0 -1))

View File

@ -1,8 +1,7 @@
#lang scheme/unit
(require string-constants
"drsig.ss"
mzlib/list
mred)
racket/gui/base)
(import)

View File

@ -2,7 +2,7 @@
(require typed/mred/mred
typed/framework/framework
scheme/class
racket/class
string-constants/string-constant)

View File

@ -1,4 +1,4 @@
#lang mzscheme
#lang racket/base
(provide break-threads)
(define super-cust (current-custodian))
(define first-child (make-custodian))

View File

@ -1,28 +1,28 @@
#lang mzscheme
(require mred
mzlib/class)
(provide (all-from-except mred frame%)
(rename registering-frame% frame%)
#lang racket/base
(require racket/gui/base
racket/class)
(provide (except-out (all-from-out racket/gui/base) frame%)
(rename-out [registering-frame% frame%])
lookup-frame-name)
(define (lookup-frame-name frame)
(semaphore-wait label-sema)
(begin0
(hash-table-get label-ht frame (λ () #f))
(hash-ref label-ht frame (λ () #f))
(semaphore-post label-sema)))
(define label-sema (make-semaphore 1))
(define label-ht (make-hash-table 'weak))
(define label-ht (make-weak-hasheq))
(define registering-frame%
(class frame%
(define/override (set-label x)
(semaphore-wait label-sema)
(hash-table-put! label-ht this x)
(hash-set! label-ht this x)
(semaphore-post label-sema)
(super set-label x))
(inherit get-label)
(super-instantiate ())
(semaphore-wait label-sema)
(hash-table-put! label-ht this (get-label))
(hash-set! label-ht this (get-label))
(semaphore-post label-sema)))

View File

@ -1,13 +1,13 @@
#lang scheme/base
#lang racket/base
(require scheme/unit
mrlib/hierlist
scheme/class
scheme/contract
scheme/string
scheme/list
racket/class
racket/contract
racket/string
racket/list
racket/gui/base
"drsig.ss"
string-constants
mred
framework
setup/getinfo
syntax/toplevel
@ -1252,7 +1252,12 @@
(message-box
(string-constant drscheme)
(format
"The drscheme-language-position, drscheme-language-modules, drscheme-language-numbers, and drscheme-language-readers specifications aren't correct. Expected (listof (cons string (listof string))), (listof (listof string)), (listof (listof number)), (listof string), (listof string), and (listof module-spec) respectively, where the lengths of the outer lists are the same. Got ~e, ~e, ~e, ~e, ~e, and ~e"
(string-append
"The drscheme-language-position, drscheme-language-modules, drscheme-language-numbers,"
" and drscheme-language-readers specifications aren't correct. Expected"
" (listof (cons string (listof string))), (listof (listof string)), (listof (listof number)), (listof string),"
" (listof string), and (listof module-spec) respectively, where the lengths of the outer lists are the same."
" Got ~e, ~e, ~e, ~e, ~e, and ~e")
lang-positions
lang-modules
numberss
@ -1431,7 +1436,7 @@
(let ([words #f])
(λ ()
(unless words
(set! words (text:get-completions/manuals '(scheme/base scheme/contract))))
(set! words (text:get-completions/manuals '(racket/base racket/contract))))
words)))
(define get-all-manual-keywords

View File

@ -1,14 +1,14 @@
#reader scribble/reader
#lang scheme/base
(require (for-syntax scheme/base)
#lang racket/base
(require (for-syntax racket/base)
scribble/srcdoc
scheme/class
scheme/gui/base
scheme/contract
racket/class
racket/gui/base
racket/contract
"recon.ss")
(require/doc scheme/base scribble/manual)
(require/doc racket/base scribble/manual)
(require (for-meta 2 scheme/base))
(require (for-meta 2 racket/base))
(provide language-object-abstraction)

View File

@ -9,17 +9,17 @@
;; NOTE: this module instantiates stacktrace itself, so we have
;; to be careful to not mix that instantiation with the one
;; drscheme/private/debug.ss does. errortrace-lib's is for the
;; drracket/private/debug.ss does. errortrace-lib's is for the
;; compilation handling, DrScheme's is for profiling and test coverage
;; (which do not do compilation)
(prefix-in el: errortrace/errortrace-lib)
mzlib/pconvert
scheme/pretty
racket/pretty
mzlib/struct
scheme/class
scheme/file
scheme/list
racket/class
racket/file
racket/list
compiler/embed
launcher
mred

View File

@ -1,8 +1,8 @@
#lang scheme/base
#lang racket/base
(provide startup)
(require scheme/file)
(require racket/file)
(define (read-from-string s) (read (open-input-string s)))

View File

@ -1,9 +1,9 @@
#lang scheme/base
#lang racket/base
(require scheme/gui/base "launcher-bootstrap.ss")
(require racket/gui/base "launcher-bootstrap.ss")
(current-namespace (make-gui-empty-namespace))
(namespace-require 'scheme/gui/base)
(namespace-require 'scheme/class)
(namespace-require 'racket/gui/base)
(namespace-require 'racket/class)
(startup)

View File

@ -1,8 +1,8 @@
#lang scheme/base
#lang racket/base
(require "launcher-bootstrap.ss")
(current-namespace (make-base-empty-namespace))
(namespace-require 'scheme/base)
(namespace-require 'racket/base)
(startup)

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(require scheme/unit
"modes.ss"
"font.ss"

View File

@ -7,7 +7,7 @@
framework
mzlib/class
mzlib/list
scheme/path
racket/path
browser/external
setup/plt-installer)

View File

@ -1,7 +1,7 @@
#lang scheme/unit
(require string-constants
mzlib/class
mzlib/list
racket/class
racket/list
framework
"drsig.ss")
@ -23,7 +23,7 @@
(define (not-a-language-language? l)
(and (not (null? l))
(equal? (car (last-pair l))
(equal? (last l)
(string-constant no-language-chosen))))
(define (add-initial-modes)

View File

@ -1,7 +1,7 @@
#lang scheme/base
#lang racket/base
(require mred
scheme/class
racket/class
syntax/moddep
syntax/toplevel
framework/framework
@ -9,7 +9,7 @@
mrlib/graph
"drsig.ss"
scheme/unit
scheme/async-channel
racket/async-channel
setup/private/lib-roots)
(define-struct req (filename key))

View File

@ -1,12 +1,12 @@
#lang scheme/base
#lang racket/base
(provide module-language-tools@)
(require mrlib/switchable-button
mrlib/bitmap-label
scheme/contract
racket/contract
framework
scheme/unit
scheme/class
scheme/gui/base
racket/class
racket/gui/base
"drsig.ss")
(define op (current-output-port))

View File

@ -1,11 +1,11 @@
#lang scheme/base
#lang racket/base
(provide module-language@)
(require scheme/unit
scheme/class
scheme/list
scheme/path
scheme/contract
racket/class
racket/list
racket/path
racket/contract
mred
compiler/embed
compiler/cm
@ -382,7 +382,7 @@
#:literal-expression
(begin
(parameterize ([current-namespace (make-base-empty-namespace)])
(namespace-require 'scheme/base)
(namespace-require 'racket/base)
(compile
`(namespace-require '',(string->symbol (path->string short-program-name))))))
#:cmdline '("-U" "--")))))
@ -672,7 +672,7 @@
(raise-hopeless-syntax-error "bad syntax in name position of module"
stx name))
(when filename (check-filename-matches filename name* stx))
(let* (;; rewrite the module to use the scheme/base version of `module'
(let* (;; rewrite the module to use the racket/base version of `module'
[mod (datum->syntax #'here 'module mod)]
[expr (datum->syntax stx `(,mod ,name ,lang . ,body) stx stx)])
(values name lang expr)))

View File

@ -2,8 +2,8 @@
(require framework
mzlib/class
mred
scheme/file
scheme/path
racket/file
racket/path
mzlib/thread
mzlib/async-channel
string-constants

View File

@ -1,6 +1,6 @@
#lang mzscheme
#lang racket/base
(require mred
mzlib/class
racket/class
framework)
(provide snip-class)

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require scheme/class scheme/gui/base)
#lang racket/base
(require racket/class racket/gui/base)
(provide draw-palaka palaka-pattern-size)
(define scale 1)

View File

@ -1,6 +1,6 @@
#lang scheme/base
#lang racket/base
(require (for-syntax scheme/base)
(require (for-syntax racket/base)
framework/framework)
(provide (rename-out [-preferences:get preferences:get])

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require scheme/gui/base
scheme/class
#lang racket/base
(require racket/gui/base
racket/class
profile/sampler
profile/render-text
profile/analyzer

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require (for-syntax scheme/base))
#lang racket/base
(require (for-syntax racket/base))
(provide reconstitute)
(begin-for-syntax

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
#|
@ -20,15 +20,15 @@ TODO
;; user's io ports, to aid any debugging printouts.
;; (esp. useful when debugging the users's io)
(require scheme/class
scheme/path
scheme/pretty
(require racket/class
racket/path
racket/pretty
scheme/unit
scheme/list
racket/list
string-constants
setup/xref
scheme/gui/base
racket/gui/base
framework
browser/external
"drsig.ss"

View File

@ -1,7 +1,7 @@
#lang mzscheme
(require mzlib/class
mzlib/pretty
mred)
#lang racket/base
(require racket/class
racket/pretty
racket/gui/base)
(define head-size 40)
(define small-bitmap-factor 1/2)

View File

@ -1,9 +1,9 @@
#lang scheme/unit
(require scheme/class
scheme/list
scheme/runtime-path
scheme/contract
(require racket/class
racket/list
racket/runtime-path
racket/contract
setup/getinfo
mred
framework
@ -13,7 +13,7 @@
mrlib/switchable-button
string-constants)
(require (for-syntax scheme/base scheme/match))
(require (for-syntax racket/base racket/match))
(import [prefix drscheme:frame: drscheme:frame^]
[prefix drscheme:unit: drscheme:unit^]

View File

@ -1,12 +1,12 @@
#lang scheme/base
#lang racket/base
(require scheme/contract
(require racket/contract
scheme/unit
scheme/class
scheme/path
scheme/port
scheme/list
scheme/gui/base
racket/class
racket/path
racket/port
racket/list
racket/gui/base
string-constants
framework
(prefix-in tr: trace/stacktrace)

View File

@ -1,5 +1,4 @@
#reader scribble/reader
#lang scheme/base
#lang at-exp racket/base
(require scribble/decode
scribble/manual)

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
#|
closing:
@ -11,12 +11,12 @@ module browser threading seems wrong.
|#
(require scheme/contract
(require racket/contract
scheme/unit
scheme/class
scheme/path
scheme/port
scheme/list
racket/class
racket/path
racket/port
racket/list
string-constants
framework
mrlib/name-message

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(require scheme/gui/base
framework
scheme/class)

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
(require scheme/class
scheme/gui/base
string-constants/string-constant)

View File

@ -1,4 +1,4 @@
#lang scheme/base
#lang racket/base
#|
Check Syntax separates two classes of identifiers,
@ -2276,16 +2276,28 @@ If the namespace does not, they are colored the unbound color.
(parameterize ([current-namespace user-namespace]
[current-directory user-directory]
[current-load-relative-directory user-directory])
(let ([ans (with-handlers ([exn:fail? (λ (x) #f)])
(cond
[(module-path-index? datum)
(resolved-module-path-name
(module-path-index-resolve datum))]
[else
(resolved-module-path-name
((current-module-name-resolver) datum #f #f))]))])
(and (path? ans)
ans))))
(let* ([rkt-path/mod-path
(with-handlers ([exn:fail? (λ (x) #f)])
(cond
[(module-path-index? datum)
(resolved-module-path-name
(module-path-index-resolve datum))]
[else
(resolved-module-path-name
((current-module-name-resolver) datum #f #f))]))]
[rkt-path/f (and (path? rkt-path/mod-path) rkt-path/mod-path)])
(let/ec k
(unless (path? rkt-path/f) (k rkt-path/f))
(when (file-exists? rkt-path/f) (k rkt-path/f))
(let* ([bts (path->bytes rkt-path/f)]
[len (bytes-length bts)])
(unless (and (len . >= . 4)
(bytes=? #".rkt" (subbytes bts (- len 4))))
(k rkt-path/f))
(let ([ss-path (bytes->path (bytes-append (subbytes bts 0 (- len 4)) #".ss"))])
(unless (file-exists? ss-path)
(k rkt-path/f))
ss-path))))))
;; make-require-open-menu : path -> menu -> void
(define (make-require-open-menu file)

View File

@ -1,4 +1,4 @@
#lang at-exp scheme/base
#lang at-exp racket/base
#|

View File

@ -1,4 +1,5 @@
(module tool mzscheme
(require "private/drsig.ss")
(provide drscheme:tool^
drscheme:tool-exports^))
#lang racket/base
(require "private/drsig.ss")
(provide drscheme:tool^
drscheme:tool-exports^)

3
collects/meta/props Executable file → Normal file
View File

@ -812,6 +812,7 @@ path/s is either such a string or a list of them.
"collects/handin-server/web-status-server.ss" drdr:command-line "mzc ~s"
"collects/help" responsible (robby)
"collects/help/bug-report.ss" drdr:command-line "mred-text -t ~s"
"collects/help/help.ss" drdr:command-line "mzc ~s"
"collects/hierlist/hierlist.ss" drdr:command-line "mred-text -t ~s"
"collects/honu" responsible (mflatt rafkind)
"collects/htdp" responsible (matthias)
@ -897,8 +898,8 @@ path/s is either such a string or a list of them.
"collects/make" responsible (mflatt)
"collects/meta" responsible (eli)
"collects/meta/check-dists.ss" drdr:command-line ""
"collects/meta/drdr" responsible (jay) drdr:command-line ""
"collects/meta/contrib/completion/racket-completion.bash" responsible (samth sstrickl) drdr:command-line ""
"collects/meta/drdr" responsible (jay) drdr:command-line ""
"collects/mred/edit-main.ss" drdr:command-line "mzc ~s"
"collects/mred/edit.ss" drdr:command-line "mred-text -t ~s"
"collects/mred/lang/main.ss" drdr:command-line "mred-text -t ~s"

View File

@ -1,6 +0,0 @@
#lang racket
(require racket/init
scheme/gui/base)
(provide (all-from-out racket/init
scheme/gui/base))

View File

@ -22,6 +22,7 @@
for/last for*/last
for/hash for*/hash
for/hasheq for*/hasheq
for/hasheqv for*/hasheqv
for/fold/derived for*/fold/derived
@ -952,6 +953,14 @@
#`(let-values ([(key val) #,x])
(hash-set table key val))))
(define-for-variants (for/hasheqv for*/hasheqv)
([table #hasheqv()])
(lambda (x) x)
(lambda (rhs) rhs)
(lambda (x)
#`(let-values ([(key val) #,x])
(hash-set table key val))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; specific sequences

View File

@ -7,7 +7,9 @@
set-member? set-add set-remove
set-union set-intersect set-subtract
set-map set-for-each
(rename-out [*in-set in-set]))
(rename-out [*in-set in-set])
for/set for/seteq for/seteqv
for*/set for*/seteq for*/seteqv)
(define-struct set (ht)
#:omit-define-syntaxes
@ -206,3 +208,17 @@
#t
;; loop args
((hash-iterate-next ht pos)))]])))
(define-syntax-rule (define-for for/fold/derived for/set set)
(define-syntax (for/set stx)
(syntax-case stx ()
[(_ bindings . body)
(quasisyntax/loc stx
(for/fold/derived #,stx ([s (set)]) bindings (set-add s (let () . body))))])))
(define-for for/fold/derived for/set set)
(define-for for*/fold/derived for*/set set)
(define-for for/fold/derived for/seteq seteq)
(define-for for*/fold/derived for*/seteq seteq)
(define-for for/fold/derived for/seteqv seteqv)
(define-for for*/fold/derived for*/seteqv seteqv)

View File

@ -1,3 +1,5 @@
#lang scheme/private
(provide (except-out (all-from-out racket/base) struct))
(provide (except-out (all-from-out racket/base)
struct
hash hasheq hasheqv))

1050
collects/scribble/racket.ss Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,985 +1,3 @@
(module scheme scheme/base
(require "core.ss"
"basic.ss"
"search.ss"
"private/manual-sprop.ss"
"private/on-demand.ss"
mzlib/class
mzlib/for
syntax/modresolve
syntax/modcode
(for-syntax scheme/base))
(provide define-code
to-element
to-element/no-color
to-paragraph
to-paragraph/prefix
syntax-ize
syntax-ize-hook
current-keyword-list
current-variable-list
current-meta-list
input-color
output-color
input-background-color
no-color
reader-color
result-color
keyword-color
comment-color
paren-color
meta-color
value-color
symbol-color
variable-color
opt-color
error-color
syntax-link-color
value-link-color
module-color
module-link-color
block-color
highlighted-color
(struct-out var-id)
(struct-out shaped-parens)
(struct-out just-context)
(struct-out alternate-display)
(struct-out literal-syntax)
(for-syntax make-variable-id
variable-id?
make-element-id-transformer
element-id-transformer?))
(define (make-scheme-style s #:tt? [tt? #t])
(make-style s (if tt?
(cons 'tt-chars scheme-properties)
scheme-properties)))
(define-on-demand output-color (make-scheme-style "ScmOut"))
(define-on-demand input-color (make-scheme-style "ScmIn"))
(define-on-demand input-background-color (make-scheme-style "ScmInBG"))
(define-on-demand no-color (make-scheme-style "ScmPlain"))
(define-on-demand reader-color (make-scheme-style "ScmRdr"))
(define-on-demand result-color (make-scheme-style "ScmRes"))
(define-on-demand keyword-color (make-scheme-style "ScmKw"))
(define-on-demand comment-color (make-scheme-style "ScmCmt"))
(define-on-demand paren-color (make-scheme-style "ScmPn"))
(define-on-demand meta-color (make-scheme-style "ScmMeta"))
(define-on-demand value-color (make-scheme-style "ScmVal"))
(define-on-demand symbol-color (make-scheme-style "ScmSym"))
(define-on-demand variable-color (make-scheme-style "ScmVar"))
(define-on-demand opt-color (make-scheme-style "ScmOpt"))
(define-on-demand error-color (make-scheme-style "ScmErr" #:tt? #f))
(define-on-demand syntax-link-color (make-scheme-style "ScmStxLink"))
(define-on-demand value-link-color (make-scheme-style "ScmValLink"))
(define-on-demand module-color (make-scheme-style "ScmMod"))
(define-on-demand module-link-color (make-scheme-style "ScmModLink"))
(define-on-demand block-color (make-scheme-style "ScmBlk"))
(define-on-demand highlighted-color (make-scheme-style "highlighted" #:tt? #f))
(define current-keyword-list
(make-parameter null))
(define current-variable-list
(make-parameter null))
(define current-meta-list
(make-parameter null))
(define defined-names (make-hasheq))
(define-struct (sized-element element) (length))
(define-struct (spaces element) (cnt))
(define (literalize-spaces i)
(let ([m (regexp-match-positions #rx" +" i)])
(if m
(let ([cnt (- (cdar m) (caar m))])
(make-spaces #f
(list
(literalize-spaces (substring i 0 (caar m)))
(hspace cnt)
(literalize-spaces (substring i (cdar m))))
cnt))
i)))
(define line-breakable-space (make-element 'tt " "))
;; These caches intentionally record a key with the value.
;; That way, when the value is no longer used, the key
;; goes away, and the entry is gone.
(define id-element-cache (make-weak-hash))
(define element-cache (make-weak-hash))
(define-struct (cached-delayed-element delayed-element) (cache-key))
(define-struct (cached-element element) (cache-key))
(define (make-id-element c s)
(let* ([key (and id-element-cache
(let ([b (identifier-label-binding c)])
(vector (syntax-e c)
(module-path-index->taglet (caddr b))
(cadddr b)
(list-ref b 5))))])
(or (and key
(let ([b (hash-ref id-element-cache key #f)])
(and b
(weak-box-value b))))
(let ([e (make-cached-delayed-element
(lambda (renderer sec ri)
(let* ([tag (find-scheme-tag sec ri c #f)])
(if tag
(list
(case (car tag)
[(form)
(make-link-element syntax-link-color (list s) tag)]
[else
(make-link-element value-link-color (list s) tag)]))
(list
(make-element "badlink"
(make-element value-link-color s))))))
(lambda () s)
(lambda () s)
key)])
(when key
(hash-set! id-element-cache key (make-weak-box e)))
e))))
(define (make-element/cache style content)
(if (and element-cache
(string? content))
(let ([key (vector style content)])
(let ([b (hash-ref element-cache key #f)])
(or (and b (weak-box-value b))
(let ([e (make-cached-element style content key)])
(hash-set! element-cache key (make-weak-box e))
e))))
(make-element style content)))
(define (to-quoted qs qq? quote-depth out color? inc!)
(if (and qq? (zero? quote-depth))
(begin
(out qs (and color? value-color))
(inc!)
(add1 quote-depth))
quote-depth))
(define (to-unquoted qq? quote-depth out color? inc!)
(if (or (not qq?) (zero? quote-depth))
quote-depth
(begin
(out "," (and color? meta-color))
(inc!)
(to-unquoted qq? (sub1 quote-depth) out color? inc!))))
(define (typeset-atom c out color? quote-depth qq?)
(if (and (var-id? (syntax-e c))
(zero? quote-depth))
(out (format "~s" (let ([v (var-id-sym (syntax-e c))])
(if (syntax? v)
(syntax-e v)
v)))
variable-color)
(let*-values ([(is-var?) (and (identifier? c)
(memq (syntax-e c) (current-variable-list)))]
[(s it? sub?)
(let ([sc (syntax-e c)])
(let ([s (or (syntax-property c 'display-string)
(format "~s" (if (literal-syntax? sc)
(literal-syntax-stx sc)
(if (var-id? sc)
(var-id-sym sc)
sc))))])
(if (and (symbol? sc)
((string-length s) . > . 1)
(char=? (string-ref s 0) #\_)
(not (or (identifier-label-binding c)
is-var?)))
(values (substring s 1) #t #f)
(values s #f #f))))])
(let ([quote-depth (if (and qq? (identifier? c))
(let ([quote-depth
(if (and (quote-depth . < . 2)
(memq (syntax-e c) '(unquote unquote-splicing)))
(to-unquoted qq? quote-depth out color? void)
quote-depth)])
(to-quoted "'" qq? quote-depth out color? void))
quote-depth)])
(if (or (element? (syntax-e c))
(delayed-element? (syntax-e c))
(part-relative-element? (syntax-e c)))
(out (syntax-e c) #f)
(out (if (and (identifier? c)
color?
(quote-depth . <= . 0)
(not (or it? is-var?)))
(if (pair? (identifier-label-binding c))
(make-id-element c s)
s)
(literalize-spaces s))
(cond
[(positive? quote-depth) value-color]
[(let ([v (syntax-e c)])
(or (number? v)
(string? v)
(bytes? v)
(char? v)
(regexp? v)
(byte-regexp? v)
(boolean? v)))
value-color]
[(identifier? c)
(cond
[is-var?
variable-color]
[(and (identifier? c)
(memq (syntax-e c) (current-keyword-list)))
keyword-color]
[(and (identifier? c)
(memq (syntax-e c) (current-meta-list)))
meta-color]
[it? variable-color]
[else symbol-color])]
[else paren-color])
(string-length s)))))))
(define omitable (make-style #f '(omitable)))
(define (gen-typeset c multi-line? prefix1 prefix suffix color? qq?)
(let* ([c (syntax-ize c 0 #:qq? qq?)]
[content null]
[docs null]
[first (syntax-case c (code:line)
[(code:line e . rest) #'e]
[else c])]
[init-col (or (syntax-column first) 0)]
[src-col init-col]
[inc-src-col (lambda () (set! src-col (add1 src-col)))]
[dest-col 0]
[highlight? #f]
[col-map (make-hash)]
[next-col-map (make-hash)]
[line (or (syntax-line first) 0)])
(define (finish-line!)
(when multi-line?
(set! docs (cons (make-paragraph omitable (reverse content))
docs))
(set! content null)))
(define out
(case-lambda
[(v cls)
(out v cls (let sz-loop ([v v])
(cond
[(string? v) (string-length v)]
[(list? v) (for/fold ([s 0]) ([v (in-list v)]) (+ s (sz-loop v)))]
[(sized-element? v) (sized-element-length v)]
[(element? v)
(sz-loop (element-content v))]
[(delayed-element? v)
(content-width v)]
[(part-relative-element? v)
(content-width v)]
[(spaces? v)
(+ (sz-loop (car (element-content v)))
(spaces-cnt v)
(sz-loop (caddr (element-content v))))]
[else 1])))]
[(v cls len)
(unless (equal? v "")
(cond
[(spaces? v)
(out (car (element-content v)) cls 0)
(out (cadr (element-content v)) #f 0)
(out (caddr (element-content v)) cls len)]
[(equal? v "\n")
(if multi-line?
(begin
(finish-line!)
(out prefix cls))
(out " " cls))]
[else
(set! content (cons ((if highlight?
(lambda (c)
(make-element highlighted-color c))
values)
(if (and color? cls)
(make-element/cache cls v)
v))
content))
(set! dest-col (+ dest-col len))]))]))
(define advance
(case-lambda
[(c init-line! delta)
(let ([c (+ delta (or (syntax-column c) 0))]
[l (syntax-line c)])
(let ([new-line? (and l (l . > . line))])
(when new-line?
(for ([i (in-range (- l line))])
(out "\n" no-color))
(set! line l)
(set! col-map next-col-map)
(set! next-col-map (make-hash))
(init-line!))
(let ([d-col (let ([def-val (+ dest-col (- c src-col))])
(if new-line?
(hash-ref col-map c def-val)
def-val))])
(let ([amt (- d-col dest-col)])
(when (positive? amt)
(let ([old-dest-col dest-col])
(out (if (and (= 1 amt) (not multi-line?))
line-breakable-space ; allows a line break to replace the space
(hspace amt))
#f)
(set! dest-col (+ old-dest-col amt))))))
(set! src-col c)
(hash-set! next-col-map src-col dest-col)))]
[(c init-line!) (advance c init-line! 0)]))
(define (convert-infix c quote-depth qq?)
(let ([l (syntax->list c)])
(and l
((length l) . >= . 3)
((or (syntax-position (car l)) -inf.0)
. > .
(or (syntax-position (cadr l)) +inf.0))
(let ([a (car l)])
(let loop ([l (cdr l)]
[prev null])
(cond
[(null? l) #f] ; couldn't unwind
[else (let ([p2 (syntax-position (car l))])
(if (and p2
(p2 . > . (syntax-position a)))
(datum->syntax c
(append
(reverse prev)
(list
(datum->syntax
a
(let ([val? (positive? quote-depth)])
(make-sized-element
(if val? value-color #f)
(list
(make-element/cache (if val? value-color paren-color) '". ")
(typeset a #f "" "" "" (not val?) qq?)
(make-element/cache (if val? value-color paren-color) '" ."))
(+ (syntax-span a) 4)))
(list (syntax-source a)
(syntax-line a)
(- (syntax-column a) 2)
(- (syntax-position a) 2)
(+ (syntax-span a) 4))
a))
l)
c
c)
(loop (cdr l)
(cons (car l) prev))))]))))))
(define (no-fancy-chars s)
(cond
[(eq? s 'rsquo) "'"]
[else s]))
(define (loop init-line! quote-depth qq?)
(lambda (c)
(cond
[(eq? 'code:blank (syntax-e c))
(advance c init-line!)]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:comment))
(let ([l (syntax->list c)])
(unless (and l (= 2 (length l)))
(raise-syntax-error
#f
"does not have a single sub-form"
c)))
(advance c init-line!)
(out ";" comment-color)
(out 'nbsp comment-color)
(let ([v (syntax->datum (cadr (syntax->list c)))])
(if (paragraph? v)
(map (lambda (v)
(let ([v (no-fancy-chars v)])
(if (or (string? v) (symbol? v))
(out v comment-color)
(out v #f))))
(paragraph-content v))
(out (no-fancy-chars v) comment-color)))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:contract))
(advance c init-line!)
(out "; " comment-color)
(let* ([l (cdr (syntax->list c))]
[s-col (or (syntax-column (car l)) src-col)])
(set! src-col s-col)
(for-each (loop (lambda ()
(set! src-col s-col)
(set! dest-col 0)
(out "; " comment-color))
0
qq?)
l))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:line))
(let ([l (cdr (syntax->list c))])
(for-each (loop init-line! quote-depth qq?)
l))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:hilite))
(let ([l (syntax->list c)]
[h? highlight?])
(unless (and l (= 2 (length l)))
(error "bad code:redex: ~e" (syntax->datum c)))
(advance c init-line!)
(set! src-col (syntax-column (cadr l)))
(hash-set! next-col-map src-col dest-col)
(set! highlight? #t)
((loop init-line! quote-depth qq?) (cadr l))
(set! highlight? h?)
(set! src-col (add1 src-col)))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:quote))
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(out "(" (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 1))
(hash-set! next-col-map src-col dest-col)
((loop init-line! quote-depth qq?)
(datum->syntax #'here 'quote (car (syntax-e c))))
(for-each (loop init-line! (add1 quote-depth) qq?)
(cdr (syntax->list c)))
(out ")" (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 1))
#;
(hash-set! next-col-map src-col dest-col))]
[(and (pair? (syntax-e c))
(memq (syntax-e (car (syntax-e c)))
'(quote quasiquote unquote unquote-splicing
quasisyntax syntax unsyntax unsyntax-splicing))
(let ([v (syntax->list c)])
(and v (= 2 (length v))))
(or (not qq?)
(quote-depth . > . 1)
(not (memq (syntax-e (car (syntax-e c)))
'(unquote unquote-splicing)))))
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(let-values ([(str quote-delta)
(case (syntax-e (car (syntax-e c)))
[(quote) (values "'" +inf.0)]
[(unquote) (values "," -1)]
[(unquote-splicing) (values ",@" -1)]
[(quasiquote) (values "`" +1)]
[(syntax) (values "#'" 0)]
[(quasisyntax) (values "#`" 0)]
[(unsyntax) (values "#," 0)]
[(unsyntax-splicing) (values "#,@" 0)])])
(out str (if (positive? (+ quote-depth quote-delta))
value-color
reader-color))
(let ([i (cadr (syntax->list c))])
(set! src-col (or (syntax-column i) src-col))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (+ quote-depth quote-delta) qq?) i))))]
[(and (pair? (syntax-e c))
(convert-infix c quote-depth qq?))
=> (lambda (converted)
((loop init-line! quote-depth qq?) converted))]
[(or (pair? (syntax-e c))
(null? (syntax-e c))
(vector? (syntax-e c))
(and (struct? (syntax-e c))
(prefab-struct-key (syntax-e c)))
(struct-proxy? (syntax-e c)))
(let* ([sh (or (syntax-property c 'paren-shape)
#\()]
[quote-depth (if (and (not qq?)
(zero? quote-depth)
(or (vector? (syntax-e c))
(struct? (syntax-e c))))
+inf.0
quote-depth)]
[p-color (if (positive? quote-depth)
value-color
(if (eq? sh #\?)
opt-color
paren-color))])
(advance c init-line!)
(let ([quote-depth (if (struct-proxy? (syntax-e c))
(to-unquoted qq? quote-depth out color? inc-src-col)
(to-quoted "`" qq? quote-depth out color? inc-src-col))])
(when (vector? (syntax-e c))
(let ([vec (syntax-e c)])
(out "#" #;(format "#~a" (vector-length vec)) p-color)
(if (zero? (vector-length vec))
(set! src-col (+ src-col (- (syntax-span c) 2)))
(set! src-col (+ src-col (- (syntax-column (vector-ref vec 0))
(syntax-column c)
1))))))
(when (struct? (syntax-e c))
(out "#s" p-color)
(set! src-col (+ src-col 2)))
(out (case sh
[(#\[ #\?) "["]
[(#\{) "{"]
[else "("])
p-color)
(set! src-col (+ src-col 1))
(hash-set! next-col-map src-col dest-col)
(let lloop ([l (cond
[(vector? (syntax-e c))
(vector->short-list (syntax-e c) syntax-e)]
[(struct? (syntax-e c))
(let ([l (vector->list (struct->vector (syntax-e c)))])
;; Need to build key datum, syntax-ize it internally, and
;; set the overall width to fit right:
(cons (let ([key (syntax-ize (prefab-struct-key (syntax-e c))
(+ 3 (or (syntax-column c) 0))
(or (syntax-line c) 1))]
[end (if (pair? (cdr l))
(and (equal? (syntax-line c) (syntax-line (cadr l)))
(syntax-column (cadr l)))
(and (syntax-column c)
(+ (syntax-column c) (syntax-span c))))])
(if end
(datum->syntax #f
(syntax-e key)
(vector #f (syntax-line key)
(syntax-column key)
(syntax-position key)
(- end 1 (syntax-column key))))
end))
(cdr l)))]
[(struct-proxy? (syntax-e c))
(cons
(struct-proxy-name (syntax-e c))
(struct-proxy-content (syntax-e c)))]
[else c])]
[first-qq? (and qq? (not (struct-proxy? (syntax-e c))))])
(cond
[(and (syntax? l)
(pair? (syntax-e l))
(not (and (memq (syntax-e (car (syntax-e l)))
'(quote unquote syntax unsyntax quasiquote quasiunsyntax))
(let ([v (syntax->list l)])
(and v (= 2 (length v))))
(or (not qq?)
(quote-depth . > . 1)
(not (memq (syntax-e (car (syntax-e l)))
'(unquote unquote-splicing)))))))
(lloop (syntax-e l) first-qq?)]
[(or (null? l)
(and (syntax? l)
(null? (syntax-e l))))
(void)]
[(pair? l)
((loop init-line! quote-depth first-qq?) (car l))
(lloop (cdr l) qq?)]
[else
(advance l init-line! -2)
(out ". " (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 3))
(hash-set! next-col-map src-col dest-col)
((loop init-line! quote-depth first-qq?) l)]))
(out (case sh
[(#\[ #\?) "]"]
[(#\{) "}"]
[else ")"])
p-color)
(set! src-col (+ src-col 1))
#;
(hash-set! next-col-map src-col dest-col)))]
[(box? (syntax-e c))
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(out "#&" value-color)
(set! src-col (+ src-col 2))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (if qq? quote-depth +inf.0) qq?) (unbox (syntax-e c))))]
[(hash? (syntax-e c))
(advance c init-line!)
(let ([equal-table? (not (hash-eq? (syntax-e c)))]
[quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(out (if equal-table?
"#hash"
"#hasheq")
value-color)
(let ([delta (+ 5 (if equal-table? 2 0))]
[orig-col src-col])
(set! src-col (+ src-col delta))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (if qq? quote-depth +inf.0) qq?)
(syntax-ize (hash-map (syntax-e c) cons)
(+ (syntax-column c) delta)))
(set! src-col (+ orig-col (syntax-span c)))))]
[(graph-reference? (syntax-e c))
(advance c init-line!)
(out (format "#~a#" (unbox (graph-reference-bx (syntax-e c))))
(if (positive? quote-depth)
value-color
paren-color))
(set! src-col (+ src-col (syntax-span c)))]
[(graph-defn? (syntax-e c))
(advance c init-line!)
(let ([bx (graph-defn-bx (syntax-e c))])
(out (format "#~a=" (unbox bx))
(if (positive? quote-depth)
value-color
paren-color))
(set! src-col (+ src-col 3))
((loop init-line! quote-depth qq?) (graph-defn-r (syntax-e c))))]
[else
(advance c init-line!)
(typeset-atom c out color? quote-depth qq?)
(set! src-col (+ src-col (or (syntax-span c) 1)))
#;
(hash-set! next-col-map src-col dest-col)])))
(out prefix1 #f)
(set! dest-col 0)
(hash-set! next-col-map init-col dest-col)
((loop (lambda () (set! src-col init-col) (set! dest-col 0)) 0 qq?) c)
(if (list? suffix)
(map (lambda (sfx)
(finish-line!)
(out sfx #f))
suffix)
(out suffix #f))
(unless (null? content)
(finish-line!))
(if multi-line?
(if (= 1 (length docs))
(car docs)
(make-table block-color (map list (reverse docs))))
(make-sized-element #f (reverse content) dest-col))))
(define (typeset c multi-line? prefix1 prefix suffix color? qq?)
(let* ([c (syntax-ize c 0 #:qq? qq?)]
[s (syntax-e c)])
(if (or multi-line?
(eq? 'code:blank s)
(pair? s)
(vector? s)
(struct? s)
(box? s)
(null? s)
(hash? s)
(graph-defn? s)
(graph-reference? s)
(struct-proxy? s))
(gen-typeset c multi-line? prefix1 prefix suffix color? qq?)
(typeset-atom c
(letrec ([mk
(case-lambda
[(elem color)
(mk elem color (or (syntax-span c) 1))]
[(elem color len)
(if (and (string? elem)
(= len (string-length elem)))
(make-element/cache (and color? color) elem)
(make-sized-element (and color? color) elem len))])])
mk)
color? 0 qq?))))
(define (to-element c #:qq? [qq? #f])
(typeset c #f "" "" "" #t qq?))
(define (to-element/no-color c #:qq? [qq? #f])
(typeset c #f "" "" "" #f qq?))
(define (to-paragraph c #:qq? [qq? #f])
(typeset c #t "" "" "" #t qq?))
(define ((to-paragraph/prefix pfx1 pfx sfx) c #:qq? [qq? #f])
(typeset c #t pfx1 pfx sfx #t qq?))
(begin-for-syntax
(define-struct variable-id (sym)
#:omit-define-syntaxes
#:property prop:procedure (lambda (self stx)
(raise-syntax-error
#f
(string-append
"misuse of an identifier (not in `scheme', etc.) that is"
" bound as a code-typesetting variable")
stx)))
(define-struct element-id-transformer (proc)
#:omit-define-syntaxes
#:property prop:procedure (lambda (self stx)
(raise-syntax-error
#f
(string-append
"misuse of an identifier (not in `scheme', etc.) that is"
" bound as an code-typesetting element transformer")
stx))))
(define-syntax (define-code stx)
(syntax-case stx ()
[(_ code typeset-code uncode d->s stx-prop)
(syntax/loc stx
(define-syntax (code stx)
(define (wrap-loc v ctx e)
`(,#'d->s ,ctx
,e
#(code
,(syntax-line v)
,(syntax-column v)
,(syntax-position v)
,(syntax-span v))))
(define (stx->loc-s-expr v)
(let ([slv (and (identifier? v)
(syntax-local-value v (lambda () #f)))])
(cond
[(variable-id? slv)
(wrap-loc v #f `(,#'make-var-id ',(variable-id-sym slv)))]
[(element-id-transformer? slv)
(wrap-loc v #f ((element-id-transformer-proc slv) v))]
[(syntax? v)
(let ([mk (wrap-loc
v
`(quote-syntax ,(datum->syntax v 'defcode))
(syntax-case v (uncode)
[(uncode e) #'e]
[else (stx->loc-s-expr (syntax-e v))]))])
(let ([prop (syntax-property v 'paren-shape)])
(if prop
`(,#'stx-prop ,mk 'paren-shape ,prop)
mk)))]
[(null? v) 'null]
[(list? v) `(list . ,(map stx->loc-s-expr v))]
[(pair? v) `(cons ,(stx->loc-s-expr (car v))
,(stx->loc-s-expr (cdr v)))]
[(vector? v) `(vector ,@(map
stx->loc-s-expr
(vector->list v)))]
[(and (struct? v) (prefab-struct-key v))
`(make-prefab-struct (quote ,(prefab-struct-key v))
,@(map
stx->loc-s-expr
(cdr (vector->list (struct->vector v)))))]
[(box? v) `(box ,(stx->loc-s-expr (unbox v)))]
[else `(quote ,v)])))
(define (cvt s)
(datum->syntax #'here (stx->loc-s-expr s) #f))
(if (eq? (syntax-local-context) 'expression)
(syntax-case stx ()
[(_ expr) #`(typeset-code #,(cvt #'expr))]
[(_ expr (... ...))
#`(typeset-code #,(cvt #'(code:line expr (... ...))))])
(quasisyntax/loc stx
(#%expression #,stx)))))]
[(_ code typeset-code uncode d->s)
#'(define-code code typeset-code uncode d->s syntax-property)]
[(_ code typeset-code uncode)
#'(define-code code typeset-code uncode datum->syntax syntax-property)]
[(_ code typeset-code) #'(define-code code typeset-code unsyntax)]))
(define syntax-ize-hook (make-parameter (lambda (v col) #f)))
(define (vector->short-list v extract)
(vector->list v)
#;
(let ([l (vector->list v)])
(reverse (list-tail
(reverse l)
(- (vector-length v)
(let loop ([i (sub1 (vector-length v))])
(cond
[(zero? i) 1]
[(eq? (extract (vector-ref v i))
(extract (vector-ref v (sub1 i))))
(loop (sub1 i))]
[else (add1 i)])))))))
(define (short-list->vector v l)
(list->vector
(let ([n (length l)])
(if (n . < . (vector-length v))
(reverse (let loop ([r (reverse l)][i (- (vector-length v) n)])
(if (zero? i)
r
(loop (cons (car r) r) (sub1 i)))))
l))))
(define-struct var-id (sym))
(define-struct shaped-parens (val shape))
(define-struct just-context (val ctx))
(define-struct alternate-display (id string))
(define-struct literal-syntax (stx))
(define-struct struct-proxy (name content))
(define-struct graph-reference (bx))
(define-struct graph-defn (r bx))
(define (syntax-ize v col [line 1] #:qq? [qq? #f])
(do-syntax-ize v col line (box #hasheq()) #f (and qq? 0)))
(define (graph-count ht graph?)
(and graph?
(let ([n (hash-ref (unbox ht) '#%graph-count 0)])
(set-box! ht (hash-set (unbox ht) '#%graph-count (add1 n)))
n)))
(define (do-syntax-ize v col line ht graph? qq)
(cond
[((syntax-ize-hook) v col)
=> (lambda (r) r)]
[(shaped-parens? v)
(syntax-property (do-syntax-ize (shaped-parens-val v) col line ht #f qq)
'paren-shape
(shaped-parens-shape v))]
[(just-context? v)
(let ([s (do-syntax-ize (just-context-val v) col line ht #f qq)])
(datum->syntax (just-context-ctx v)
(syntax-e s)
s
s
(just-context-ctx v)))]
[(alternate-display? v)
(let ([s (do-syntax-ize (alternate-display-id v) col line ht #f qq)])
(syntax-property s
'display-string
(alternate-display-string v)))]
[(hash-ref (unbox ht) v #f)
=> (lambda (m)
(unless (unbox m)
(set-box! m #t))
(datum->syntax #f
(make-graph-reference m)
(vector #f line col (+ 1 col) 1)))]
[(and (list? v)
(pair? v)
(let ([s (let ([s (car v)])
(if (just-context? s)
(just-context-val s)
s))])
(and
(or (memq s '(quaisquote quote))
(and (memq s '(unquote unquote-splicing))
(or (not qq)
(qq . > . 2))))
s)))
=> (lambda (s)
(let ([c (do-syntax-ize (cadr v) (+ col 1) line ht #f qq)])
(datum->syntax #f
(list (do-syntax-ize (car v) col line ht #f
(and qq
(case s
[(quaisquote) (add1 qq)]
[(unquote unquote-splicing) (sub1 qq)]
[else qq])))
c)
(vector #f line col (+ 1 col)
(+ 1 (syntax-span c))))))]
[(or (list? v)
(vector? v)
(and (struct? v)
(or (and qq
;; Watch out for partially transparent subtypes of `element':
(not (element? v)))
(prefab-struct-key v))))
(let ([orig-ht (unbox ht)]
[graph-box (box (graph-count ht graph?))]
[qq (and qq (max 1 qq))])
(set-box! ht (hash-set (unbox ht) v graph-box))
(let* ([graph-sz (if graph?
(+ 2 (string-length (format "~a" (unbox graph-box))))
0)]
[vec-sz (cond
[(vector? v)
(+ 1 #;(string-length (format "~a" (vector-length v))))]
[(struct? v)
(if (prefab-struct-key v)
2
0)]
[else 0])]
[r (let ([l (let loop ([col (+ col 1 vec-sz graph-sz)]
[v (cond
[(vector? v)
(vector->short-list v values)]
[(struct? v)
(cons (let ([pf (prefab-struct-key v)])
(if pf
(prefab-struct-key v)
(object-name v)))
(cdr (vector->list (struct->vector v))))]
[else v])])
(if (null? v)
null
(let ([i (do-syntax-ize (car v) col line ht #f qq)])
(cons i
(loop (+ col 1 (syntax-span i)) (cdr v))))))])
(datum->syntax #f
(cond
[(vector? v) (short-list->vector v l)]
[(struct? v)
(let ([pf (prefab-struct-key v)])
(if pf
(apply make-prefab-struct (prefab-struct-key v) (cdr l))
(make-struct-proxy (car l) (cdr l))))]
[else l])
(vector #f line
(+ graph-sz col)
(+ 1 graph-sz col)
(+ 2
vec-sz
(if (zero? (length l))
0
(sub1 (length l)))
(apply + (map syntax-span l))))))])
(unless graph?
(set-box! ht (hash-set (unbox ht) v #f)))
(cond
[graph? (datum->syntax #f
(make-graph-defn r graph-box)
(vector #f (syntax-line r)
(- (syntax-column r) graph-sz)
(- (syntax-position r) graph-sz)
(+ (syntax-span r) graph-sz)))]
[(unbox graph-box)
;; Go again, this time knowing that there will be a graph:
(set-box! ht orig-ht)
(do-syntax-ize v col line ht #t qq)]
[else r])))]
[(pair? v)
(let ([orig-ht (unbox ht)]
[graph-box (box (graph-count ht graph?))]
[qq (and qq (max 1 qq))])
(set-box! ht (hash-set (unbox ht) v graph-box))
(let* ([inc (if graph?
(+ 2 (string-length (format "~a" (unbox graph-box))))
0)]
[a (do-syntax-ize (car v) (+ col 1 inc) line ht #f qq)]
[sep (if (and (pair? (cdr v))
;; FIXME: what if it turns out to be a graph reference?
(not (hash-ref (unbox ht) (cdr v) #f)))
0
3)]
[b (do-syntax-ize (cdr v) (+ col 1 inc (syntax-span a) sep) line ht #f qq)])
(let ([r (datum->syntax #f
(cons a b)
(vector #f line (+ col inc) (+ 1 col inc)
(+ 2 sep (syntax-span a) (syntax-span b))))])
(unless graph?
(set-box! ht (hash-set (unbox ht) v #f)))
(cond
[graph? (datum->syntax #f
(make-graph-defn r graph-box)
(vector #f line col (+ 1 col)
(+ inc (syntax-span r))))]
[(unbox graph-box)
;; Go again...
(set-box! ht orig-ht)
(do-syntax-ize v col line ht #t qq)]
[else r]))))]
[(box? v)
(let ([a (do-syntax-ize (unbox v) (+ col 2) line ht #f (and qq (max 1 qq)))])
(datum->syntax #f
(box a)
(vector #f line col (+ 1 col)
(+ 2 (syntax-span a)))))]
[else
(datum->syntax #f v (vector #f line col (+ 1 col) 1))])))
#lang racket/base
(require "racket.ss")
(provide (all-from-out "racket.ss"))

View File

@ -8,11 +8,12 @@ through a textbook:
@itemize[
@item{@italic{@link["http:///www.htdp.org/"]{How to
Design Programs}} is the best place to start.}
@item{@italic{@link["http:///www.htdp.org/"]{How to Design Programs}}
is the best place to start. Whenever the book says ``Scheme,''
you can read it as ``Racket.''}
@item{@other-manual['(lib "web-server/scribblings/tutorial/continue.scrbl")]
introduces you to the Module language and building web applications.}
introduces you to modules and building web applications.}
@item{@other-manual['(lib "scribblings/guide/guide.scrbl")] describes
the rest of the Racket language, which is much bigger than

View File

@ -1,6 +1,6 @@
#lang scribble/doc
@(require scribble/struct
scribble/scheme
scribble/racket
(for-syntax racket/base)
"mz.ss"
"prog-steps.ss")
@ -11,13 +11,13 @@
@(define *redex (lambda (c)
(make-element highlighted-color (list c))))
@(define-syntax redex
(syntax-rules () [(_ a) (*redex (scheme a))]))
(syntax-rules () [(_ a) (*redex (racket a))]))
@(define hole (make-element #f (list "[]")))
@(define (*sub c e) (make-element #f (list c "[" e "]")))
@(define-syntax sub
(syntax-rules () [(_ a b) (*sub (scheme a) (scheme b))]))
(syntax-rules () [(_ a b) (*sub (racket a) (racket b))]))
@(define (frame n)
(make-element variable-color
(list "C" (make-element 'subscript (list (format "~a" n))))))
@ -29,21 +29,21 @@ to switch to the usual langle/rangle that is used in syntax definitions.
@(define comma (make-element 'tt (list ", ")))
@(define (*state c e) (make-element #f (list langle c comma e rangle)))
@(define-syntax state
(syntax-rules () [(_ a b) (*state (scheme a) (scheme b))]))
(syntax-rules () [(_ a b) (*state (racket a) (racket b))]))
;}
@;------------------------------------------------------------------------
@title[#:tag "eval-model"]{Evaluation Model}
Scheme evaluation can be viewed as the simplification of expressions
Racket evaluation can be viewed as the simplification of expressions
to obtain values. For example, just as an elementary-school student
simplifies
@verbatim{ 1 + 1 = 2}
Scheme evaluation simplifies
Racket evaluation simplifies
@schemeblock[
@racketblock[
(+ 1 1) @#,reduces 2
]
@ -51,14 +51,14 @@ The arrow @reduces above replaces the more traditional @tt{=} to
emphasize that evaluation proceeds in a particular direction towards
simpler expressions. In particular, a @deftech{value} is an
expression that evaluation simplifies no further, such as the number
@scheme[2].
@racket[2].
@;------------------------------------------------------------------------
@section[#:tag "cont-model"]{Sub-expression Evaluation and Continuations}
Some simplifications require more than one step. For example:
@schemeblock[
@racketblock[
(- 4 #,(redex (+ 1 1))) #,reduces #,(redex (- 4 2)) #,reduces 2
]
@ -66,15 +66,15 @@ An expression that is not a @tech{value} can always be partitioned
into two parts: a @deftech{redex}, which is the part that changed in a
single-step simplification (highlighted), and the
@deftech{continuation}, which is the surrounding expression
context. In @scheme[(- 4 (+ 1 1))], the redex is @scheme[(+ 1 1)], and
the continuation is @scheme[(- 4 @#,hole)], where @hole takes the
context. In @racket[(- 4 (+ 1 1))], the redex is @racket[(+ 1 1)], and
the continuation is @racket[(- 4 @#,hole)], where @hole takes the
place of the redex. That is, the continuation says how to ``continue''
after the @tech{redex} is reduced to a @tech{value}.
Before some things can be evaluated, some sub-expressions must be
evaluated; for example, in the application @scheme[(- 4 (+ 1 1))], the
application of @scheme[-] cannot be reduced until the sub-expression
@scheme[(+ 1 1)] is reduced.
evaluated; for example, in the application @racket[(- 4 (+ 1 1))], the
application of @racket[-] cannot be reduced until the sub-expression
@racket[(+ 1 1)] is reduced.
Thus, the specification of each syntactic form specifies how (some of)
its sub-expressions are evaluated, and then how the results are
@ -86,65 +86,65 @@ evaluation steps during which an expression contains the @tech{redex}.
@;------------------------------------------------------------------------
@section{Tail Position}
An expression @scheme[_expr1] is in @deftech{tail position} with
respect to an enclosing expression @scheme[_expr2] if, whenever
@scheme[_expr1] becomes a redex, its @tech{continuation} is the same
as was the enclosing @scheme[_expr2]'s @tech{continuation}.
An expression @racket[_expr1] is in @deftech{tail position} with
respect to an enclosing expression @racket[_expr2] if, whenever
@racket[_expr1] becomes a redex, its @tech{continuation} is the same
as was the enclosing @racket[_expr2]'s @tech{continuation}.
For example, the @scheme[(+ 1 1)] expression is @italic{not} in @tech{tail
position} with respect to @scheme[(- 4 (+ 1 1))]. To illustrate, we use
For example, the @racket[(+ 1 1)] expression is @italic{not} in @tech{tail
position} with respect to @racket[(- 4 (+ 1 1))]. To illustrate, we use
the notation @sub[_C _expr] to mean the expression that is produced by
substituting @scheme[_expr] in place of @hole in the @tech{continuation}
@scheme[_C]:
substituting @racket[_expr] in place of @hole in the @tech{continuation}
@racket[_C]:
@schemeblock[
@racketblock[
@#,sub[_C (- 4 (+ 1 1))] @#,reduces @#,sub[_C (- 4 2)]
]
In this case, the @tech{continuation} for reducing @scheme[(+ 1 1)] is
@sub[_C (+ 4 @#,hole)], not just @scheme[_C].
In this case, the @tech{continuation} for reducing @racket[(+ 1 1)] is
@sub[_C (+ 4 @#,hole)], not just @racket[_C].
In contrast, @scheme[(+ 1 1)] is in @tech{tail position} with respect
to @scheme[(if (zero? 0) (+ 1 1) 3)], because, for any continuation
@scheme[_C],
In contrast, @racket[(+ 1 1)] is in @tech{tail position} with respect
to @racket[(if (zero? 0) (+ 1 1) 3)], because, for any continuation
@racket[_C],
@schemeblock[
@racketblock[
@#,sub[_C (if (zero? 0) (+ 1 1) 3)] @#,reduces @#,sub[_C (if #t (+ 1 1) 3)] @#,reduces @#,sub[_C (+ 1 1)]
]
The steps in this reduction sequence are driven by the definition of
@scheme[if], and they do not depend on the @tech{continuation}
@scheme[_C]. The ``then'' branch of an @scheme[if] form is always in
@tech{tail position} with respect to the @scheme[if] form. Due to a
similar reduction rule for @scheme[if] and @scheme[#f], the ``else''
branch of an @scheme[if] form is also in @tech{tail position}.
@racket[if], and they do not depend on the @tech{continuation}
@racket[_C]. The ``then'' branch of an @racket[if] form is always in
@tech{tail position} with respect to the @racket[if] form. Due to a
similar reduction rule for @racket[if] and @racket[#f], the ``else''
branch of an @racket[if] form is also in @tech{tail position}.
@tech{Tail-position} specifications provide a guarantee about the
asymptotic space consumption of a computation. In general, the
specification of @tech{tail positions} goes with each syntactic form,
like @scheme[if].
like @racket[if].
@;------------------------------------------------------------------------
@section[#:tag "values-model"]{Multiple Return Values}
A Scheme expression can evaluate to @deftech{multiple values}, in the
A Racket expression can evaluate to @deftech{multiple values}, in the
same way that a procedure can accept multiple arguments.
Most @tech{continuations} expect a particular number of result
@tech{values}. Indeed, most @tech{continuations}, such as @scheme[(+
@tech{values}. Indeed, most @tech{continuations}, such as @racket[(+
@#,hole 1)] expect a single @tech{value}. The @tech{continuation}
@scheme[(let-values ([(x y) @#,hole]) _expr)] expects two result
@tech{values}; the first result replaces @scheme[x] in the body
@scheme[_expr], and the second replaces @scheme[y] in
@scheme[_expr]. The @tech{continuation} @scheme[(begin @#,hole (+ 1
@racket[(let-values ([(x y) @#,hole]) _expr)] expects two result
@tech{values}; the first result replaces @racket[x] in the body
@racket[_expr], and the second replaces @racket[y] in
@racket[_expr]. The @tech{continuation} @racket[(begin @#,hole (+ 1
2))] accepts any number of result @tech{values}, because it ignores
the result(s).
In general, the specification of a syntactic form inidicates the
number of @tech{values} that it produces and the number that it
expects from each of its sub-expression. In addtion, some procedures
(notably @scheme[values]) produce multiple @tech{values}, and some
procedures (notably @scheme[call-with-values]) create continuations
(notably @racket[values]) produce multiple @tech{values}, and some
procedures (notably @racket[call-with-values]) create continuations
internally that accept a certain number of @tech{values}.
@;------------------------------------------------------------------------
@ -158,28 +158,28 @@ then an algebra student simplifies @tt{x + 1} as follows:
@verbatim{ x + 1 = 10 + 1 = 11}
Scheme works much the same way, in that a set of @tech{top-level
Racket works much the same way, in that a set of @tech{top-level
variables} are available for substitutions on demand during
evaluation. For example, given
@schemeblock[
@racketblock[
(define x 10)
]
then
@schemeblock[
@racketblock[
#,(redex (+ x 1)) #,reduces #,(redex (+ 10 1)) #,reduces 11
]
In Scheme, the way definitions appear is just as important as the way
that they are used. Scheme evaluation thus keeps track of both
In Racket, the way definitions appear is just as important as the way
that they are used. Racket evaluation thus keeps track of both
definitions and the current expression, and it extends the set of
definitions in response to evaluating forms such as @scheme[define].
definitions in response to evaluating forms such as @racket[define].
Each evaluation step, then, takes the current set of definitions and
program to a new set of definitions and program. Before a
@scheme[define] can be moved into the set of definitions, its
@racket[define] can be moved into the set of definitions, its
right-hand expression must be reduced to a @tech{value}.
@prog-steps/no-obj[
@ -197,7 +197,7 @@ right-hand expression must be reduced to a @tech{value}.
11]
]
Using @scheme[set!], a program can change the value associated with an
Using @racket[set!], a program can change the value associated with an
existing @tech{top-level variable}:
@prog-steps/no-obj[
@ -214,9 +214,9 @@ existing @tech{top-level variable}:
@;------------------------------------------------------------------------
@section{Objects and Imperative Update}
In addition to @scheme[set!] for imperative update of @tech{top-level
In addition to @racket[set!] for imperative update of @tech{top-level
variables}, various procedures enable the modification of elements
within a compound data structure. For example, @scheme[vector-set!]
within a compound data structure. For example, @racket[vector-set!]
modifies the content of a vector.
To allow such modifications to data, we must distingiush between
@ -224,16 +224,16 @@ To allow such modifications to data, we must distingiush between
@deftech{objects}, which hold the data referenced by a value.
A few kinds of @tech{objects} can serve directly as values, including
booleans, @scheme[(void)], and small exact integers. More generally,
booleans, @racket[(void)], and small exact integers. More generally,
however, a @tech{value} is a reference to an @tech{object}. For
example, a @tech{value} can be a reference to a particular vector that
currently holds the value @scheme[10] in its first slot. If an
currently holds the value @racket[10] in its first slot. If an
@tech{object} is modified, then the modification is visible through
all copies of the @tech{value} that reference the same @tech{object}.
In the evaluation model, a set of @tech{objects} must be carried along
with each step in evaluation, just like the definition set. Operations
that create @tech{objects}, such as @scheme[vector], add to the set of
that create @tech{objects}, such as @racket[vector], add to the set of
@tech{objects}:
@prog-steps[
@ -306,35 +306,35 @@ reference is crucial. A @tech{top-level variable} is not a
value is extracted from the current set of definitions. An object
reference, in contrast is a value, and therefore needs no further
evaluation. The model evaluation steps above use angle-bracketed
@scheme[<o1>] for an object reference to distinguish it from a
@racket[<o1>] for an object reference to distinguish it from a
@tech{variable} name.
A direct object reference can never appear in a text-based source
program. A program representation created with
@scheme[datum->syntax-object], however, can embed direct references to
@racket[datum->syntax], however, can embed direct references to
existing @tech{objects}.
@;------------------------------------------------------------------------
@section[#:tag "model-eq"]{Object Identity and Comparisons}
The @scheme[eq?] operator compares two @tech{values}, returning
@scheme[#t] when the values refer to the same @tech{object}. This form
The @racket[eq?] operator compares two @tech{values}, returning
@racket[#t] when the values refer to the same @tech{object}. This form
of equality is suitable for comparing objects that support imperative
update (e.g., to determine that the effect of modifying an object
through one reference is visible through another reference). Also, an
@scheme[eq?] test evaluates quickly, and @scheme[eq?]-based hashing
is more lightweight than @scheme[equal?]-based hashing in hash tables.
@racket[eq?] test evaluates quickly, and @racket[eq?]-based hashing
is more lightweight than @racket[equal?]-based hashing in hash tables.
In some cases, however, @scheme[eq?] is unsuitable as a comparison
In some cases, however, @racket[eq?] is unsuitable as a comparison
operator, because the generation of @tech{objects} is not clearly
defined. In particular, two applications of @scheme[+] to the same two
exact integers may or may not produce results that are @scheme[eq?],
although the results are always @scheme[equal?]. Similarly, evaluation
of a @scheme[lambda] form typically generates a new procedure
defined. In particular, two applications of @racket[+] to the same two
exact integers may or may not produce results that are @racket[eq?],
although the results are always @racket[equal?]. Similarly, evaluation
of a @racket[lambda] form typically generates a new procedure
@tech{object}, but it may re-use a procedure @tech{object} previously
generated by the same source @scheme[lambda] form.
generated by the same source @racket[lambda] form.
The behavior of a datatype with respect to @scheme[eq?] is generally
The behavior of a datatype with respect to @racket[eq?] is generally
specified with the datatype and its associated procedures.
@;------------------------------------------------------------------------
@ -352,9 +352,9 @@ In the program state
(+ 1 x)]
]
evaluation cannot depend on @scheme[<o2>], because it is not part of
evaluation cannot depend on @racket[<o2>], because it is not part of
the program to evaluate, and it is not referenced by any definition
that is accessible in the program. The @tech{object} @scheme[<o2>] may
that is accessible in the program. The @tech{object} @racket[<o2>] may
therefore be removed from the evaluation by @deftech{garbage
collection}.
@ -364,17 +364,17 @@ collector in determining which @tech{objects} are reachable for the
remainder of the computation. If an @tech{object} is reachable only
via a @tech{weak reference}, then the object can be reclaimed, and the
@tech{weak reference} is replaced by a different @tech{value}
(typically @scheme[#f]).
(typically @racket[#f]).
As a special case, a @tech{fixnum} is always considered reachable by
the garbage collector. Many other values are always reachable due to
the way they are implemented and used: A @tech{character} in the
Latin-1 range is always reachable, because @scheme[equal?] Latin-1
characters are always @scheme[eq?], and all of the Latin-1 characters
are referenced by an internal module. Similarly, @scheme[null],
@scheme[#t], @scheme[#f], @scheme[eof], and @|void-const| and are
always reachable. Values produced by @scheme[quote] remain reachable
when the @scheme[quote] expression itself is reachable.
Latin-1 range is always reachable, because @racket[equal?] Latin-1
characters are always @racket[eq?], and all of the Latin-1 characters
are referenced by an internal module. Similarly, @racket[null],
@racket[#t], @racket[#f], @racket[eof], and @|void-const| and are
always reachable. Values produced by @racket[quote] remain reachable
when the @racket[quote] expression itself is reachable.
@;------------------------------------------------------------------------
@section{Procedure Applications and Local Variables}
@ -391,8 +391,8 @@ The key step in this simplification is take the body of the defined
function @tt{f}, and then replace each @tt{x} with the actual
@tech{value} @tt{1}.
Scheme procedure application works much the same way. A procedure is
an @tech{object}, so evaluating @scheme[(f 7)] starts with a
Racket procedure application works much the same way. A procedure is
an @tech{object}, so evaluating @racket[(f 7)] starts with a
@tech{variable} lookup:
@prog-steps[
@ -406,9 +406,9 @@ an @tech{object}, so evaluating @scheme[(f 7)] starts with a
Unlike in algebra, however, the @tech{value} associated with an
argument can be changed in the body of a procedure by using
@scheme[set!], as in the example @scheme[(lambda (x) (begin (set! x 3)
x))]. Since the @tech{value} associated with @scheme[x] can be
changed, an actual value for cannot be substituted for @scheme[x] when
@racket[set!], as in the example @racket[(lambda (x) (begin (set! x 3)
x))]. Since the @tech{value} associated with @racket[x] can be
changed, an actual value for cannot be substituted for @racket[x] when
the procedure is applied.
Instead, a new @deftech{location} is created for each @tech{variable}
@ -439,10 +439,10 @@ a @tech{location} is generated, it (conceptually) uses a name that has
not been used before and that cannot not be generated again or
accessed directly.
Generating a @tech{location} in this way means that @scheme[set!]
Generating a @tech{location} in this way means that @racket[set!]
evaluates for @tech{local variables} in the same way as for
@tech{top-level variables}, because the @tech{local variable} is
always replaced with a @tech{location} by the time the @scheme[set!]
always replaced with a @tech{location} by the time the @racket[set!]
form is evaluated:
@prog-steps[
@ -472,16 +472,16 @@ form is evaluated:
The substitution and @tech{location}-generation step of procedure
application requires that the argument is a @tech{value}. Therefore,
in @scheme[((lambda (x) (+ x 10)) (+ 1 2))], the @scheme[(+ 1 2)]
sub-expression must be simplified to the @tech{value} @scheme[3], and
then @scheme[3] can be placed into a @tech{location} for
@scheme[x]. In other words, Scheme is a @deftech{call-by-value}
in @racket[((lambda (x) (+ x 10)) (+ 1 2))], the @racket[(+ 1 2)]
sub-expression must be simplified to the @tech{value} @racket[3], and
then @racket[3] can be placed into a @tech{location} for
@racket[x]. In other words, Racket is a @deftech{call-by-value}
language.
Evaluation of a local-variable form, such as @scheme[(let ([x (+ 1
2)]) _expr)], is the same as for a procedure call. After @scheme[(+ 1
Evaluation of a local-variable form, such as @racket[(let ([x (+ 1
2)]) _expr)], is the same as for a procedure call. After @racket[(+ 1
2)] produces a @tech{value}, it is stored in a fresh @tech{location}
that replaces every instance of @scheme[x] in @scheme[_expr].
that replaces every instance of @racket[x] in @racket[_expr].
@;------------------------------------------------------------------------
@section{Variables and Locations}
@ -498,20 +498,20 @@ through different instantiations.
For example, in the program
@schemeblock[(define y (+ (let ([x 5]) x) 6))]
@racketblock[(define y (+ (let ([x 5]) x) 6))]
both @scheme[y] and @scheme[x] are @tech{variables}. The @scheme[y]
@tech{variable} is a @tech{top-level variable}, and the @scheme[x] is
both @racket[y] and @racket[x] are @tech{variables}. The @racket[y]
@tech{variable} is a @tech{top-level variable}, and the @racket[x] is
a @tech{local variable}. When this code is evaluated, a
@tech{location} is created for @scheme[x] to hold the value
@scheme[5], and a @tech{location} is also created for @scheme[y] to
hold the value @scheme[6].
@tech{location} is created for @racket[x] to hold the value
@racket[5], and a @tech{location} is also created for @racket[y] to
hold the value @racket[6].
The replacement of a @tech{variable} with a @tech{location} during
evaluation implements Scheme's @deftech{lexical scoping}. For example,
when a procedure-argument @tech{variable} @scheme[x] is replaced by
the @tech{location} @scheme[xloc], then it is replaced throughout the
body of the procedure, including with any nested @scheme[lambda]
evaluation implements Racket's @deftech{lexical scoping}. For example,
when a procedure-argument @tech{variable} @racket[x] is replaced by
the @tech{location} @racket[xloc], then it is replaced throughout the
body of the procedure, including with any nested @racket[lambda]
forms. As a result, future references of the @tech{variable} always
access the same @tech{location}.
@ -520,7 +520,7 @@ access the same @tech{location}.
@margin-note/ref{See @secref["module"] for the syntax of modules.}
Most definitions in PLT Scheme are in modules. In terms of evaluation,
Most definitions in Racket are in modules. In terms of evaluation,
a module is essentially a prefix on a defined name, so that different
modules can define the name. That is, a @deftech{module-level
variable} is like a @tech{top-level variable} from the perspective of
@ -528,57 +528,57 @@ evaluation.
One difference between a module and a top-level definition is that a
module can be declared without instantiating its module-level
definitions. Evaluation of a @scheme[require] @deftech{instantiates}
definitions. Evaluation of a @racket[require] @deftech{instantiates}
(i.e., triggers the @deftech{instantiation} of) a declared module,
which creates variables that correspond to its module-level
definitions.
For example, given the module declaration
@schemeblock[
(module m scheme
@racketblock[
(module m racket
(define x 10))
]
the evaluation of @scheme[(require m)] creates the variable @scheme[x]
and installs @scheme[10] as its value. This @scheme[x] is unrelated to
any top-level definition of @scheme[x].
the evaluation of @racket[(require m)] creates the variable @racket[x]
and installs @racket[10] as its value. This @racket[x] is unrelated to
any top-level definition of @racket[x].
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "module-phase"]{Phases}
A module can be @tech{instantiate}d in multiple @deftech{phases}. A
phase is an integer that, again, is effectively a prefix on the names
of module-level definitions. A top-level @scheme[require]
of module-level definitions. A top-level @racket[require]
@tech{instantiates} a module at @tech{phase} 0, if the module is not
already @tech{instantiate}d at phase 0. A top-level
@scheme[(require (for-syntax ....))] @tech{instantiates} a module at
@racket[(require (for-syntax ....))] @tech{instantiates} a module at
@tech{phase} 1 (if it is not already @tech{instantiate}d at that
level); @scheme[for-syntax] also has a different binding
level); @racket[for-syntax] also has a different binding
effect on further program parsing, as described in
@secref["intro-binding"].
Within a module, some definitions are shifted by a phase already; the
@scheme[define-for-syntax] form is like @scheme[define], but it
@racket[define-for-syntax] form is like @racket[define], but it
defines a variable at relative @tech{phase} 1, instead of relative
@tech{phase} 0. Thus, if the module is @tech{instantiate}d at phase 1,
the variables for @scheme[define-for-syntax] are created at phase 2,
the variables for @racket[define-for-syntax] are created at phase 2,
and so on. Moreover, this relative phase acts as another layer of
prefixing, so that a @scheme[define] of @scheme[x] and a
@scheme[define-for-syntax] of @scheme[x] can co-exist in a module
prefixing, so that a @racket[define] of @racket[x] and a
@racket[define-for-syntax] of @racket[x] can co-exist in a module
without colliding. Again, the higher phases are mainly related to
program parsing, instead of normal evaluation.
If a module @tech{instantiate}d at @tech{phase} @math{n}
@scheme[require]s another module, then the @scheme[require]d module is
@racket[require]s another module, then the @racket[require]d module is
first @tech{instantiate}d at phase @math{n}, and so on
transitively. (Module @scheme[require]s cannot form cycles.) If a
module @tech{instantiate}d at phase @math{n} @scheme[require]s
@scheme[for-syntax] another module, the other module becomes
transitively. (Module @racket[require]s cannot form cycles.) If a
module @tech{instantiate}d at phase @math{n} @racket[require]s
@racket[for-syntax] another module, the other module becomes
@deftech{available} at @tech{phase} @math{n+1}, and it may later be
@tech{instantiate}d at @tech{phase} @math{n+1}. If a module that is
@tech{available} at phase @math{n} for @math{n>0} @scheme[require]s
@scheme[for-template] another module, the other module becomes
@tech{available} at phase @math{n} for @math{n>0} @racket[require]s
@racket[for-template] another module, the other module becomes
@tech{available} at @tech{phase} @math{n-1}, and so
on. @tech{Instantiation}s of @tech{available} modules above
@tech{phase} 0 are triggered on demand as described in
@ -591,11 +591,11 @@ module forms (see @secref["mod-parse"]), and are, again, conceptually
distinguished by prefixes.
Top-level variables can exist in multiple phases in the same way as
within modules. For example, @scheme[define-for-syntax] creates a
within modules. For example, @racket[define-for-syntax] creates a
@tech{phase} 1 variable. Furthermore, reflective operations like
@scheme[make-base-namespace] and @scheme[eval] provide access to
@racket[make-base-namespace] and @racket[eval] provide access to
top-level variables in higher @tech{phases}, while module
@tech{instantiations} (triggered by with @scheme[require]) relative to such
@tech{instantiations} (triggered by with @racket[require]) relative to such
top-levels are in corresponding higher @tech{phase}s.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -620,9 +620,9 @@ re-declared, each re-declaration of the module is immediately
@margin-note/ref{See @secref["contmarks"] for continuation-mark forms and functions.}
Every continuation @scheme[_C] can be partitioned into
Every continuation @racket[_C] can be partitioned into
@deftech{continuation frames} @frame[1], @frame[2], ..., @frame["n"]
such that @scheme[_C] = @*sub[@frame[1] @*sub[@frame[2] @*sub["..."
such that @racket[_C] = @*sub[@frame[1] @*sub[@frame[2] @*sub["..."
@frame["n"]]]], and no frame @frame["i"] can be itself partitioned
into smaller continuations. Evaluation steps add and remove frames to
the current continuation, typically one at a time.
@ -675,13 +675,13 @@ escape-continuation aborts can cross continuation barriers.
@margin-note/ref{See @secref["concurrency"] for thread and synchronization functions.}
Scheme supports multiple @deftech{threads} of evaluation. Threads run
Racket supports multiple @deftech{threads} of evaluation. Threads run
concurrently, in the sense that one thread can preempt another without
its cooperation, but threads currently all run on the same processor
(i.e., the same underlying OS process and thread). See also
@secref["futures"].
Threads are created explicitly by functions such as @scheme[thread].
Threads are created explicitly by functions such as @racket[thread].
In terms of the evaluation model, each step in evaluation actually consists of multiple concurrent
expressions, up to one per thread, rather than a single expression. The expressions all
share the same objects and top-level variables, so that they can
@ -705,7 +705,7 @@ is created) as all other threads.
@margin-note/ref{See @secref["parameters"] for parameter forms and functions.}
@deftech{Parameters} are essentially a derived concept in Scheme; they
@deftech{Parameters} are essentially a derived concept in Racket; they
are defined in terms of @tech{continuation marks} and @tech{thread
cells}. However, parameters are also built in, in the sense that some
primitive procedures consult parameter values. For example, the
@ -726,8 +726,8 @@ preserved thread cell, and the combination of thread cell and current
thread yields the parameter's value. A parameter procedure sets or
accesses the relevant thread cell for its parameter.
Various operations, such as @scheme[parameterize] or
@scheme[call-with-parameterization], install a parameterization into
Various operations, such as @racket[parameterize] or
@racket[call-with-parameterization], install a parameterization into
the current continuation's frame.
@;------------------------------------------------------------------------
@ -735,7 +735,7 @@ the current continuation's frame.
@margin-note/ref{See @secref["exns"] for exception forms, functions, and types.}
@deftech{Exceptions} are essentially a derived concept in Scheme; they
@deftech{Exceptions} are essentially a derived concept in Racket; they
are defined in terms of continuations, prompts, and continuation
marks. However, exceptions are also built in, in the sense that
primitive forms and procedures may raise exceptions.
@ -763,7 +763,7 @@ A @deftech{custodian} manages a collection of threads,
@tech{file-stream ports}, TCP ports, @tech{TCP listeners}, @tech{UDP
sockets}, and @tech{byte converters}. Whenever a thread, etc. is
created, it is placed under the management of the @deftech{current
custodian} as determined by the @scheme[current-custodian]
custodian} as determined by the @racket[current-custodian]
@tech{parameter}.
@margin-note{In MrEd, custodians also manage eventspaces.}
@ -774,20 +774,20 @@ Every object managed by a subordinate custodian is also managed by the
custodian's owner.
When a @tech{custodian} is shut down via
@scheme[custodian-shutdown-all], it forcibly and immediately closes
@racket[custodian-shutdown-all], it forcibly and immediately closes
the ports, TCP connections, etc. that it manages, as well as
terminating (or suspending) its threads. A custodian that has been
shut down cannot manage new objects. If the current custodian is shut
down before a procedure is called to create a managed resource (e.g.,
@scheme[open-input-port], @scheme[thread]), the
@racket[open-input-port], @racket[thread]), the
@exnraise[exn:fail:contract].
A thread can have multiple managing custodians, and a suspended thread
created with @scheme[thread/suspend-to-kill] can have zero
created with @racket[thread/suspend-to-kill] can have zero
custodians. Extra custodians become associated with a thread through
@scheme[thread-resume] (see @secref["threadkill"]). When a thread
@racket[thread-resume] (see @secref["threadkill"]). When a thread
has multiple custodians, it is not necessarily killed by a
@scheme[custodian-shutdown-all], but shut-down custodians are removed
@racket[custodian-shutdown-all], but shut-down custodians are removed
from the thread's managing set, and the thread is killed when its
managing set becomes empty.
@ -800,15 +800,15 @@ collected, at which point its subordinates become immediately
subordinate to the collected custodian's superordinate custodian.
In addition to the other entities managed by a custodian, a
@deftech{custodian box} created with @scheme[make-custodian-box]
@deftech{custodian box} created with @racket[make-custodian-box]
strongly holds onto a value placed in the box until the box's
custodian is shut down. The custodian only weakly retains the box
itself, however (so the box and its content can be collected if there
are no other references to them).
When PLT Scheme is compiled with support for per-custodian memory
accounting (see @scheme[custodian-memory-accounting-available?]), the
@scheme[current-memory-use] procedure can report a custodian-specific
When Racket is compiled with support for per-custodian memory
accounting (see @racket[custodian-memory-accounting-available?]), the
@racket[current-memory-use] procedure can report a custodian-specific
result. This result determines how much memory is occupied by objects
that are reachable from the custodian's managed values, especially its
threads, and including its sub-custodians' managed values. If an

View File

@ -89,12 +89,14 @@ expression is a list of the results in order.
@deftogether[(
@defform[(for/hash (for-clause ...) body ...+)]
@defform[(for/hasheq (for-clause ...) body ...+)]
@defform[(for/hasheqv (for-clause ...) body ...+)]
)]{
Like @scheme[for/list], but the result is an immutable @tech{hash
table}; @scheme[for/hash] creates a table using @scheme[equal?] to
distinguish keys, and @scheme[for/hasheq] produces a table using
@scheme[eq?]. The last expression in the @scheme[body]s must return
distinguish keys, @scheme[for/hasheq] produces a table using
@scheme[eq?], and @scheme[for/hasheqv] produces a table using
@scheme[eqv?]. The last expression in the @scheme[body]s must return
two values: a key and a value to extend the hash table accumulated by
the iteration.
@ -212,6 +214,7 @@ nested.
@defform[(for*/lists (id ...) (for-clause ...) body ...+)]
@defform[(for*/hash (for-clause ...) body ...+)]
@defform[(for*/hasheq (for-clause ...) body ...+)]
@defform[(for*/hasheqv (for-clause ...) body ...+)]
@defform[(for*/and (for-clause ...) body ...+)]
@defform[(for*/or (for-clause ...) body ...+)]
@defform[(for*/first (for-clause ...) body ...+)]

View File

@ -86,6 +86,11 @@ unpredictable.
Returns @scheme[#t] if @scheme[v] is a @tech{hash table}, @scheme[#f]
otherwise.}
@defproc[(hash-equal? [hash hash?]) boolean?]{
Returns @scheme[#t] if @scheme[hash] compares keys with @scheme[equal?],
@scheme[#f] if it compares with @scheme[eq?] or @scheme[eqv?].}
@defproc[(hash-eqv? [hash hash?]) boolean?]{
Returns @scheme[#t] if @scheme[hash] compares keys with @scheme[eqv?],
@ -102,73 +107,69 @@ Returns @scheme[#t] if @scheme[hash] compares keys with @scheme[eq?],
Returns @scheme[#t] if @scheme[hash] retains its keys weakly,
@scheme[#f] if it retains keys strongly.}
@deftogether[(
@defproc[(hash [key any/c] [val any/c] ... ...) (and/c hash? hash-equal? immutable?)]
@defproc[(hasheq [key any/c] [val any/c] ... ...) (and/c hash? hash-eq? immutable?)]
@defproc[(hasheqv [key any/c] [val any/c] ... ...) (and/c hash? hash-eqv? immutable?)]
)]{
@defproc[(make-hash [assocs (listof pair?) null]) hash?]{
Creates an immutable hash table with each given @scheme[key] mapped to
the following @scheme[val]; each @scheme[key] must have a @scheme[val],
so the total number of arguments to @scheme[hash] must be even.
Creates a mutable hash table that holds keys strongly and that uses
@scheme[equal?] to compare keys. See also @scheme[make-custom-hash].
The @scheme[hash] procedure creates a table where keys are compared
with @scheme[equal?], @scheme[hasheq] procedure creates a table where
keys are compared with @scheme[eq?], and @scheme[hasheqv] procedure
creates a table where keys are compared with @scheme[eqv?].
The @scheme[key] to @scheme[val] mappings are added to the table in
the order that they appear in the argument list, so later mappings can
hide earlier mappings if the @scheme[key]s are equal.}
@deftogether[(
@defproc[(make-hash [assocs (listof pair?) null]) (and/c hash? hash-equal?)]
@defproc[(make-hasheqv [assocs (listof pair?) null]) (and/c hash? hash-eqv?)]
@defproc[(make-hasheq [assocs (listof pair?) null]) (and/c hash? hash-eq?)]
)]{
Creates a mutable hash table that holds keys strongly.
The @scheme[make-hash] procedure creates a table where keys are
compared with @scheme[equal?], @scheme[make-hasheq] procedure creates
a table where keys are compared with @scheme[eq?], and
@scheme[make-hasheqv] procedure creates a table where keys are
compared with @scheme[eqv?].
The table is initialized with the content of @scheme[assocs]. In each
element of @scheme[assocs], the @scheme[car] is a key, and the
@scheme[cdr] is the corresponding value. The mappings are added to the
table in the order that they appear in @scheme[assocs], so later
mappings can hide earlier mappings.}
mappings can hide earlier mappings.
See also @scheme[make-custom-hash].}
@defproc[(make-hasheqv [assocs (listof pair?) null]) (and/c hash? hash-eqv?)]{
Creates a mutable hash table that holds keys strongly and that
uses @scheme[eqv?] to compare keys. The table is initialized with the
content of @scheme[assocs] as in @scheme[make-hash].}
@defproc[(make-hasheq [assocs (listof pair?) null]) (and/c hash? hash-eq?)]{
Creates a mutable hash table that holds keys strongly and that
uses @scheme[eq?] to compare keys. The table is initialized with the
content of @scheme[assocs] as in @scheme[make-hash].}
@defproc[(make-weak-hash [assocs (listof pair?) null]) (and/c hash? hash-weak?)]{
Creates a mutable hash table that holds keys weakly and that
uses @scheme[equal?] to compare keys; see also
@scheme[make-weak-custom-hash]. The table is initialized with the
content of @scheme[assocs] as in @scheme[make-hash].}
@defproc[(make-weak-hasheqv [assocs (listof pair?) null]) (and/c hash? hash-eqv? hash-weak?)]{
Creates a mutable hash table that holds keys weakly and that
uses @scheme[eqv?] to compare keys. The table is initialized with the
content of @scheme[assocs] as in @scheme[make-hash].}
@defproc[(make-weak-hasheq [assocs (listof pair?) null]) (and/c hash? hash-eq? hash-weak?)]{
Creates a mutable hash table that holds keys weakly and that
uses @scheme[eq?] to compare keys. The table is initialized with the
content of @scheme[assocs] as in @scheme[make-hash].}
@deftogether[(
@defproc[(make-weak-hash [assocs (listof pair?) null]) (and/c hash? hash-equal? hash-weak?)]
@defproc[(make-weak-hasheqv [assocs (listof pair?) null]) (and/c hash? hash-eqv? hash-weak?)]
@defproc[(make-weak-hasheq [assocs (listof pair?) null]) (and/c hash? hash-eq? hash-weak?)]
)]{
Like @scheme[make-hash], @scheme[make-hasheq], and
@scheme[make-hasheqv], but creates a mutable hash table that holds
keys weakly.}
@deftogether[(
@defproc[(make-immutable-hash [assocs (listof pair?)])
(and/c hash? immutable?)]{
Creates an immutable hash table that compares keys with
@scheme[equal?]. The table is created with the content of
@scheme[assocs] as in @scheme[make-hash].}
(and/c hash? hash-equal? immutable?)]
@defproc[(make-immutable-hasheqv [assocs (listof pair?)])
(and/c hash? hash-eqv? immutable?)]{
Like @scheme[make-immutable-hash], but the resulting hash table
compares keys with @scheme[eqv?].}
(and/c hash? hash-eqv? immutable?)]
@defproc[(make-immutable-hasheq [assocs (listof pair?)])
(and/c hash? hash-eq? immutable?)]{
(and/c hash? hash-eq? immutable?)]
)]{
Like @scheme[make-immutable-hash], but the resulting hash table
compares keys with @scheme[eq?].}
Like @scheme[hash], @scheme[hasheq], and @scheme[hasheqv], but accepts
the key--value mapping in association-list form like
@scheme[make-hash], @scheme[make-hasheq], and @scheme[make-hasheqv].}
@defproc[(hash-set! [hash (and/c hash? (not/c immutable?))]

View File

@ -43,7 +43,7 @@
(define (*prog-steps cont? objs defs progs)
(make-table
'((valignment top top top top top top))
'((valignment baseline baseline baseline baseline baseline baseline))
(apply
append
(for/list ([obj (or objs (in-naturals))]

View File

@ -109,6 +109,7 @@ Applies the procedure @scheme[proc] to each element in
@scheme[set] in an unspecified order, accumulating the results
into a list.}
@defproc[(set-for-each [set set?]
[proc (any/c . -> . any)])
void?]{
@ -116,7 +117,21 @@ into a list.}
Applies @scheme[proc] to each element in @scheme[set] (for the
side-effects of @scheme[proc]) in an unspecified order.}
@defproc[(in-set [set set?]) sequence?]{
Explicitly converts a set to a sequence for use with @scheme[for] and
other forms.}
@deftogether[(
@defform[(for/set (for-clause ...) body ...+)]
@defform[(for/seteq (for-clause ...) body ...+)]
@defform[(for/seteqv (for-clause ...) body ...+)]
@defform[(for*/set (for-clause ...) body ...+)]
@defform[(for*/seteq (for-clause ...) body ...+)]
@defform[(for*/seteqv (for-clause ...) body ...+)]
)]{
Analogous to @scheme[for/list] and @scheme[for*/list], but to
construct a set instead of a list.}

View File

@ -3,13 +3,13 @@
(for-syntax mzscheme)
"mz.ss")
@(define scheme-eval (make-base-eval))
@(interaction-eval #:eval scheme-eval (require (for-syntax racket/base)))
@(define racket-eval (make-base-eval))
@(interaction-eval #:eval racket-eval (require (for-syntax racket/base)))
@;------------------------------------------------------------------------
@title[#:tag "syntax-model"]{Syntax Model}
The syntax of a Scheme program is defined by
The syntax of a Racket program is defined by
@itemize[
@ -22,7 +22,7 @@ The syntax of a Scheme program is defined by
]
For details on the @tech{read} phase, see @secref["reader"]. Source
code is normally read in @scheme[read-syntax] mode, which produces a
code is normally read in @racket[read-syntax] mode, which produces a
@tech{syntax object}.
The @tech{expand} phase recursively processes a @tech{syntax object}
@ -38,7 +38,7 @@ new binding information.
@guideintro["binding"]{binding}
An @deftech{identifier} is source-program entity. Parsing (i.e.,
expanding) a Scheme program reveals that some @tech{identifiers}
expanding) a Racket program reveals that some @tech{identifiers}
correspond to @tech{variables}, some refer to syntactic forms, and
some are quoted to produce a symbol or a syntax object.
@ -55,13 +55,13 @@ uses of an @tech{identifier} refer to the @tech{shadowing}
For example, as a bit of source, the text
@schemeblock[(let ([x 5]) x)]
@racketblock[(let ([x 5]) x)]
includes two @tech{identifiers}: @scheme[let] and @scheme[x] (which
includes two @tech{identifiers}: @racket[let] and @racket[x] (which
appears twice). When this source is parsed in a typical
@tech{environment}, @scheme[x] turns out to represent a
@tech{variable} (unlike @scheme[let]). In particular, the first
@scheme[x] @tech{binds} the second @scheme[x].
@tech{environment}, @racket[x] turns out to represent a
@tech{variable} (unlike @racket[let]). In particular, the first
@racket[x] @tech{binds} the second @racket[x].
A @deftech{top-level binding} is a @tech{binding} from a definition at
the top-level; a @deftech{module binding} is a binding from a
@ -73,10 +73,10 @@ identifiers are called @tech{unbound} in a module context.
Throughout the documentation, @tech{identifiers} are typeset to
suggest the way that they are parsed. A black, boldface
@tech{identifier} like @scheme[lambda] indicates as a reference to a
syntactic form. A plain blue @tech{identifier} like @schemeidfont{x}
@tech{identifier} like @racket[lambda] indicates as a reference to a
syntactic form. A plain blue @tech{identifier} like @racketidfont{x}
is a @tech{variable} or a reference to an unspecified @tech{top-level
variable}. A hyperlinked @tech{identifier} @scheme[cons] is a
variable}. A hyperlinked @tech{identifier} @racket[cons] is a
reference to a specific @tech{top-level variable}.
Every binding has a @deftech{phase level} in which it can be
@ -108,17 +108,17 @@ different phase levels.
@;------------------------------------------------------------------------
@section[#:tag "stxobj-model"]{Syntax Objects}
A @deftech{syntax object} combines a simpler Scheme value, such as a
A @deftech{syntax object} combines a simpler Racket value, such as a
symbol or pair, with @deftech{lexical information} about bindings,
source-location information, @tech{syntax properties}, and
@tech{syntax certificates}. In particular, an @tech{identifier} is
represented as a symbol object that combines a symbol and lexical and
other information.
For example, a @schemeidfont{car} @tech{identifier} might have
@tech{lexical information} that designates it as the @scheme[car] from
the @schememodname[racket/base] language (i.e., the built-in
@scheme[car]). Similarly, a @schemeidfont{lambda} identifier's
For example, a @racketidfont{car} @tech{identifier} might have
@tech{lexical information} that designates it as the @racket[car] from
the @racketmodname[racket/base] language (i.e., the built-in
@racket[car]). Similarly, a @racketidfont{lambda} identifier's
@tech{lexical information} may indicate that it represents a procedure
form. Some other @tech{identifier}'s @tech{lexical information} may
indicate that it references a @tech{top-level variable}.
@ -128,42 +128,42 @@ an @tech{identifier} or simple constant, its internal components can
be extracted. Even for extracted identifier, detailed information
about binding is available mostly indirectly; two identifiers can be
compared to see if they refer to the same binding (i.e.,
@scheme[free-identifier=?]), or whether each identifier would bind the
@racket[free-identifier=?]), or whether each identifier would bind the
other if one was in a binding position and the other in an expression
position (i.e., @scheme[bound-identifier=?]).
position (i.e., @racket[bound-identifier=?]).
For example, the when the program written as
@schemeblock[(let ([x 5]) (+ x 6))]
@racketblock[(let ([x 5]) (+ x 6))]
is represented as a @tech{syntax object}, then two @tech{syntax
objects} can be extracted for the two @scheme[x]s. Both the
@scheme[free-identifier=?] and @scheme[bound-identifier=?] predicates
will indicate that the @scheme[x]s are the same. In contrast, the
@scheme[let] @tech{identifier} is not @scheme[free-identifier=?] or
@scheme[bound-identifier=?] to either @scheme[x].
objects} can be extracted for the two @racket[x]s. Both the
@racket[free-identifier=?] and @racket[bound-identifier=?] predicates
will indicate that the @racket[x]s are the same. In contrast, the
@racket[let] @tech{identifier} is not @racket[free-identifier=?] or
@racket[bound-identifier=?] to either @racket[x].
The @tech{lexical information} in a @tech{syntax object} is
independent of the other half, and it can be copied to a new syntax
object in combination with an arbitrary other Scheme value. Thus,
object in combination with an arbitrary other Racket value. Thus,
identifier-@tech{binding} information in a @tech{syntax object} is
predicated on the symbolic name of the @tech{identifier} as well as
the identifier's @tech{lexical information}; the same question with
the same @tech{lexical information} but different base value can
produce a different answer.
For example, combining the lexical information from @scheme[let] in
the program above to @scheme['x] would not produce an identifier that
is @scheme[free-identifier=?] to either @scheme[x], since it does not
appear in the scope of the @scheme[x] binding. Combining the lexical
context of the @scheme[6] with @scheme['x], in contrast, would produce
an identifier that is @scheme[bound-identifier=?] to both @scheme[x]s.
For example, combining the lexical information from @racket[let] in
the program above to @racket['x] would not produce an identifier that
is @racket[free-identifier=?] to either @racket[x], since it does not
appear in the scope of the @racket[x] binding. Combining the lexical
context of the @racket[6] with @racket['x], in contrast, would produce
an identifier that is @racket[bound-identifier=?] to both @racket[x]s.
The @scheme[quote-syntax] form bridges the evaluation of a program and
the representation of a program. Specifically, @scheme[(quote-syntax
The @racket[quote-syntax] form bridges the evaluation of a program and
the representation of a program. Specifically, @racket[(quote-syntax
_datum)] produces a syntax object that preserves all of the lexical
information that @scheme[_datum] had when it was parsed as part of the
@scheme[quote-syntax] form.
information that @racket[_datum] had when it was parsed as part of the
@racket[quote-syntax] form.
@;------------------------------------------------------------------------
@section[#:tag "expansion"]{Expansion@aux-elem{ (Parsing)}}
@ -184,7 +184,7 @@ following grammar:
@margin-note{Beware that the symbolic names of identifiers in a fully
expanded program may not match the symbolic names in the grammar. Only
the binding (according to @scheme[free-identifier=?]) matters.}
the binding (according to @racket[free-identifier=?]) matters.}
@schemegrammar*[
#:literals (#%expression module #%plain-module-begin begin #%provide
@ -217,7 +217,7 @@ the binding (according to @scheme[free-identifier=?]) matters.}
(letrec-values (((id ...) expr) ...)
expr ...+)
(set! id expr)
(@#,scheme[quote] datum)
(@#,racket[quote] datum)
(quote-syntax datum)
(with-continuation-mark expr expr expr)
(#%plain-app expr ...+)
@ -235,29 +235,29 @@ information} on its @tech{identifiers} indicates the
@tech{parse}.
More specifically, the typesetting of identifiers in the above grammar
is significant. For example, the second case for @scheme[_expr] is a
is significant. For example, the second case for @racket[_expr] is a
@tech{syntax-object} list whose first element is an @tech{identifier},
where the @tech{identifier}'s @tech{lexical information} specifies a
binding to the @scheme[#%plain-lambda] of the
@schememodname[racket/base] language (i.e., the @tech{identifier} is
@scheme[free-identifier=?] to one whose binding is
@scheme[#%plain-lambda]). In all cases, identifiers above typeset as
binding to the @racket[#%plain-lambda] of the
@racketmodname[racket/base] language (i.e., the @tech{identifier} is
@racket[free-identifier=?] to one whose binding is
@racket[#%plain-lambda]). In all cases, identifiers above typeset as
syntactic-form names refer to the bindings defined in
@secref["syntax"].
Only @tech{phase levels} 0 and 1 are relevant for the parse of a
program (though the @scheme[_datum] in a @scheme[quote-syntax] form
program (though the @racket[_datum] in a @racket[quote-syntax] form
preserves its information for all @tech{phase level}s). In particular,
the relevant @tech{phase level} is 0, except for the @scheme[_expr]s
in a @scheme[define-syntax], @scheme[define-syntaxes],
@scheme[define-for-syntax], or @scheme[define-values-for-syntax] form,
the relevant @tech{phase level} is 0, except for the @racket[_expr]s
in a @racket[define-syntax], @racket[define-syntaxes],
@racket[define-for-syntax], or @racket[define-values-for-syntax] form,
in which case the relevant @tech{phase level} is 1 (for which
comparisons are made using @scheme[free-transformer-identifier=?]
instead of @scheme[free-identifier=?]).
comparisons are made using @racket[free-transformer-identifier=?]
instead of @racket[free-identifier=?]).
In addition to the grammar above, @scheme[letrec-syntaxes+values] can
In addition to the grammar above, @racket[letrec-syntaxes+values] can
appear in a fully local-expanded expression, such as the result from
@scheme[local-expand] when the stop list is empty.
@racket[local-expand] when the stop list is empty.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "expand-steps"]{Expansion Steps}
@ -274,15 +274,15 @@ the @tech{syntax object} being expanded:
@tech{binding} other than as a @tech{top-level variable}, that
@tech{binding} is used to continue. If the @tech{identifier}
has no @tech{binding}, a new @tech{syntax-object} symbol
@scheme['#%top] is created using the @tech{lexical information}
of the @tech{identifier}; if this @schemeidfont{#%top}
@racket['#%top] is created using the @tech{lexical information}
of the @tech{identifier}; if this @racketidfont{#%top}
@tech{identifier} has no @tech{binding} (other than as a
@tech{top-level variable}), then parsing fails with an
@scheme[exn:fail:syntax] exception. Otherwise, the new
@racket[exn:fail:syntax] exception. Otherwise, the new
@tech{identifier} is combined with the original
@tech{identifier} in a new @tech{syntax-object} pair (also
using the same @tech{lexical information} as the original
@tech{identifier}), and the @schemeidfont{#%top} @tech{binding}
@tech{identifier}), and the @racketidfont{#%top} @tech{binding}
is used to continue.}
@item{If it is a @tech{syntax-object} pair whose first element is an
@ -291,26 +291,26 @@ the @tech{syntax object} being expanded:
the @tech{identifier}'s @tech{binding} is used to continue.}
@item{If it is a @tech{syntax-object} pair of any other form, then a
new @tech{syntax-object} symbol @scheme['#%app] is created
new @tech{syntax-object} symbol @racket['#%app] is created
using the @tech{lexical information} of the pair. If the
resulting @schemeidfont{#%app} @tech{identifier} has no
binding, parsing fails with an @scheme[exn:fail:syntax]
resulting @racketidfont{#%app} @tech{identifier} has no
binding, parsing fails with an @racket[exn:fail:syntax]
exception. Otherwise, the new @tech{identifier} is combined
with the original pair to form a new @tech{syntax-object} pair
(also using the same @tech{lexical information} as the original
pair), and the @schemeidfont{#%app} @tech{binding} is used to
pair), and the @racketidfont{#%app} @tech{binding} is used to
continue.}
@item{If it is any other syntax object, then a new
@tech{syntax-object} symbol @scheme['#%datum] is created using
@tech{syntax-object} symbol @racket['#%datum] is created using
the @tech{lexical information} of the original @tech{syntax
object}. If the resulting @schemeidfont{#%datum}
object}. If the resulting @racketidfont{#%datum}
@tech{identifier} has no @tech{binding}, parsing fails with an
@scheme[exn:fail:syntax] exception. Otherwise, the new
@racket[exn:fail:syntax] exception. Otherwise, the new
@tech{identifier} is combined with the original @tech{syntax
object} in a new @tech{syntax-object} pair (using the same
@tech{lexical information} as the original pair), and the
@schemeidfont{#%datum} @tech{binding} is used to continue.}
@racketidfont{#%datum} @tech{binding} is used to continue.}
]
@ -321,24 +321,24 @@ things:
@itemize[
@item{A @tech{transformer binding}, such as introduced by
@scheme[define-syntax] or @scheme[let-syntax]. If the
@racket[define-syntax] or @racket[let-syntax]. If the
associated value is a procedure of one argument, the procedure
is called as a @tech{syntax transformer} (described below), and
parsing starts again with the @tech{syntax-object} result. If
the @tech{transformer binding} is to any other kind of value,
parsing fails with an @scheme[exn:fail:syntax] exception. The
call to the @tech{syntax transformer} is @scheme[parameterize]d
to set @scheme[current-namespace] to a @tech{namespace} that
parsing fails with an @racket[exn:fail:syntax] exception. The
call to the @tech{syntax transformer} is @racket[parameterize]d
to set @racket[current-namespace] to a @tech{namespace} that
shares @tech{bindings} and @tech{variables} with the namespace
being used to expand, except that its @tech{base phase} is one
greater.}
@item{A @tech{variable} @tech{binding}, such as introduced by a
module-level @scheme[define] or by @scheme[let]. In this case,
module-level @racket[define] or by @racket[let]. In this case,
if the form being parsed is just an @tech{identifier}, then it
is parsed as a reference to the corresponding
@tech{variable}. If the form being parsed is a
@tech{syntax-object} pair, then an @scheme[#%app] is added to
@tech{syntax-object} pair, then an @racket[#%app] is added to
the front of the @tech{syntax-object} pair in the same way as
when the first item in the @tech{syntax-object} pair is not an
identifier (third case in the previous enumeration), and
@ -357,7 +357,7 @@ things:
Each expansion step occurs in a particular @deftech{context}, and
transformers and core syntactic forms may expand differently for
different @tech{contexts}. For example, a @scheme[module] form is
different @tech{contexts}. For example, a @racket[module] form is
allowed only in a @tech{top-level context}, and it fails in other
contexts. The possible @tech{contexts} are as follows:
@ -365,7 +365,7 @@ contexts. The possible @tech{contexts} are as follows:
@item{@deftech{top-level context} : outside of any module, definition, or
expression, except that sub-expressions of a top-level
@scheme[begin] form are also expanded as top-level forms.}
@racket[begin] form are also expanded as top-level forms.}
@item{@deftech{module-begin context} : inside the body of a module, as the
only form within the module.}
@ -382,7 +382,7 @@ contexts. The possible @tech{contexts} are as follows:
]
Different core @tech{syntactic forms} parse sub-forms using different
@tech{contexts}. For example, a @scheme[let] form always parses the
@tech{contexts}. For example, a @racket[let] form always parses the
right-hand expressions of a binding in an @tech{expression context},
but it starts parsing the body in an @tech{internal-definition
context}.
@ -395,58 +395,58 @@ core syntactic forms are encountered:
@itemize[
@item{When a @scheme[require] form is encountered at the top level or
@item{When a @racket[require] form is encountered at the top level or
module level, all lexical information derived from the top
level or the specific module's level are extended with bindings
from the specified modules. If not otherwise indicated in the
@scheme[require] form, bindings are introduced at the
@racket[require] form, bindings are introduced at the
@tech{phase level}s specified by the exporting modules:
@tech{phase level} 0 for each normal @scheme[provide],
@tech{phase level} 1 for each @scheme[for-syntax]
@scheme[provide], and so on. The @scheme[for-meta]
@scheme[provide] form allows exports at an arbitrary
@tech{phase level} 0 for each normal @racket[provide],
@tech{phase level} 1 for each @racket[for-syntax]
@racket[provide], and so on. The @racket[for-meta]
@racket[provide] form allows exports at an arbitrary
@tech{phase level} (as long as a binding exists within the
module at the @tech{phase level}).
A @scheme[for-syntax] sub-form within @scheme[require] imports
A @racket[for-syntax] sub-form within @racket[require] imports
similarly, but the resulting bindings have a @tech{phase level}
that is one more than the exported @tech{phase levels}, when
exports for the @tech{label phase level} are still imported at
the @tech{label phase level}. More generally, a
@scheme[for-meta] sub-form within @scheme[require] imports with
@racket[for-meta] sub-form within @racket[require] imports with
the specified @tech{phase level} shift; if the specified shift
is @scheme[#f], or if @scheme[for-label] is used to import,
is @racket[#f], or if @racket[for-label] is used to import,
then all bindings are imported into the @tech{label phase
level}.}
@item{When a @scheme[define], @scheme[define-values],
@scheme[define-syntax], or @scheme[define-syntaxes] form is
@item{When a @racket[define], @racket[define-values],
@racket[define-syntax], or @racket[define-syntaxes] form is
encountered at the top level or module level, all lexical
information derived from the top level or the specific module's
level is extended with bindings for the specified identifiers
at @tech{phase level} 0 (i.e., the @tech{base environment} is
extended).}
@item{When a @scheme[define-for-syntax] or
@scheme[define-values-for-syntax] form is encountered at the
@item{When a @racket[define-for-syntax] or
@racket[define-values-for-syntax] form is encountered at the
top level or module level, bindings are introduced as for
@scheme[define-values], but at @tech{phase level} 1 (i.e., the
@racket[define-values], but at @tech{phase level} 1 (i.e., the
@tech{transformer environment} is extended).}
@item{When a @scheme[let-values] form is encountered, the body of the
@scheme[let-values] form is extended (by creating new
@item{When a @racket[let-values] form is encountered, the body of the
@racket[let-values] form is extended (by creating new
@tech{syntax objects}) with bindings for the specified
identifiers. The same bindings are added to the identifiers
themselves, so that the identifiers in binding position are
@scheme[bound-identifier=?] to uses in the fully expanded form,
and so they are not @scheme[bound-identifier=?] to other
@racket[bound-identifier=?] to uses in the fully expanded form,
and so they are not @racket[bound-identifier=?] to other
identifiers. The bindings are available for use at the
@tech{phase level} at which the @scheme[let-values] form is
@tech{phase level} at which the @racket[let-values] form is
expanded.}
@item{When a @scheme[letrec-values] or
@scheme[letrec-syntaxes+values] form is encountered, bindings
are added as for @scheme[let-values], except that the
@item{When a @racket[letrec-values] or
@racket[letrec-syntaxes+values] form is encountered, bindings
are added as for @racket[let-values], except that the
right-hand-side expressions are also extended with the
bindings.}
@ -457,26 +457,26 @@ core syntactic forms are encountered:
A new binding in lexical information maps to a new variable. The
identifiers mapped to this variable are those that currently have the
same binding (i.e., that are currently @scheme[bound-identifier=?]) to
same binding (i.e., that are currently @racket[bound-identifier=?]) to
the identifier associated with the binding.
For example, in
@schemeblock[
@racketblock[
(let-values ([(x) 10]) (+ x y))
]
the binding introduced for @scheme[x] applies to the @scheme[x] in the
body, but not the @scheme[y] n the body, because (at the point in
expansion where the @scheme[let-values] form is encountered) the
binding @scheme[x] and the body @scheme[y] are not
@scheme[bound-identifier=?].
the binding introduced for @racket[x] applies to the @racket[x] in the
body, but not the @racket[y] n the body, because (at the point in
expansion where the @racket[let-values] form is encountered) the
binding @racket[x] and the body @racket[y] are not
@racket[bound-identifier=?].
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "transformer-model"]{Transformer Bindings}
In a @tech{top-level context} or @tech{module context}, when the
expander encounters a @scheme[define-syntaxes] form, the binding that
expander encounters a @racket[define-syntaxes] form, the binding that
it introduces for the defined identifiers is a @deftech{transformer
binding}. The @tech{value} of the @tech{binding} exists at expansion
time, rather than run time (though the two times can overlap), though
@ -484,13 +484,13 @@ the binding itself is introduced with @tech{phase level} 0 (i.e., in
the @tech{base environment}).
The @tech{value} for the binding is obtained by evaluating the
expression in the @scheme[define-syntaxes] form. This expression must
expression in the @racket[define-syntaxes] form. This expression must
be @tech{expand}ed (i.e. parsed) before it can be evaluated, and it is
expanded at @tech{phase level} 1 (i.e., in the @tech{transformer
environment}) instead of @tech{phase level} 0.
If the resulting @scheme[value] is a procedure of one argument or
the result of @scheme[make-set!-transformer] on a procedure, then it
If the resulting @racket[value] is a procedure of one argument or
the result of @racket[make-set!-transformer] on a procedure, then it
is used as a @deftech{syntax transformer} (a.k.a. @deftech{macro}).
The procedure is expected to accept a syntax object and return a
syntax object. A use of the binding (at @tech{phase level} 0) triggers
@ -503,7 +503,7 @@ applies to all sub-@tech{syntax objects}). The result of the
transformer is similarly extended with the same @tech{syntax
mark}. When a @tech{syntax object}'s @tech{lexical information}
includes the same mark twice in a row, the marks effectively
cancel. Otherwise, two identifiers are @scheme[bound-identifier=?]
cancel. Otherwise, two identifiers are @racket[bound-identifier=?]
(that is, one can bind the other) only if they have the same binding
and if they have the same marks---counting only marks that were added
after the binding.
@ -512,7 +512,7 @@ This marking process helps keep binding in an expanded program
consistent with the lexical structure of the source program. For
example, the expanded form of the program
@schemeblock[
@racketblock[
(define x 12)
(define-syntax m
(syntax-rules ()
@ -522,7 +522,7 @@ example, the expanded form of the program
is
@schemeblock[
@racketblock[
(define x 12)
(define-syntax m
(syntax-rules ()
@ -530,42 +530,42 @@ is
(let-values ([(x) 10]) x)
]
However, the result of the last expression is @scheme[12], not
@scheme[10]. The reason is that the transformer bound to @scheme[m]
introduces the binding @scheme[x], but the referencing @scheme[x] is
present in the argument to the transformer. The introduced @scheme[x]
is the one left with a mark, and the reference @scheme[x] has no mark,
so the binding @scheme[x] is not @scheme[bound-identifier=?] to the
body @scheme[x].
However, the result of the last expression is @racket[12], not
@racket[10]. The reason is that the transformer bound to @racket[m]
introduces the binding @racket[x], but the referencing @racket[x] is
present in the argument to the transformer. The introduced @racket[x]
is the one left with a mark, and the reference @racket[x] has no mark,
so the binding @racket[x] is not @racket[bound-identifier=?] to the
body @racket[x].
The @scheme[set!] form works with the @scheme[make-set!-transformer]
and @scheme[prop:set!-transformer] property to support
@deftech{assignment transformers} that transform @scheme[set!]
The @racket[set!] form works with the @racket[make-set!-transformer]
and @racket[prop:set!-transformer] property to support
@deftech{assignment transformers} that transform @racket[set!]
expressions. An @tech{assignment transformer} contains a procedure
that is applied by @scheme[set!] in the same way as a normal
that is applied by @racket[set!] in the same way as a normal
transformer by the expander.
The @scheme[make-rename-transformer] procedure or
@scheme[prop:rename-transformer] property creates a value that is also
handled specially by the expander and by @scheme[set!] as a
transformer binding's value. When @scheme[_id] is bound to a
The @racket[make-rename-transformer] procedure or
@racket[prop:rename-transformer] property creates a value that is also
handled specially by the expander and by @racket[set!] as a
transformer binding's value. When @racket[_id] is bound to a
@deftech{rename transformer} produced by
@scheme[make-rename-transformer], it is replaced with the target
identifier passed to @scheme[make-rename-transformer]. In addition, as
@racket[make-rename-transformer], it is replaced with the target
identifier passed to @racket[make-rename-transformer]. In addition, as
long as the target identifier does not have a true value for the
@scheme['not-free-identifier=?] @tech{syntax property}, the lexical information that
contains the binding of @scheme[_id] is also enriched so that
@scheme[_id] is @scheme[free-identifier=?] to the target identifier,
@scheme[identifier-binding] returns the same results for both
identifiers, and @scheme[provide] exports @scheme[_id] as the target
@racket['not-free-identifier=?] @tech{syntax property}, the lexical information that
contains the binding of @racket[_id] is also enriched so that
@racket[_id] is @racket[free-identifier=?] to the target identifier,
@racket[identifier-binding] returns the same results for both
identifiers, and @racket[provide] exports @racket[_id] as the target
identifier. Finally, the binding is treated specially by
@scheme[syntax-local-value], and
@scheme[syntax-local-make-delta-introducer] as used by @tech{syntax
@racket[syntax-local-value], and
@racket[syntax-local-make-delta-introducer] as used by @tech{syntax
transformer}s.
In addition to using marks to track introduced identifiers, the
expander tracks the expansion history of a form through @tech{syntax
properties} such as @scheme['origin]. See @secref["stxprops"] for
properties} such as @racket['origin]. See @secref["stxprops"] for
more information.
Finally, the expander uses @tech{syntax certificates} to control the
@ -573,15 +573,15 @@ way that unexported and protected @tech{module bindings} are used. See
@secref["stxcerts"] for more information on @tech{syntax
certificates}.
The expander's handling of @scheme[letrec-values+syntaxes] is similar
to its handling of @scheme[define-syntaxes]. A
@scheme[letrec-values+syntaxes] mist be expanded in an arbitrary phase
The expander's handling of @racket[letrec-values+syntaxes] is similar
to its handling of @racket[define-syntaxes]. A
@racket[letrec-values+syntaxes] mist be expanded in an arbitrary phase
level @math{n} (not just 0), in which case the expression for the
@tech{transformer binding} is expanded at @tech{phase level} @math{n+1}.
The expression in a @scheme[define-for-syntax] or
@scheme[define-values-for-syntax] form is expanded and evaluated in
the same way as for @scheme[syntax]. However, the introduced binding
The expression in a @racket[define-for-syntax] or
@racket[define-values-for-syntax] form is expanded and evaluated in
the same way as for @racket[syntax]. However, the introduced binding
is a variable binding at @tech{phase level} 1 (not a @tech{transformer
binding} at @tech{phase level} 0).
@ -595,9 +595,9 @@ forms. Partial expansion works by cutting off the normal recursion
expansion when the relevant binding is for a primitive syntactic form.
As a special case, when expansion would otherwise add an
@schemeidfont{#%app}, @schemeidfont{#%datum}, or @schemeidfont{#%top}
@racketidfont{#%app}, @racketidfont{#%datum}, or @racketidfont{#%top}
identifier to an expression, and when the binding turns out to be the
primitive @scheme[#%app], @scheme[#%datum], or @scheme[#%top] form,
primitive @racket[#%app], @racket[#%datum], or @racket[#%top] form,
then expansion stops without adding the identifier.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -611,72 +611,72 @@ recursively expands only until the form becomes one of the following:
@itemize[
@item{A @scheme[define-values] or @scheme[define-syntaxes] form, for
@item{A @racket[define-values] or @racket[define-syntaxes] form, for
any form other than the last one: The definition form is not
expanded further. Instead, the next form is expanded partially,
and so on. As soon as an expression form is found, the
accumulated definition forms are converted to a
@scheme[letrec-values] (if no @scheme[define-syntaxes] forms
were found) or @scheme[letrec-syntaxes+values] form, moving the
@racket[letrec-values] (if no @racket[define-syntaxes] forms
were found) or @racket[letrec-syntaxes+values] form, moving the
expression forms to the body to be expanded in expression
context.
When a @scheme[define-values] form is discovered, the lexical
When a @racket[define-values] form is discovered, the lexical
context of all syntax objects for the body sequence is
immediately enriched with bindings for the
@scheme[define-values] form before expansion continues. When a
@scheme[define-syntaxes] form is discovered, the right-hand
@racket[define-values] form before expansion continues. When a
@racket[define-syntaxes] form is discovered, the right-hand
side is expanded and evaluated (as for a
@scheme[letrec-values+syntaxes] form), and a transformer
@racket[letrec-values+syntaxes] form), and a transformer
binding is installed for the body sequence before expansion
continues.}
@item{A primitive expression form other than @scheme[begin]: The
@item{A primitive expression form other than @racket[begin]: The
expression is expanded in an expression context, along with all
remaining body forms. If any definitions were found, this
expansion takes place after conversion to a
@scheme[letrec-values] or @scheme[letrec-syntaxes+values]
@racket[letrec-values] or @racket[letrec-syntaxes+values]
form. Otherwise, the expressions are expanded immediately.}
@item{A @scheme[begin] form: The sub-forms of the @scheme[begin] are
@item{A @racket[begin] form: The sub-forms of the @racket[begin] are
spliced into the internal-definition sequence, and partial
expansion continues with the first of the newly-spliced forms
(or the next form, if the @scheme[begin] had no sub-forms).}
(or the next form, if the @racket[begin] had no sub-forms).}
]
If the last expression form turns out to be a @scheme[define-values]
or @scheme[define-syntaxes] form, expansion fails with a syntax error.
If the last expression form turns out to be a @racket[define-values]
or @racket[define-syntaxes] form, expansion fails with a syntax error.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "mod-parse"]{Module Phases and Visits}
A @scheme[require] form not only introduces @tech{bindings} at
A @racket[require] form not only introduces @tech{bindings} at
expansion time, but also @deftech{visits} the referenced module when
it is encountered by the expander. That is, the expander
instantiates any @scheme[define-for-syntax]ed variables defined
instantiates any @racket[define-for-syntax]ed variables defined
in the module, and also evaluates all expressions for
@scheme[define-syntaxes] @tech{transformer bindings}.
@racket[define-syntaxes] @tech{transformer bindings}.
Module @tech{visits} propagate through @scheme[require]s in the same
Module @tech{visits} propagate through @racket[require]s in the same
way as module @tech{instantiation}. Moreover, when a module is
@tech{visit}ed at @tech{phase} 0, any module that it @scheme[require]s
@scheme[for-syntax] is @tech{instantiate}d at @tech{phase} 1, while
further @scheme[require]s @scheme[for-template] leading back
@tech{visit}ed at @tech{phase} 0, any module that it @racket[require]s
@racket[for-syntax] is @tech{instantiate}d at @tech{phase} 1, while
further @racket[require]s @racket[for-template] leading back
to @tech{phase} 0 causes the required module to be visited at
@tech{phase} 0 (i.e., not @tech{instantiate}d).
During compilation, the top-level of module context is itself
implicitly @tech{visit}ed. Thus, when the expander encounters
@scheme[(require (for-syntax ....))], it immediately
@racket[(require (for-syntax ....))], it immediately
@tech{instantiate}s the required module at @tech{phase} 1, in addition
to adding bindings at @tech{phase level} 1 (i.e., the
@tech{transformer environment}). Similarly, the expander immediately
evaluates any @scheme[define-values-for-syntax] form that it
evaluates any @racket[define-values-for-syntax] form that it
encounters.
@tech{Phases} beyond 0 are @tech{visit}ed on demand. For example,
when the right-hand side of a @tech{phase}-0 @scheme[let-syntax] is to
when the right-hand side of a @tech{phase}-0 @racket[let-syntax] is to
be expanded, then modules that are @tech{available} at @tech{phase} 1
are visited. More generally, initiating expansion at @tech{phase}
@math{n} @tech{visit}s modules at @tech{phase} @math{n}, which in turn
@ -686,14 +686,14 @@ modules in the enclosing @tech{namespace}'s @tech{module registry};
a per-registry lock prevents multiple threads from concurrently
instantiating and visiting available modules.
When the expander encounters @scheme[require] and @scheme[(require
When the expander encounters @racket[require] and @racket[(require
(for-syntax ....))] within a @tech{module context}, the resulting
@tech{visits} and @tech{instantiations} are specific to the expansion
of the enclosing module, and are kept separate from @tech{visits} and
@tech{instantiations} triggered from a @tech{top-level context} or
from the expansion of a different module. Along the same lines, when a
module is attached to a namespace through
@scheme[namespace-attach-module], modules that it @scheme[require]s
@racket[namespace-attach-module], modules that it @racket[require]s
are transitively attached, but instances are attached only at
phases at or below the namespace's @tech{base phase}.
@ -710,7 +710,7 @@ When a top-level definition binds an identifier that originates from a
(define-syntax def-and-use-of-x
(syntax-rules ()
[(def-and-use-of-x val)
(code:comment @#,t{@scheme[x] below originates from this macro:})
(code:comment @#,t{@racket[x] below originates from this macro:})
(begin (define x val) x)]))
(define x 1)
x
@ -720,7 +720,7 @@ x
(define-syntax def-and-use
(syntax-rules ()
[(def-and-use x val)
(code:comment @#,t{@scheme{x} below was provided by the macro use:})
(code:comment @#,t{@racket{x} below was provided by the macro use:})
(begin (define x val) x)]))
(def-and-use x 3)
x
@ -733,12 +733,12 @@ For a top-level definition (outside of a module), the order of
definition were not present. (No such dependency on order occurs
within a module, since a module binding covers the entire module
body.) To support the declaration of an identifier before its use,
the @scheme[define-syntaxes] form avoids binding an identifier if the
body of the @scheme[define-syntaxes] declaration produces zero
the @racket[define-syntaxes] form avoids binding an identifier if the
body of the @racket[define-syntaxes] declaration produces zero
results.
@examples[
#:eval scheme-eval
#:eval racket-eval
(define bucket-1 0)
(define bucket-2 0)
(define-syntax def-and-set!-use-of-x
@ -755,7 +755,7 @@ bucket-2
(syntax-rules ()
[(def-and-use)
(begin
(code:comment @#,t{Initial reference to @scheme[even] precedes definition:})
(code:comment @#,t{Initial reference to @racket[even] precedes definition:})
(define (odd x) (if (zero? x) #f (even (sub1 x))))
(define (even x) (if (zero? x) #t (odd (sub1 x))))
(odd 17))]))
@ -765,7 +765,7 @@ bucket-2
(syntax-rules ()
[(def-and-use)
(begin
(code:comment @#,t{Declare before definition via no-values @scheme[define-syntaxes]:})
(code:comment @#,t{Declare before definition via no-values @racket[define-syntaxes]:})
(define-syntaxes (odd even) (values))
(define (odd x) (if (zero? x) #f (even (sub1 x))))
(define (even x) (if (zero? x) #t (odd (sub1 x))))
@ -773,29 +773,29 @@ bucket-2
(defs-and-uses)
]
Macro-generated @scheme{require} and @scheme{provide}
Macro-generated @racket{require} and @racket{provide}
clauses also introduce and reference generation-specific bindings:
@itemize[
@item{In @scheme[require], for a @scheme[_require-spec] of the form
@scheme[(rename-in [_orig-id _bind-id])] or @scheme[(only-in
.... [_orig-id _bind-id])], the @scheme[_bind-id] is bound only for
@item{In @racket[require], for a @racket[_require-spec] of the form
@racket[(rename-in [_orig-id _bind-id])] or @racket[(only-in
.... [_orig-id _bind-id])], the @racket[_bind-id] is bound only for
uses of the identifier generated by the same macro expansion as
@scheme[_bind-id]. In @scheme[require] for other
@scheme[_require-spec]s, the generator of the @scheme[_require-spec]
@racket[_bind-id]. In @racket[require] for other
@racket[_require-spec]s, the generator of the @racket[_require-spec]
determines the scope of the bindings.}
@item{In @scheme[provide], for a @scheme[_provide-spec] of the form
@scheme[_id], the exported identifier is the one that binds
@scheme[_id] within the module in a generator-specific way, but the
external name is the plain @scheme[_id]. The exceptions for
@scheme[all-except-out] are similarly determined in a
generator-specific way, as is the @scheme[_orig-id] binding of a
@scheme[rename-out] form, but plain identifiers are used for the
external names. For @scheme[all-defined-out], only identifiers with
@item{In @racket[provide], for a @racket[_provide-spec] of the form
@racket[_id], the exported identifier is the one that binds
@racket[_id] within the module in a generator-specific way, but the
external name is the plain @racket[_id]. The exceptions for
@racket[all-except-out] are similarly determined in a
generator-specific way, as is the @racket[_orig-id] binding of a
@racket[rename-out] form, but plain identifiers are used for the
external names. For @racket[all-defined-out], only identifiers with
definitions having the same generator as the
@scheme[(all-defined-out)] form are exported; the external name is
@racket[(all-defined-out)] form are exported; the external name is
the plain identifier from the definition.}
]
@ -815,7 +815,7 @@ string, so it is suitable for saving and re-loading code.
Although individual read, expand, compile, and evaluate operations are
available, the operations are often combined automatically. For
example, the @scheme[eval] procedure takes a syntax object and expands
example, the @racket[eval] procedure takes a syntax object and expands
it, compiles it, and evaluates it.
@;------------------------------------------------------------------------
@ -826,7 +826,7 @@ manipulate namespaces.}
A @deftech{namespace} is a top-level mapping from symbols to binding
information. It is the starting point for expanding an expression; a
@tech{syntax object} produced by @scheme[read-syntax] has no initial
@tech{syntax object} produced by @racket[read-syntax] has no initial
lexical context; the @tech{syntax object} can be expanded after
initializing it with the mappings of a particular namespace. A
namespace is also the starting point evaluating expanded code, where
@ -850,7 +850,7 @@ An ``empty'' namespace maps all symbols to top-level variables.
Certain evaluations extend a namespace for future expansions;
importing a module into the top-level adjusts the namespace bindings
for all of the imported named, and evaluating a top-level
@scheme[define] form updates the namespace's mapping to refer to a
@racket[define] form updates the namespace's mapping to refer to a
variable (in addition to installing a value into the variable).
A namespace also has a @deftech{module registry} that maps module
@ -863,9 +863,9 @@ distinct set of module instances in each @tech{phase}. That is, even
though module declarations are shared for all @tech{phase levels},
module instances are distinct for each @tech{phase}. Each namespace
has a @deftech{base phase}, which corresponds to the phase used by
reflective operations such as @scheme[eval] and
@scheme[dynamic-require]. In particular, using @scheme[eval] on a
@scheme[require] form @tech{instantiates} a module in the namespace's
reflective operations such as @racket[eval] and
@racket[dynamic-require]. In particular, using @racket[eval] on a
@racket[require] form @tech{instantiates} a module in the namespace's
@tech{base phase}.
After a namespace is created, module instances from existing
@ -890,14 +890,14 @@ and to start evaluating expanded/compiled code.
@examples[
(code:line
(define x 'orig) (code:comment @#,t{define in the original namespace}))
(code:comment @#,t{The following @scheme[let] expression is compiled in the original})
(code:comment @#,t{namespace, so direct references to @scheme[x] see @scheme['orig].})
(code:comment @#,t{The following @racket[let] expression is compiled in the original})
(code:comment @#,t{namespace, so direct references to @racket[x] see @racket['orig].})
(code:line
(let ([n (make-base-namespace)]) (code:comment @#,t{make new namespace})
(parameterize ([current-namespace n])
(eval '(define x 'new)) (code:comment @#,t{evals in the new namespace})
(display x) (code:comment @#,t{displays @scheme['orig]})
(display (eval 'x)))) (code:comment @#,t{displays @scheme['new]}))
(display x) (code:comment @#,t{displays @racket['orig]})
(display (eval 'x)))) (code:comment @#,t{displays @racket['new]}))
]
A @tech{namespace} is purely a top-level entity, not to be confused
@ -924,7 +924,7 @@ x
(define x 7)
x
(f)
(module m mzscheme (define x 8) (provide x))
(module m racket (define x 8) (provide x))
(require 'm)
(eval:alts x (eval 'x))
(f)
@ -937,28 +937,28 @@ To improve error reporting, names are inferred at compile-time for
certain kinds of values, such as procedures. For example, evaluating
the following expression:
@schemeblock[
@racketblock[
(let ([f (lambda () 0)]) (f 1 2 3))
]
produces an error message because too many arguments are provided to
the procedure. The error message is able to report @schemeidfont{f} as
the name of the procedure. In this case, Scheme decides, at
compile-time, to name as @scheme['f] all procedures created by the
@scheme[let]-bound @scheme[lambda].
the procedure. The error message is able to report @racketidfont{f} as
the name of the procedure. In this case, Racket decides, at
compile-time, to name as @racket['f] all procedures created by the
@racket[let]-bound @racket[lambda].
Names are inferred whenever possible for procedures. Names closer to
an expression take precedence. For example, in
@schemeblock[
@racketblock[
(define my-f
(let ([f (lambda () 0)]) f))
]
the procedure bound to @scheme[my-f] will have the inferred name
@scheme['f].
the procedure bound to @racket[my-f] will have the inferred name
@racket['f].
When an @indexed-scheme['inferred-name] property is attached to a
When an @indexed-racket['inferred-name] property is attached to a
syntax object for an expression (see @secref["stxprops"]), the
property value is used for naming the expression, and it overrides any
name that was inferred from the expression's context. Normally, the
@ -967,8 +967,8 @@ property value should be a symbol or an identifier.
When an inferred name is not available, but a source location is
available, a name is constructed using the source location
information. Inferred and property-assigned names are also available
to syntax transformers, via @scheme[syntax-local-name].
to syntax transformers, via @racket[syntax-local-name].
@;----------------------------------------
@close-eval[scheme-eval]
@close-eval[racket-eval]

File diff suppressed because it is too large Load Diff

View File

@ -102,4 +102,8 @@
;; ----------------------------------------
(test (set 1 2 3) 'for/set (for/set ([i '(0 1 2)]) (add1 i)))
;; ----------------------------------------
(report-errs)

View File

@ -84,6 +84,7 @@
mzscheme/lang/reader
scheme/base/lang/reader
scheme/lang/reader
scheme/private/lang/reader
scheme/private/provider/lang/reader
racket/base/lang/reader
racket/private/lang/reader

File diff suppressed because it is too large Load Diff

View File

@ -100,11 +100,15 @@ static Scheme_Object *make_weak_hasheqv(int argc, Scheme_Object *argv[]);
static Scheme_Object *make_immutable_hash(int argc, Scheme_Object *argv[]);
static Scheme_Object *make_immutable_hasheq(int argc, Scheme_Object *argv[]);
static Scheme_Object *make_immutable_hasheqv(int argc, Scheme_Object *argv[]);
static Scheme_Object *direct_hash(int argc, Scheme_Object *argv[]);
static Scheme_Object *direct_hasheq(int argc, Scheme_Object *argv[]);
static Scheme_Object *direct_hasheqv(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_table_count(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_table_copy(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_p(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_eq_p(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_eqv_p(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_equal_p(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_weak_p(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_table_put_bang(int argc, Scheme_Object *argv[]);
static Scheme_Object *hash_table_put(int argc, Scheme_Object *argv[]);
@ -511,6 +515,21 @@ scheme_init_list (Scheme_Env *env)
"make-immutable-hasheqv",
1, 1),
env);
scheme_add_global_constant("hash",
scheme_make_immed_prim(direct_hash,
"hash",
0, -1),
env);
scheme_add_global_constant("hasheq",
scheme_make_immed_prim(direct_hasheq,
"hasheq",
0, -1),
env);
scheme_add_global_constant("hasheqv",
scheme_make_immed_prim(direct_hasheqv,
"hasheqv",
0, -1),
env);
scheme_add_global_constant("hash?",
scheme_make_folding_prim(hash_p,
"hash?",
@ -526,6 +545,11 @@ scheme_init_list (Scheme_Env *env)
"hash-eqv?",
1, 1, 1),
env);
scheme_add_global_constant("hash-equal?",
scheme_make_folding_prim(hash_equal_p,
"hash-equal?",
1, 1, 1),
env);
scheme_add_global_constant("hash-weak?",
scheme_make_folding_prim(hash_weak_p,
"hash-weak?",
@ -1817,6 +1841,42 @@ static Scheme_Object *make_immutable_hasheqv(int argc, Scheme_Object *argv[])
return make_immutable_table("make-immutable-hasheqv", 2, argc, argv);
}
static Scheme_Object *direct_table(const char *who, int kind, int argc, Scheme_Object *argv[])
{
int i;
Scheme_Hash_Tree *ht;
if (argc & 0x1) {
scheme_arg_mismatch(who,
"key does not have a value (i.e., an odd number of arguments were provided): ",
argv[argc-1]);
return NULL;
}
ht = scheme_make_hash_tree(kind);
for (i = 0; i < argc; i += 2) {
ht = scheme_hash_tree_set(ht, argv[i], argv[i+1]);
}
return (Scheme_Object *)ht;
}
static Scheme_Object *direct_hash(int argc, Scheme_Object *argv[])
{
return direct_table("hash", 1, argc, argv);
}
static Scheme_Object *direct_hasheq(int argc, Scheme_Object *argv[])
{
return direct_table("hasheq", 0, argc, argv);
}
static Scheme_Object *direct_hasheqv(int argc, Scheme_Object *argv[])
{
return direct_table("hasheqv", 2, argc, argv);
}
Scheme_Hash_Table *scheme_make_hash_table_equal()
{
Scheme_Hash_Table *t;
@ -2005,6 +2065,29 @@ static Scheme_Object *hash_eqv_p(int argc, Scheme_Object *argv[])
return scheme_false;
}
static Scheme_Object *hash_equal_p(int argc, Scheme_Object *argv[])
{
Scheme_Object *o = argv[0];
if (SCHEME_CHAPERONEP(o))
o = SCHEME_CHAPERONE_VAL(o);
if (SCHEME_HASHTP(o)) {
if (((Scheme_Hash_Table *)o)->compare == compare_equal)
return scheme_true;
} else if (SCHEME_HASHTRP(o)) {
if (SCHEME_HASHTR_FLAGS((Scheme_Hash_Tree *)o) & 0x1)
return scheme_true;
} else if (SCHEME_BUCKTP(o)) {
if (((Scheme_Bucket_Table *)o)->compare == compare_equal)
return scheme_true;
} else {
scheme_wrong_type("hash-equal?", "hash", 0, argc, argv);
}
return scheme_false;
}
static Scheme_Object *hash_weak_p(int argc, Scheme_Object *argv[])
{
Scheme_Object *o = argv[0];

View File

@ -13,7 +13,7 @@
#define USE_COMPILED_STARTUP 1
#define EXPECTED_PRIM_COUNT 988
#define EXPECTED_PRIM_COUNT 992
#define EXPECTED_UNSAFE_COUNT 65
#define EXPECTED_FLFXNUM_COUNT 53

View File

@ -13,12 +13,12 @@
consistently.)
*/
#define MZSCHEME_VERSION "4.2.5.10"
#define MZSCHEME_VERSION "4.2.5.11"
#define MZSCHEME_VERSION_X 4
#define MZSCHEME_VERSION_Y 2
#define MZSCHEME_VERSION_Z 5
#define MZSCHEME_VERSION_W 10
#define MZSCHEME_VERSION_W 11
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)