From 78ec58582776c660fbeb0782ce708ae40295223a Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 8 Jan 2009 17:33:44 +0000 Subject: [PATCH 01/38] fix print method of editor<%> classes svn: r13038 --- collects/mred/private/editor.ss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/collects/mred/private/editor.ss b/collects/mred/private/editor.ss index a3b13cb453..f5c4d3a7bf 100644 --- a/collects/mred/private/editor.ss +++ b/collects/mred/private/editor.ss @@ -358,7 +358,8 @@ [(x y) (sp x y 'standard #f #t)] [(x y z) (sp x y z #f #t)] [(x y z f) (sp x y z f #t)] - [(x y z f b?) (sp x y z f b?)]))] + [(x y z f b?) (sp x y z f b?)] + [(x y z f b? eps?) (sp x y z f b? eps?)]))] [on-new-box (entry-point From 2821275df73eb5159d7ae005315f450269d83ae2 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Thu, 8 Jan 2009 23:04:27 +0000 Subject: [PATCH 02/38] simplified world terminology svn: r13041 --- .../2htdp/scribblings/universe.scrbl | 162 +++++++++--------- 1 file changed, 84 insertions(+), 78 deletions(-) diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index 6609c611b4..14997b1957 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -32,9 +32,9 @@ This @tt{universe.ss} teachpack implements and provides the functionality for creating interactive, graphical programs that consist of plain - mathematical functions. We refer to such programs as @defterm{world} + mathematical functions. We refer to such programs as @deftech{world} programs. In addition, world programs can also become a part of a - @defterm{universe}, a collection of worlds that can exchange messages. + @deftech{universe}, a collection of worlds that can exchange messages. The purpose of this documentation is to give experienced Schemers and HtDP teachers a concise overview for using the library. The first part of the @@ -42,7 +42,7 @@ The purpose of this documentation is to give experienced Schemers and HtDP presents an illustration of how to design such programs for a simple domain; it is suited for a novice who knows how to design conditional functions for symbols. The second half of the documentation focuses on - @tech{universe} programs: how it is managed via a server, how @tech{world} + "universe" programs: how it is managed via a server, how @tech{world} programs register with the server, etc. The last two sections show how to design a simple universe of two communicating worlds. @@ -138,17 +138,17 @@ The following picture provides an intuitive overview of the workings of a @image["nuworld.png"] - The @scheme[big-bang] form installs @scheme[World_0] as the initial - world. The handlers @scheme[tock], @scheme[react], and @scheme[click] transform + The @scheme[big-bang] form installs @scheme[World_0] as the initial @tech{WorldState}. + The handlers @scheme[tock], @scheme[react], and @scheme[click] transform one world into another one; each time an event is handled, @scheme[done] is used to check whether the world is final, in which case the program is shut down; and finally, @scheme[draw] renders each world as a scene, which is then displayed on an external canvas. -@deftech{World} : @scheme[any/c] +@deftech{WorldState} : @scheme[any/c] The design of a world program demands that you come up with a data - definition of all possible states. We use @tech{World} to refer to + definition of all possible states. We use @tech{WorldState} to refer to this collection of data, using a capital W to distinguish it from the program. In principle, there are no constraints on this data definition though it mustn't be an instance of the @tech{Package} @@ -176,7 +176,7 @@ The design of a world program demands that you come up with a data starts a @tech{world} program in the initial state specified with @scheme[state-expr], which must of course evaluate to an element of - @tech{World}. Its behavior is specified via the handler functions + @tech{WorldState}. Its behavior is specified via the handler functions designated in the optional @scheme[spec] clauses, especially how the @tech{world} program deals with clock ticks, with key events, with mouse events, and eventually with messages from the universe; how it renders @@ -190,7 +190,7 @@ The design of a world program demands that you come up with a data @item{ @defform[(on-tick tick-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{World}) (unsyntax @tech{World}))])]{ + ([tick-expr (-> (unsyntax @tech{WorldState}) (unsyntax @tech{WorldState}))])]{ tell DrScheme to call the @scheme[tick-expr] function on the current world every time the clock ticks. The result of the call becomes the @@ -199,7 +199,7 @@ current world. The clock ticks at the rate of 28 times per second.}} @item{ @defform/none[(on-tick tick-expr rate-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{World}) (unsyntax @tech{World}))] + ([tick-expr (-> (unsyntax @tech{WorldState}) (unsyntax @tech{WorldState}))] [rate-expr natural-number/c])]{ tell DrScheme to call the @scheme[tick-expr] function on the current world every time the clock ticks. The result of the call becomes the @@ -234,7 +234,7 @@ A character is used to signal that the user has hit an alphanumeric @defform[(on-key change-expr) #:contracts - ([change-expr (-> (unsyntax @tech{World}) key-event? (unsyntax @tech{World}))])]{ + ([change-expr (-> (unsyntax @tech{WorldState}) key-event? (unsyntax @tech{WorldState}))])]{ tell DrScheme to call @scheme[change-expr] function on the current world and a @tech{KeyEvent} for every keystroke the user of the computer makes. The result of the call becomes the current world. @@ -288,7 +288,7 @@ All @tech{MouseEvent}s are represented via symbols: @defform[(on-mouse clack-expr) #:contracts ([clack-expr - (-> (unsyntax @tech{World}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) (unsyntax @tech{World}))])]{ + (-> (unsyntax @tech{WorldState}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) (unsyntax @tech{WorldState}))])]{ tell DrScheme to call @scheme[clack-expr] on the current world, the current @scheme[x] and @scheme[y] coordinates of the mouse, and and a @tech{MouseEvent} for every (noticeable) action of the mouse by the @@ -303,7 +303,7 @@ All @tech{MouseEvent}s are represented via symbols: @defform[(on-draw render-expr) #:contracts - ([render-expr (-> (unsyntax @tech{World}) scene?)])]{ + ([render-expr (-> (unsyntax @tech{WorldState}) scene?)])]{ tell DrScheme to call the function @scheme[render-expr] whenever the canvas must be drawn. The external canvas is usually re-drawn after DrScheme has @@ -312,7 +312,7 @@ All @tech{MouseEvent}s are represented via symbols: @defform/none[(on-draw render-expr width-expr height-expr) #:contracts - ([render-expr (-> (unsyntax @tech{World}) scene?)] + ([render-expr (-> (unsyntax @tech{WorldState}) scene?)] [width-expr natural-number/c] [height-expr natural-number/c])]{ @@ -325,7 +325,7 @@ All @tech{MouseEvent}s are represented via symbols: @defform[(stop-when last-world?) #:contracts - ([last-world? (-> (unsyntax @tech{World}) boolean?)])]{ + ([last-world? (-> (unsyntax @tech{WorldState}) boolean?)])]{ tell DrScheme to call the @scheme[last-world?] function whenever the canvas is drawn. If this call produces @scheme[true], the world program is shut down. Specifically, the clock is stopped; no more @@ -436,7 +436,8 @@ it to the locked position; and} Simulating any dynamic behavior via a @tech{world} program demands two different activities. First, we must tease out those portions of our domain that change over time or in reaction to actions, and we must - develop a data representation @deftech{D} for this information. Keep in + develop a data representation for this information. This is what we call + @tech{WorldState}. Keep in mind that a good data definition makes it easy for readers to map data to information in the real world and vice versa. For all others aspects of the world, we use global constants, including graphical or visual @@ -447,7 +448,7 @@ Second, we must translate the actions in our domain---the arrows in the teachpack can deal with. Once we have decided to use the passing of time for one aspect, key presses for another, and mouse movements for a third, we must develop functions that map the current state of the - world---represented as data from @tech{D}---into the next state of the + world---represented as data from @tech{WorldState}---into the next state of the world. Put differently, we have just created a wish list with three handler functions that have the following general contract and purpose statements: @@ -455,16 +456,16 @@ Second, we must translate the actions in our domain---the arrows in the @(begin #reader scribble/comment-reader (schemeblock -;; tick : @tech{D} -> @tech{D} +;; tick : WorldState -> WorldState ;; deal with the passing of time (define (tick w) ...) -;; click : @tech{D} @emph{Number} @emph{Number} @tech{MouseEvent} -> @tech{D} +;; click : WorldState @emph{Number} @emph{Number} @tech{MouseEvent} -> WorldState ;; deal with a mouse click at @emph{(x,y)} of kind @emph{me} ;; in the current world @emph{w} (define (click w x y me) ...) -;; control : @tech{D} @tech{KeyEvent} -> @tech{D} +;; control : WorldState @tech{KeyEvent} -> WorldState ;; deal with a key event (symbol, char) @emph{ke} ;; in the current world @emph{w} (define (control w ke) ...) @@ -487,15 +488,14 @@ Our first and immediate goal is to represent the world as data. In this the door is whether it is locked, unlocked but closed, or open. We use three symbols to represent the three states: -@deftech{SD} : state of door - @(begin #reader scribble/comment-reader (schemeblock -;; The state of the door (SD) is one of: +;; WorldState is one of: ;; -- @scheme['locked] ;; -- @scheme['closed] ;; -- @scheme['open] +;; interpretation: state of door )) Symbols are particularly well-suited here because they directly express @@ -535,14 +535,14 @@ a visible scene.} ] -Let's start with @emph{automatic-closer}. Substituting @tech{SD} for -@tech{D} and @emph{automatic-closer} for @emph{tick}, we get its contract, +Let's start with @emph{automatic-closer}. Since @emph{automatic-closer} +acts as the @scheme[on-tick] handler, we get its contract, and it is easy to refine the purpose statement, too: @(begin #reader scribble/comment-reader (schemeblock -;; automatic-closer : @tech{SD} -> @tech{SD} +;; automatic-closer : WorldState -> WorldState ;; closes an open door over the period of one tick (define (automatic-closer state-of-door) ...) )) @@ -560,7 +560,7 @@ and it is easy to refine the purpose statement, too: @(begin #reader scribble/comment-reader (schemeblock -;; automatic-closer : @tech{SD} -> @tech{SD} +;; automatic-closer : WorldState -> WorldState ;; closes an open door over the period of one tick (check-expect (automatic-closer 'locked) 'locked) @@ -604,7 +604,7 @@ For the remaining three arrows of the diagram, we design a function that @(begin #reader scribble/comment-reader (schemeblock -;; door-actions : @tech{SD} @tech{KeyEvent} -> @tech{SD} +;; door-actions : WorldState @tech{KeyEvent} -> WorldState ;; key events simulate actions on the door (define (door-actions s k) ...) )) @@ -644,7 +644,7 @@ purpose: @(begin #reader scribble/comment-reader (schemeblock -;; render : @tech{SD} -> @tech{scene} +;; render : WorldState -> @tech{scene} ;; translate the current state of the door into a large text (define (render s) (text (symbol->string s) 40 'red)) @@ -719,9 +719,9 @@ Note the last clause includes @scheme[empty] of course. Each world-producing callback in a world program---those for handling clock tick events, keyboard events, and mouse events---may produce a - @tech{Package} in addition to just a @tech{World}. + @tech{Package} in addition to just a @tech{WorldState}. -@deftech{Package} represents a pair consisting of a @tech{World} (state) +@deftech{Package} represents a pair consisting of a @tech{WorldState} and a message from a @tech{world} program to the @tech{server}. Because programs only send messages via @tech{Package}, the teachpack does not provide the selectors for the structure, only the constructor and a @@ -731,38 +731,38 @@ Each world-producing callback in a world program---those for handling clock determine whether @scheme[x] is a @tech{Package}.} @defproc[(make-package [w any/c][m sexp?]) package?]{ - create a @tech{Package} from a @tech{World} and an @tech{S-expression}.} + create a @tech{Package} from a @tech{WorldState} and an @tech{S-expression}.} -As mentioned, all event handlers may return @tech{World}s or @tech{Package}s; +As mentioned, all event handlers may return @tech{WorldState}s or @tech{Package}s; here are the revised specifications: @defform/none[(on-tick tick-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{World}) (or/c (unsyntax @tech{World}) package?))])]{ + ([tick-expr (-> (unsyntax @tech{WorldState}) (or/c (unsyntax @tech{WorldState}) package?))])]{ } @defform/none[(on-tick tick-expr rate-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{World}) (or/c (unsyntax @tech{World}) package?))] + ([tick-expr (-> (unsyntax @tech{WorldState}) (or/c (unsyntax @tech{WorldState}) package?))] [rate-expr natural-number/c])]{ } @defform/none[(on-key change-expr) #:contracts - ([change-expr (-> (unsyntax @tech{World}) key-event? (or/c (unsyntax @tech{World}) package?))])]{ + ([change-expr (-> (unsyntax @tech{WorldState}) key-event? (or/c (unsyntax @tech{WorldState}) package?))])]{ } @defform/none[(on-mouse clack-expr) #:contracts ([clack-expr - (-> (unsyntax @tech{World}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) - (or/c (unsyntax @tech{World}) package?))])]{ + (-> (unsyntax @tech{WorldState}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) + (or/c (unsyntax @tech{WorldState}) package?))])]{ } If one of these event handlers produces a @tech{Package}, the content of the world field becomes the next world and the message field specifies what the world sends to the universe. This distinction also explains why the data - definition for @tech{World} may not include a @tech{Package}. + definition for @tech{WorldState} may not include a @tech{Package}. @subsection{Connecting with the Universe} @@ -823,14 +823,14 @@ The @scheme[on-receive] clause of a @scheme[big-bang] specifies the event handle @defform[(on-receive receive-expr) #:contracts - ([receive-expr (-> (unsyntax @tech{World}) sexp? (or/c (unsyntax @tech{World}) package?))])]{ + ([receive-expr (-> (unsyntax @tech{WorldState}) sexp? (or/c (unsyntax @tech{WorldState}) package?))])]{ tell DrScheme to call @scheme[receive-expr] for every message receipt, on the current - @tech{World} and the received message. The result of the call becomes the current - @tech{World}. + @tech{WorldState} and the received message. The result of the call becomes the current + @tech{WorldState}. Because @scheme[receive-expr] is (or evaluates to) a world-transforming function, it too can produce a @tech{Package} instead of just a - @tech{World}. If the result is a @tech{Package}, its message content is + @tech{WorldState}. If the result is a @tech{Package}, its message content is sent to the @tech{server}.} The diagram below summarizes the extensions of this section in graphical form. @@ -842,9 +842,9 @@ A registered world program may send a message to the universe server message is transmitted to the server, which may forward it to some other world program as given or in some massaged form. The arrival of a message is just another event that a world program must deal with. Like - all other event handlers @emph{receive} accepts a @tech{World} and some + all other event handlers @emph{receive} accepts a @tech{WorldState} and some auxiliary arguments (a message in this case) and produces a - @tech{World} or a @tech{Package}. + @tech{WorldState} or a @tech{Package}. When messages are sent from any of the worlds to the universe or vice versa, there is no need for the sender and receiver to synchronize. Indeed, a sender @@ -961,7 +961,7 @@ A @tech{server} keeps track of information about the @tech{universe} that represented depends on the situation and the programmer, just as with @tech{world} programs. -@deftech{Universe} @scheme[any/c] represent the server's state For running +@deftech{UniverseState} @scheme[any/c] represent the server's state For running @tech{universe}s, the teachpack demands that you come up with a data definition for (your state of the) @tech{server}. Any piece of data can represent the state. We just assume that you introduce a data definition @@ -1010,16 +1010,16 @@ description. Two of them are mandatory: @item{ @defform[(on-new new-expr) #:contracts - ([new-expr (-> (unsyntax @tech{Universe}) world? - (cons (unsyntax @tech{Universe}) [listof mail?]))])]{ + ([new-expr (-> (unsyntax @tech{UniverseState}) world? + (cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{ tell DrScheme to call the function @scheme[new-expr] every time another world joins the universe.}} @item{ @defform[(on-msg msg-expr) #:contracts - ([msg-expr (-> (unsyntax @tech{Universe}) world? sexp? - (cons (unsyntax @tech{Universe}) [listof mail?]))])]{ + ([msg-expr (-> (unsyntax @tech{UniverseState}) world? sexp? + (cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{ tell DrScheme to apply @scheme[msg-expr] to the current state of the universe, the world that sent the message, and the message itself. The handler must produce a state of the @@ -1039,7 +1039,7 @@ optional handlers: @item{ @defform/none[(on-tick tick-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{Universe}) bundle?)])]{ + ([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)])]{ tell DrScheme to apply @scheme[tick-expr] to the current state of the universe. The handler is expected to produce a bundle of the new state of the universe and a list of mails. @@ -1047,7 +1047,7 @@ optional handlers: @defform/none[(on-tick tick-expr rate-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{Universe}) bundle?)] + ([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)] [rate-expr natural-number/c])]{ tell DrScheme to apply @scheme[tick-expr] as above but use the specified clock tick rate instead of the default. @@ -1057,7 +1057,7 @@ optional handlers: @item{ @defform[(on-disconnect dis-expr) #:contracts - ([dis-expr (-> (unsyntax @tech{Universe}) world? bundle?)])]{ + ([dis-expr (-> (unsyntax @tech{UniverseState}) world? bundle?)])]{ tell DrScheme to invoke @scheme[dis-expr] every time a participating @tech{world} drops its connection to the server. The first argument is the current state of the universe; the second one is the world that got @@ -1068,7 +1068,7 @@ optional handlers: @item{ @defform[(to-string render-expr) #:contracts - ([render-expr (-> (unsyntax @tech{Universe}) string?)])]{ + ([render-expr (-> (unsyntax @tech{UniverseState}) string?)])]{ tell DrScheme to render the state of the universe after each event and to display this string in the universe console. } @@ -1134,7 +1134,7 @@ In summary, the first step of a protocol design is to introduce: @itemize[ @item{a data definition for the information about the universe that the -server tracks, call it @tech{Universe};} +server tracks, call it @tech{UniverseState};} @item{a data definition for the world(s) about their current relationship to the universe;} @@ -1172,13 +1172,13 @@ translates into the design of two functions with the following headers, @(begin #reader scribble/comment-reader (schemeblock -;; @tech{Universe} World -> (make-bundle @tech{Universe} [Listof mail?]) -;; create new @tech{Universe} when world w is joining the universe, +;; @tech{UniverseState} world? -> (make-bundle @tech{UniverseState} [Listof mail?]) +;; create new @tech{UniverseState} when world w is joining the universe, ;; which is in state s; also send mails as needed (define (add-world s w) ...) -;; @tech{Universe} World MsgW2U -> (make-bundle @tech{Universe} [Listof mail?]) -;; create new @tech{Universe} when world w is sending message m +;; @tech{UniverseState} world? MsgW2U -> (make-bundle @tech{UniverseState} [Listof mail?]) +;; create new @tech{UniverseState} when world w is sending message m ;; to universe in state s; also send mails as needed (define (process s p m) ...) )) @@ -1205,7 +1205,7 @@ As for the server's state, it must obviously keep track of all @tech{world}s tha no @tech{world}s and, at that point, the server has nothing to track. While there are many different useful ways of representing such a @tech{universe}, - we choose to introduce @tech{Universe} as a list of @tech{world}s, and we + we choose to introduce @tech{UniverseState} as a list of @tech{world}s, and we interpret non-empty lists as those where the first @tech{world} is active and the remainder are the passive @tech{world}s. As for the two possible events, @itemize[ @@ -1249,7 +1249,7 @@ The preceding subsection dictates that our server program starts like this: [schemeblock ;; teachpack: universe.ss -;; Universe is [Listof world?] +;; UniverseState is [Listof world?] ;; StopMessage is 'done. ;; GoMessage is 'it-is-your-turn. ]) @@ -1264,13 +1264,14 @@ The preceding subsection dictates that our server program starts like this: @(begin #reader scribble/comment-reader [schemeblock -;; Result is (make-bundle Universe (list (make-mail world? GoMessage))) +;; Result is +;; (make-bundle UniverseState (list (make-mail world? GoMessage))) -;; Universe world? -> Result +;; UniverseState world? -> Result ;; add world w to the universe, when server is in state u (define (add-world u w) ...) -;; Universe world? StopMessage -> Result +;; UniverseState world? StopMessage -> Result ;; world w sent message m when server is in state u (define (switch u w m) ...) ]) @@ -1279,7 +1280,7 @@ Although we could have re-used the generic contracts from this documentation, we also know from our protocol that our server sends a message to exactly one world. For this reason, both functions return the same kind of result: a bundle that contains the new state of the server -(@tech{Universe}) and a list that contains a single mail. These contracts +(@tech{UniverseState}) and a list that contains a single mail. These contracts are just refinements of the generic ones. (A type-oriented programmer would say that the contracts here are subtypes of the generic ones.) @@ -1311,7 +1312,7 @@ protocol. The protocol tells us that @emph{add-world} just adds the given @emph{world} structure---recall that this a data representation of the -actual @tech{world} program---to the @tech{Universe} and then sends a +actual @tech{world} program---to the @tech{UniverseState} and then sends a message to the first world on this list to get things going: @(begin @@ -1338,11 +1339,12 @@ Similarly, the protocol says that when @emph{switch} is invoked because a [schemeblock (define (switch univ wrld m) (local ((define univ* (append (rest univ) (list (first univ))))) - (make-bundle univ* (list (make-mail (first univ*) 'it-is-your-turn))))) + (make-bundle univ* + (list (make-mail (first univ*) 'it-is-your-turn))))) ]) As before, appending the first world to the end of the list guarantees - that there is at least this one world on the next @tech{Universe} + that there is at least this one world on the next @tech{UniverseState} (state). It is therefore acceptable to create a mail for this world. Exercise: The function definition simply assumes that @emph{wrld} is @@ -1371,31 +1373,35 @@ The final step is to design the ball @tech{world}. Recall that each world (schemeblock ;; teachpack: universe.ss -;; World is one of +;; WorldState is one of: ;; -- Number %% representing the @emph{y} coordinate ;; -- @scheme['resting] (define WORLD0 'resting) + +;; A WorldResult is one of: +;; -- WorldState +;; -- (make-package WorldState StopMessage) )) The definition says that initially a @tech{world} is passive. -The communication protocol and the refined data definition of @tech{World} +The communication protocol and the refined data definition of @tech{WorldState} imply a number of contract and purpose statements: @(begin #reader scribble/comment-reader (schemeblock -;; World GoMessage -> World or (make-package World StopMessage) +;; WorldState GoMessage -> WorldResult ;; make sure the ball is moving (define (receive w n) ...) -;; World -> World or (make-package World StopMessage) +;; WorldState -> WorldResult ;; move this ball upwards for each clock tick ;; or stay @scheme['resting] (define (move w) ...) -;; World -> Scene +;; WorldState -> Scene ;; render the world as a scene (define (render w) ...) )) @@ -1403,7 +1409,7 @@ The communication protocol and the refined data definition of @tech{World} Let's design one function at a time, starting with @emph{receive}. Since the protocol doesn't spell out what @emph{receive} is to compute, let's create a good set of functional examples, exploiting the structure of the - data organization of @tech{World}: + data organization of @tech{WorldState}: @(begin #reader scribble/comment-reader @@ -1458,7 +1464,7 @@ the scene every time @scheme['it-is-your-turn] is received. Design this function @(begin #reader scribble/comment-reader (schemeblock -; World -> World or @scheme[(make-package 'resting 'done)] +; WorldState -> WorldState or @scheme[(make-package 'resting 'done)] ; move the ball if it is flying (check-expect (move 'resting) 'resting) @@ -1498,7 +1504,7 @@ Finally, here is the third function, which renders the state as a scene: @(begin #reader scribble/comment-reader (schemeblock -; World -> Scene +; WorldState -> Scene ; render the state of the world as a scene (check-expect (render HEIGHT) (place-image BALL 50 HEIGHT MT)) @@ -1520,7 +1526,7 @@ Finally, here is the third function, which renders the state as a scene: @(begin #reader scribble/comment-reader (schemeblock -; String -> (World -> Scene) +; String -> (WorldState -> Scene) ; render the state of the world as a scene (check-expect @@ -1545,7 +1551,7 @@ Finally, here is the third function, which renders the state as a scene: #reader scribble/comment-reader (schemeblock -; String -> World +; String -> WorldState ; create and hook up a world with the @scheme[LOCALHOST] server (define (create-world name) (big-bang WORLD0 From c58702123f2966caf2c34ac82baca7fe5d7e2f1b Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Thu, 8 Jan 2009 23:37:55 +0000 Subject: [PATCH 03/38] message order svn: r13042 --- .../2htdp/scribblings/universe.scrbl | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index 14997b1957..d6d635c6f1 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -1110,13 +1110,20 @@ The first step in designing a @tech{universe} is to understand the throughout a system. We know that the @tech{universe} doesn't exist until the server starts and the @tech{world}s are joining. Because of the nature of computers and networks, however, we may assume little else. Our network - connections ensure that if some @tech{world} sends two messages in some - order, they arrive in the same order at the server. In contrast, it is - generally impossible to ensure whether one world joins before another or - whether a message from one world gets to the server before another world's - message gets there. It is therefore the designer's task to establish a - protocol that enforces a certain order onto a universe and this activity - is called @emph{protocol design}. + connections ensure that if some @tech{world} or the @tech{server} sends + two messages to the @emph{same} place in some order, they arrive in the + same order (if they arrive at all). In contrast, if two distinct + @tech{world} programs send one message each, the network does not + guarantee the order of arrival at the server; similarly, if the + @tech{server} is asked to send some messages to several distinct + @tech{world} programs, they may arrive at those worlds in the order sent + or in the some other order. In the same vein, it is impossible to ensure + that one world joins before another. Worst, when someone removes the + connection (cable, wireless) between a computer that runs a @tech{world} + program and the rest of the network or if some network cable is cut, + messages don't go anywhere. Due to this vagaries, it is therefore the + designer's task to establish a protocol that enforces a certain order onto + a universe and this activity is called @emph{protocol design}. From the perspective of the @tech{universe}, the design of a protocol is about the design of data representations for tracking universe information From 71d4c900df52d748eac03178cc215a4dfc8455c2 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Fri, 9 Jan 2009 08:50:13 +0000 Subject: [PATCH 04/38] Welcome to a new PLT day. svn: r13045 --- collects/repos-time-stamp/stamp.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collects/repos-time-stamp/stamp.ss b/collects/repos-time-stamp/stamp.ss index c487735d3b..e2ca27e5d8 100644 --- a/collects/repos-time-stamp/stamp.ss +++ b/collects/repos-time-stamp/stamp.ss @@ -1 +1 @@ -#lang scheme/base (provide stamp) (define stamp "8jan2009") +#lang scheme/base (provide stamp) (define stamp "9jan2009") From 3f44589c69e82d8df1122f4f752301b5590ac139 Mon Sep 17 00:00:00 2001 From: Casey Klein Date: Fri, 9 Jan 2009 10:23:14 +0000 Subject: [PATCH 05/38] Changed the interface for collecting reduction relation coverage. svn: r13046 --- collects/redex/private/reduction-semantics.ss | 35 +++++++++------ collects/redex/private/struct.ss | 9 ++-- collects/redex/private/tl-test.ss | 43 +++++++++---------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/collects/redex/private/reduction-semantics.ss b/collects/redex/private/reduction-semantics.ss index c077fcf151..dbd0e873dc 100644 --- a/collects/redex/private/reduction-semantics.ss +++ b/collects/redex/private/reduction-semantics.ss @@ -753,22 +753,32 @@ acc)))])) other-matches))))) (rewrite-proc-name child-make-proc) - (subst lhs-frm-id (rewrite-proc-lhs child-make-proc) rhs-from))) + (subst lhs-frm-id (rewrite-proc-lhs child-make-proc) rhs-from) + (rewrite-proc-id child-make-proc))) (define relation-coverage (make-parameter #f)) -(define-struct covered-case (name apps) #:inspector (make-inspector)) +(define (cover-case id name cov) + (hash-update! (coverage-unwrap cov) id + (λ (c) (cons (car c) (add1 (cdr c)))) + (λ () (raise-user-error + 'relation-coverage + "coverage structure not initilized for this relation")))) -(define (apply-case c) - (struct-copy covered-case c [apps (add1 (covered-case-apps c))])) +(define (covered-cases cov) + (hash-map (coverage-unwrap cov) (λ (k v) v))) -(define (cover-case id name relation-coverage) - (hash-update! relation-coverage id apply-case (make-covered-case name 0))) +(define-struct coverage (unwrap)) -(define (covered-cases relation-coverage) - (hash-map relation-coverage (λ (k v) v))) +(define (fresh-coverage relation) + (let ([h (make-hasheq)]) + (for-each + (λ (rwp) + (hash-set! h (rewrite-proc-id rwp) (cons (or (rewrite-proc-name rwp) "unnamed") 0))) + (reduction-relation-make-procs relation)) + (make-coverage h))) -(define fresh-coverage make-hasheq) +;(define fresh-coverage (compose make-coverage make-hasheq)) (define (do-leaf-match name pat w/extras proc) (let ([case-id (gensym)]) @@ -788,7 +798,8 @@ other-matches) other-matches))))) name - w/extras))) + w/extras + case-id))) (define-syntax (test-match stx) (syntax-case stx () @@ -1835,5 +1846,5 @@ (provide relation-coverage covered-cases - fresh-coverage - (struct-out covered-case)) \ No newline at end of file + (rename-out [fresh-coverage make-coverage]) + coverage?) \ No newline at end of file diff --git a/collects/redex/private/struct.ss b/collects/redex/private/struct.ss index 27cba96f84..f0c4e9d9f1 100644 --- a/collects/redex/private/struct.ss +++ b/collects/redex/private/struct.ss @@ -9,7 +9,7 @@ build-reduction-relation reduction-relation? empty-reduction-relation - make-rewrite-proc rewrite-proc? rewrite-proc-name rewrite-proc-lhs + make-rewrite-proc rewrite-proc? rewrite-proc-name rewrite-proc-lhs rewrite-proc-id (struct-out rule-pict)) (define-struct rule-pict (arrow lhs rhs label side-conditions fresh-vars pattern-binds)) @@ -20,14 +20,15 @@ ;; we want to avoid doing it multiple times, so it is cached in a reduction-relation struct -(define-values (make-rewrite-proc rewrite-proc? rewrite-proc-name rewrite-proc-lhs) +(define-values (make-rewrite-proc rewrite-proc? rewrite-proc-name rewrite-proc-lhs rewrite-proc-id) (let () (define-values (type constructor predicate accessor mutator) - (make-struct-type 'rewrite-proc #f 3 0 #f '() #f 0)) + (make-struct-type 'rewrite-proc #f 4 0 #f '() #f 0)) (values constructor predicate (make-struct-field-accessor accessor 1 'name) - (make-struct-field-accessor accessor 2 'lhs)))) + (make-struct-field-accessor accessor 2 'lhs) + (make-struct-field-accessor accessor 3 'id)))) ;; lang : compiled-language ;; make-procs = (listof (compiled-lang -> proc)) diff --git a/collects/redex/private/tl-test.ss b/collects/redex/private/tl-test.ss index af8919fc49..a8c52a7afd 100644 --- a/collects/redex/private/tl-test.ss +++ b/collects/redex/private/tl-test.ss @@ -1,8 +1,7 @@ (module tl-test mzscheme (require "../reduction-semantics.ss" (only "reduction-semantics.ss" - relation-coverage fresh-coverage covered-cases - make-covered-case covered-case-name) + relation-coverage make-coverage covered-cases) "test-util.ss" (only "matcher.ss" make-bindings make-bind) scheme/match @@ -1226,32 +1225,30 @@ [else #f]) #t)) - (let ([R (reduction-relation - empty-language - (--> number (q ,(add1 (term number))) - (side-condition (odd? (term number))) - side-condition) - (--> 1 4 - one) - (==> 2 t - shortcut) - with - [(--> (q a) b) - (==> a b)])] - [c (fresh-coverage)]) + (let* ([R (reduction-relation + empty-language + (--> number (q ,(add1 (term number))) + (side-condition (odd? (term number))) + side-condition) + (--> 1 4) + (==> 2 t + shortcut) + with + [(--> (q a) b) + (==> a b)])] + [c (make-coverage R)] + [< (λ (c d) (string Date: Fri, 9 Jan 2009 19:55:48 +0000 Subject: [PATCH 06/38] small bug in new world code svn: r13049 --- collects/2htdp/private/world.ss | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/collects/2htdp/private/world.ss b/collects/2htdp/private/world.ss index 2270aafeb1..b45eaa0dd9 100644 --- a/collects/2htdp/private/world.ss +++ b/collects/2htdp/private/world.ss @@ -293,16 +293,17 @@ (inherit-field world0 tick key mouse rec draw rate width height) (inherit show callback-stop!) - ;; Frame Custodian -> (-> Void) + ;; Frame Custodian ->* (-> Void) (-> Void) ;; adds the stop animation and image creation button, ;; whose callbacks runs as a thread in the custodian - ;; provide a function for switching button enabling (define/augment (create-frame frm play-back-custodian) (define p (new horizontal-pane% [parent frm][alignment '(center center)])) (define (switch) (send stop-button enable #f) (send image-button enable #t)) - (define (stop) (send stop-button enable #f)) + (define (stop) + (send image-button enable #f) + (send stop-button enable #f)) (define-syntax-rule (btn l a y ...) (new button% [parent p] [label l] [style '(border)] [callback (lambda a y ...)])) From a58010fd0ddb54ff8c8de5869b2c0f9a18eddaf3 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 9 Jan 2009 21:00:50 +0000 Subject: [PATCH 07/38] scheme/class: fix local member names to provide an better message on misuse, and to declare itself as an expression form svn: r13050 --- collects/scheme/private/classidmap.ss | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/collects/scheme/private/classidmap.ss b/collects/scheme/private/classidmap.ss index b88fb8b098..ba0d93e6eb 100644 --- a/collects/scheme/private/classidmap.ss +++ b/collects/scheme/private/classidmap.ss @@ -291,7 +291,14 @@ [else (reverse (cons args accum))]))) - (define-struct private-name (orig-id gen-id)) + (define-struct private-name (orig-id gen-id) + #:property prop:procedure (lambda (self stx) + (if (not (eq? (syntax-local-context) 'expression)) + #`(#%expression #,stx) + (raise-syntax-error + #f + "unbound local member name" + stx)))) (define (do-localize orig-id validate-local-member-stx) (let loop ([id orig-id]) From df99b2e1c4f43f4891e2b81729ca1527ffb1b8f0 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 9 Jan 2009 21:01:09 +0000 Subject: [PATCH 08/38] remove obsolete text svn: r13051 --- collects/compiler/compiler-unit.ss | 3 --- 1 file changed, 3 deletions(-) diff --git a/collects/compiler/compiler-unit.ss b/collects/compiler/compiler-unit.ss index b46c4ae3c3..57fc93c465 100644 --- a/collects/compiler/compiler-unit.ss +++ b/collects/compiler/compiler-unit.ss @@ -5,9 +5,6 @@ ;; by dynamically linking to code supplied by the MzLib, dynext, and ;; compiler collections. -;; The Scheme->C compiler is loaded as either sploadr.ss (link in -;; real MrSpidey) or loadr.ss (link in trivial MrSpidey stubs). - #lang scheme/base (require scheme/unit From 1edd3544d70cc002fad9bf74b9137a070769ae7a Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 9 Jan 2009 21:30:43 +0000 Subject: [PATCH 09/38] fix scribble to place different images with the same source name in different destination filenames svn: r13052 --- collects/scribble/base-render.ss | 81 +++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/collects/scribble/base-render.ss b/collects/scribble/base-render.ss index 153ee41e5a..0279f549ab 100644 --- a/collects/scribble/base-render.ss +++ b/collects/scribble/base-render.ss @@ -405,33 +405,70 @@ ;; ---------------------------------------- + (define copied-srcs (make-hash)) + (define copied-dests (make-hash)) + (define/public (install-file fn) (if refer-to-existing-files (if (string? fn) (string->path fn) fn) - (let ([src-dir (path-only fn)] - [dest-dir (get-dest-directory #t)] - [fn (file-name-from-path fn)]) - (let ([src-file (build-path (or src-dir (current-directory)) fn)] - [dest-file (build-path (or dest-dir (current-directory)) fn)]) - (unless (and (file-exists? dest-file) - (call-with-input-file* - src-file - (lambda (src) - (call-with-input-file* - dest-file - (lambda (dest) - (or (equal? (port-file-identity src) - (port-file-identity dest)) - (let loop () - (let ([s (read-bytes 4096 src)] - [d (read-bytes 4096 dest)]) - (and (equal? s d) - (or (eof-object? s) (loop))))))))))) - (when (file-exists? dest-file) (delete-file dest-file)) - (copy-file src-file dest-file)) - (path->string fn))))) + (let ([normalized (normal-case-path (simplify-path (path->complete-path fn)))]) + (or (hash-ref copied-srcs normalized #f) + (let ([src-dir (path-only fn)] + [dest-dir (get-dest-directory #t)] + [fn (file-name-from-path fn)]) + (let ([src-file (build-path (or src-dir (current-directory)) fn)] + [dest-file (build-path (or dest-dir (current-directory)) fn)] + [next-file-name (lambda (dest) + (let-values ([(base name dir?) (split-path dest)]) + (build-path + base + (let ([s (path-element->string (path-replace-suffix name #""))]) + (let ([n (regexp-match #rx"^(.*)_([0-9]+)$" s)]) + (format "~a_~a~a" + (if n (cadr n) s) + (if n (add1 (string->number (caddr n))) 2) + (let ([ext (filename-extension name)]) + (if ext + (bytes-append #"." ext) + ""))))))))]) + (let-values ([(dest-file normalized-dest-file) + (let loop ([dest-file dest-file]) + (let ([normalized-dest-file + (normal-case-path (simplify-path (path->complete-path dest-file)))]) + (if (file-exists? dest-file) + (cond + [(call-with-input-file* + src-file + (lambda (src) + (call-with-input-file* + dest-file + (lambda (dest) + (or (equal? (port-file-identity src) + (port-file-identity dest)) + (let loop () + (let ([s (read-bytes 4096 src)] + [d (read-bytes 4096 dest)]) + (and (equal? s d) + (or (eof-object? s) (loop)))))))))) + ;; same content at that destination + (values dest-file normalized-dest-file)] + [(hash-ref copied-dests normalized-dest-file #f) + ;; need a different file + (loop (next-file-name dest-file))] + [else + ;; replace the file + (delete-file dest-file) + (values dest-file normalized-dest-file)]) + ;; new file + (values dest-file normalized-dest-file))))]) + (unless (file-exists? dest-file) + (copy-file src-file dest-file)) + (hash-set! copied-dests normalized-dest-file #t) + (let ([result (path->string (file-name-from-path dest-file))]) + (hash-set! copied-srcs normalized result) + result)))))))) ;; ---------------------------------------- From 65fad6047df0707f6920a9d9fbd5e7ca5fe0d37b Mon Sep 17 00:00:00 2001 From: Casey Klein Date: Fri, 9 Jan 2009 21:53:53 +0000 Subject: [PATCH 10/38] Exported and documented the term generator's public interface. svn: r13053 --- collects/redex/private/rg-test.ss | 60 +++++++-------- collects/redex/private/rg.ss | 17 +++-- collects/redex/private/tl-test.ss | 2 - collects/redex/redex.scrbl | 102 +++++++++++++++++++++++++- collects/redex/reduction-semantics.ss | 15 +++- 5 files changed, 152 insertions(+), 44 deletions(-) diff --git a/collects/redex/private/rg-test.ss b/collects/redex/private/rg-test.ss index a46e922206..08393a1a2d 100644 --- a/collects/redex/private/rg-test.ss +++ b/collects/redex/private/rg-test.ss @@ -504,62 +504,62 @@ (get-output-string p) (close-output-port p)))) -;; check +;; redex-check (let () (define-language lang (d 5) (e e 4) (n number)) - (test (current-output (λ () (check lang d #f))) + (test (current-output (λ () (redex-check lang d #f))) "counterexample found after 1 attempts:\n5\n") - (test (check lang d #t) #t) - (test (check lang (d e) (and (eq? (term d) 5) (eq? (term e) 4)) #:attempts 2) #t) - (test (check lang (d ...) (zero? (modulo (foldl + 0 (term (d ...))) 5)) #:attempts 2) #t) - (test (current-output (λ () (check lang (d e) #f))) + (test (redex-check lang d #t) #t) + (test (redex-check lang (d e) (and (eq? (term d) 5) (eq? (term e) 4)) #:attempts 2) #t) + (test (redex-check lang (d ...) (zero? (modulo (foldl + 0 (term (d ...))) 5)) #:attempts 2) #t) + (test (current-output (λ () (redex-check lang (d e) #f))) "counterexample found after 1 attempts:\n(5 4)\n") - (test (current-output (λ () (check lang d (error 'pred-raised)))) + (test (current-output (λ () (redex-check lang d (error 'pred-raised)))) "counterexample found after 1 attempts:\n5\n") (test (parameterize ([check-randomness (make-random 0 0)]) - (check lang n (eq? 42 (term n)) - #:attempts 1 - #:source (reduction-relation lang (--> 42 x)))) + (redex-check lang n (eq? 42 (term n)) + #:attempts 1 + #:source (reduction-relation lang (--> 42 x)))) #t) (test (current-output (λ () (parameterize ([check-randomness (make-random 0 0)]) - (check lang n (eq? 42 (term n)) - #:attempts 1 - #:source (reduction-relation lang (--> 0 x z)))))) + (redex-check lang n (eq? 42 (term n)) + #:attempts 1 + #:source (reduction-relation lang (--> 0 x z)))))) "counterexample found (z) after 1 attempts:\n0\n") (test (current-output (λ () (parameterize ([check-randomness (make-random 1)]) - (check lang d (eq? 42 (term n)) - #:attempts 1 - #:source (reduction-relation lang (--> 0 x z)))))) + (redex-check lang d (eq? 42 (term n)) + #:attempts 1 + #:source (reduction-relation lang (--> 0 x z)))))) "counterexample found after 1 attempts:\n5\n") (test (let ([r (reduction-relation lang (--> 0 x z))]) - (check lang n (number? (term n)) - #:attempts 10 - #:source r)) + (redex-check lang n (number? (term n)) + #:attempts 10 + #:source r)) #t) (let () (define-metafunction lang [(mf 0) 0] [(mf 42) 0]) (test (parameterize ([check-randomness (make-random 0 1)]) - (check lang (n) (eq? 42 (term n)) - #:attempts 1 - #:source mf)) + (redex-check lang (n) (eq? 42 (term n)) + #:attempts 1 + #:source mf)) #t)) (let () (define-language L) (test (with-handlers ([exn:fail? exn-message]) - (check lang any #t #:source (reduction-relation L (--> 1 1)))) + (redex-check lang any #t #:source (reduction-relation L (--> 1 1)))) #rx"language for secondary source")) (let () (test (with-handlers ([exn:fail? exn-message]) - (check lang n #t #:source (reduction-relation lang (--> x 1)))) + (redex-check lang n #t #:source (reduction-relation lang (--> x 1)))) #rx"x does not match n")) (let ([stx-err (λ (stx) @@ -570,15 +570,15 @@ (eval '(require "../reduction-semantics.ss" "rg.ss")) (eval '(define-language empty)) - (test (stx-err '(check empty any #t #:typo 3)) - #rx"check: bad keyword syntax") - (test (stx-err '(check empty any #t #:attempts 3 #:attempts 4)) + (test (stx-err '(redex-check empty any #t #:typo 3)) + #rx"redex-check: bad keyword syntax") + (test (stx-err '(redex-check empty any #t #:attempts 3 #:attempts 4)) #rx"bad keyword syntax") - (test (stx-err '(check empty any #t #:attempts)) + (test (stx-err '(redex-check empty any #t #:attempts)) #rx"bad keyword syntax") - (test (stx-err '(check empty any #t #:attempts 3 4)) + (test (stx-err '(redex-check empty any #t #:attempts 3 4)) #rx"bad keyword syntax") - (test (stx-err '(check empty any #t #:source #:attempts)) + (test (stx-err '(redex-check empty any #t #:source #:attempts)) #rx"bad keyword syntax")))) ;; check-metafunction-contract diff --git a/collects/redex/private/rg.ss b/collects/redex/private/rg.ss index 6174f0ac82..3b700c2424 100644 --- a/collects/redex/private/rg.ss +++ b/collects/redex/private/rg.ss @@ -655,11 +655,12 @@ To do a better job of not generating programs with free variables, (define check-randomness (make-parameter random)) -(define-syntax (check stx) +(define-syntax (redex-check stx) (syntax-case stx () [(_ lang pat property . kw-args) (let-values ([(names names/ellipses) - (extract-names (language-id-nts #'lang 'check) 'check #t #'pat)] + (extract-names (language-id-nts #'lang 'redex-check) + 'redex-check #t #'pat)] [(attempts-stx source-stx) (let loop ([args (syntax kw-args)] [attempts #f] @@ -678,9 +679,9 @@ To do a better job of not generating programs with free variables, [attempts (or attempts-stx #'default-check-attempts)]) (quasisyntax/loc stx (let ([att attempts]) - (assert-nat 'check att) + (assert-nat 'redex-check att) (or (check-property - (cons (list #,(term-generator #'lang #'pat #'random-decisions 'check) #f) + (cons (list #,(term-generator #'lang #'pat #'random-decisions 'redex-check) #f) (let ([lang-gen (generate lang (random-decisions lang))]) #,(if (not source-stx) #'null @@ -694,16 +695,16 @@ To do a better job of not generating programs with free variables, [else #`(let ([r #,source-stx]) (unless (reduction-relation? r) - (raise-type-error 'check "reduction-relation" r)) + (raise-type-error 'redex-check "reduction-relation" r)) (values (map rewrite-proc-lhs (reduction-relation-make-procs r)) (reduction-relation-srcs r) (reduction-relation-lang r)))])]) (unless (eq? src-lang lang) - (error 'check "language for secondary source must match primary pattern's language")) + (error 'redex-check "language for secondary source must match primary pattern's language")) (zip (map lang-gen pats) srcs))))) #,(and source-stx #'(test-match lang pat)) - (λ (generated) (error 'check "~s does not match ~s" generated 'pat)) + (λ (generated) (error 'redex-check "~s does not match ~s" generated 'pat)) (λ (_ bindings) (term-let ([name/ellipses (lookup-binding bindings 'name)] ...) property)) @@ -842,7 +843,7 @@ To do a better job of not generating programs with free variables, (define generation-decisions (make-parameter random-decisions)) (provide pick-from-list pick-var min-prods decisions^ pick-sequence-length - is-nt? pick-char random-string pick-string check nt-by-name + is-nt? pick-char random-string pick-string redex-check nt-by-name pick-nt unique-chars pick-any sexp generate-term parse-pattern class-reassignments reassign-classes unparse-pattern (struct-out ellipsis) (struct-out mismatch) (struct-out class) diff --git a/collects/redex/private/tl-test.ss b/collects/redex/private/tl-test.ss index a8c52a7afd..78aae31d07 100644 --- a/collects/redex/private/tl-test.ss +++ b/collects/redex/private/tl-test.ss @@ -1,7 +1,5 @@ (module tl-test mzscheme (require "../reduction-semantics.ss" - (only "reduction-semantics.ss" - relation-coverage make-coverage covered-cases) "test-util.ss" (only "matcher.ss" make-bindings make-bind) scheme/match diff --git a/collects/redex/redex.scrbl b/collects/redex/redex.scrbl index 0335ffc8cd..1d9f533dde 100644 --- a/collects/redex/redex.scrbl +++ b/collects/redex/redex.scrbl @@ -47,9 +47,12 @@ #'((tech "term") args ...)] [x (identifier? #'x) #'(tech "term")])) +@(define redex-eval (make-base-eval)) +@(interaction-eval #:eval redex-eval (require redex/reduction-semantics)) + @title{@bold{Redex}: Debugging Operational Semantics} -@author["Robert Bruce Findler"] +@author["Robert Bruce Findler" "Casey Klein"] PLT Redex consists of a domain-specific language for specifying reduction semantics, plus a suite of tools for working with the @@ -982,6 +985,103 @@ counters so that next time this function is called, it prints the test results for the next round of tests. } +@defproc[(make-coverage [r reduction-relation?]) coverage?]{ +Constructs a structure to contain the per-case test coverage of +the relation @scheme[r]. Use with @scheme[relation-coverage] +and @scheme[covered-cases]. +} + +@defproc[(coverage? [v any/c]) boolean?]{ +Returns @scheme[#t] for a value produced by @scheme[make-coverage] +and @scheme[#f] for any other.} + +@defparam[relation-coverage c (or/c false/c coverage?)]{ +When @scheme[c] is a @scheme[coverage] structure, rather than +@scheme[#f] (the default), procedures such as +@scheme[apply-reduction-relation], @scheme[traces], etc. count +the number applications of each case of the +@scheme[reduction-relation], storing the results in @scheme[c]. +} + +@defproc[(covered-cases + [c coverage?]) + (listof (cons/c string? natural-number/c))]{ +Extracts the coverage information recorded in @scheme[c], producing +an association list mapping names to application counts.} + +@examples[ +#:eval redex-eval + (define-language addition + (e (+ number ...))) + (define reduce + (reduction-relation + addition + (--> (+) 0 "zero") + (--> (+ number) number) + (--> (+ number_1 number_2 number ...) + (+ ,(+ (term number_1) (term number_2)) + number ...) + "add"))) + (let ([coverage (make-coverage reduce)]) + (parameterize ([relation-coverage coverage]) + (apply-reduction-relation* reduce (term (+ 1 2 3))) + (covered-cases coverage)))] + +@defform*[[(generate-term language #, @|ttpattern| size-exp) + (generate-term language #, @|ttpattern| size-exp #:attempt attempt-num-expr)] + #:contracts ([size-expr natural-number/c] + [attempt-num-expr natural-number/c])]{ +Generates a random term matching @scheme[pattern] (in the given language). + +The argument @scheme[size-expr] bounds the height of the generated term +(measured as the height of the derivation tree used to produce +the term). + +The optional keyword argument @scheme[attempt-num-expr] +(default @scheme[1]) provides coarse grained control over the random +decisions made during generation (e.g., the expected length of +@pattech[pattern-sequence]s increases with @scheme[attempt-num-expr]).} + +@defform/subs[(check language #, @|ttpattern| property-expr kw-arg ...) + ([kw-arg (code:line #:attempts attempts-expr) + (code:line #:source metafunction) + (code:line #:source relation-expr)]) + #:contracts ([property-expr any/c] + [attempts-expr natural-number/c] + [relation-expr reduction-relation?])]{ +Searches for a counterexample to @scheme[property-expr], interpreted +as a predicate universally quantified over its free +@pattech[term]-variables. @scheme[check] chooses substitutions for +these free @pattech[term]-variables by generating random terms matching +@scheme[pattern] and extracting the sub-terms bound by the +@pattech[names] and non-terminals in @scheme[pattern]. + +@scheme[check] generates at most @scheme[attempts-expr] (default @scheme[100]) +random terms in its search. The size and complexity of terms it generates +gradually increases with each failed attempt. + +When the optional @scheme[#:source] argument is present, @scheme[check] +generates @math{10%} of its terms by randomly choosing a pattern from the +left-hand sides the definition of the supplied metafunction or relation. +@scheme[check] raises an exception if a term generated from an alternate +pattern does not match the @scheme[pattern].} + +@defproc[(check-reduction-relation + [relation reduction-relation?] + [property (-> any/c any/c)] + [#:attempts attempts natural-number/c 100]) + (or/c true/c void?)]{ +Tests a @scheme[relation] as follows: for each case of @scheme[relation], +@scheme[check-reduction-relation] generates @scheme[attempts] random +terms that match that case's left-hand side and applies @scheme[property] +to each random term.} + +@defform*[[(check-metafunction metafunction property) + (check-metafunction metafunction property #:attempts attempts)] + #:contracts ([property (-> any/c any/c)] + [attempts natural-number/c])]{ +Like @scheme[check-reduction-relation] but for metafunctions.} + @deftech{Debugging PLT Redex Programs} It is easy to write grammars and reduction rules that are diff --git a/collects/redex/reduction-semantics.ss b/collects/redex/reduction-semantics.ss index dfbd96b498..68c4c14a93 100644 --- a/collects/redex/reduction-semantics.ss +++ b/collects/redex/reduction-semantics.ss @@ -7,8 +7,6 @@ "private/rg.ss" "private/error.ss") -#;(provide (all-from-out "private/rg.ss")) - (provide exn:fail:redex?) ;; from error.ss (provide reduction-relation @@ -43,6 +41,11 @@ test-predicate test-results) +(provide redex-check + generate-term + check-metafunction + check-metafunction-contract) + (provide/contract [current-traced-metafunctions (parameter/c (or/c 'all (listof symbol?)))] [reduction-relation->rule-names (-> reduction-relation? (listof symbol?))] @@ -61,4 +64,10 @@ (-> bindings? symbol? any) (-> bindings? symbol? (-> any) any))] [variable-not-in (any/c symbol? . -> . symbol?)] - [variables-not-in (any/c (listof symbol?) . -> . (listof symbol?))]) + [variables-not-in (any/c (listof symbol?) . -> . (listof symbol?))] + [check-reduction-relation (->* (reduction-relation? (-> any/c any/c)) + (#:attempts natural-number/c) + (one-of/c #t (void)))] + [relation-coverage (parameter/c (or/c false/c coverage?))] + [make-coverage (-> reduction-relation? coverage?)] + [covered-cases (-> coverage? (listof (cons/c string? natural-number/c)))]) \ No newline at end of file From 38ef7d3c41b12256b0f35dbd3b83f6ddd0569fc1 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Fri, 9 Jan 2009 23:18:05 +0000 Subject: [PATCH 11/38] separated out the list of worlds from universeState svn: r13055 --- collects/2htdp/private/universe.ss | 39 ++++++++++++++++++------------ collects/2htdp/universe.ss | 22 ++++++++--------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/collects/2htdp/private/universe.ss b/collects/2htdp/private/universe.ss index 17b5263732..d170551ffa 100644 --- a/collects/2htdp/private/universe.ss +++ b/collects/2htdp/private/universe.ss @@ -31,7 +31,8 @@ (last-mixin (clock-mixin (class* object% (start-stop<%>) (inspect #f) (super-new) - (init-field ;; type Result = (make-bundle Universe [Listof Mail]) + (init-field ;; type Result + ; = (make-bundle [Listof World] Universe [Listof Mail]) universe0 ;; the initial state of the universe on-new ;; Universe World -> Result on-msg ;; Universe World Message -> Result @@ -56,8 +57,9 @@ (define (pname a ...) (define (handler e) (stop! e)) (with-handlers ([exn? handler]) - (define r (check-state-x-mail 'name (name universe a ...))) + (define r (check-state-x-mail 'name (name worlds universe a ...))) (define u (bundle-state r)) + (set! worlds (bundle-low r)) (set! universe u) (unless (boolean? to-string) (send gui add (to-string u))) (broadcast (bundle-mails r)))))) @@ -68,9 +70,9 @@ (def/cback private (pnew world) ppnew) - (define/private (ppnew uni p) + (define/private (ppnew low uni p) (world-send p 'okay) - (on-new uni p)) + (on-new low uni p)) (def/cback public (ptock) tick) @@ -80,8 +82,9 @@ (define/private (check-state-x-mail tag r) (with-handlers ((exn? (lambda (x) (stop! x)))) (define s (format "expected from ~a, given: " tag)) + (define f "(make-bundle [Listof World] Universe [Listof Mail]) ~a~e") (unless (bundle? r) - (error tag (format "(make-bundle Universe [Listof Mail]) ~a~e" s r))) + (error tag (format f s r))) r)) ;; ----------------------------------------------------------------------- @@ -109,7 +112,7 @@ (match next [(cons 'REGISTER info) (let* ([w (create-world in (second in-out) info)]) - (set! worlds (cons w worlds)) + ; (set! worlds (cons w worlds)) (pnew w) (send gui add (format "~a signed up" info)) (loop))] @@ -334,24 +337,30 @@ ; (provide - ;; type Bundle = (make-bundle Universe [Listof Mail]) + ;; type Bundle = (make-bundle [Listof World] Universe [Listof Mail]) ;; type Mail = (make-mail World S-expression) - make-bundle ;; Universe [Listof Mail] -> Bundle + make-bundle ;; [Listof World] Universe [Listof Mail] -> Bundle bundle? ;; is this a bundle? make-mail ;; World S-expression -> Mail mail? ;; is this a real mail? ) -(define-struct bundle (state mails) #:transparent) +(define-struct bundle (low state mails) #:transparent) (set! make-bundle (let ([make-bundle make-bundle]) - (lambda (state mails) - (check-arg 'make-bundle (list? mails) "list [of mails]" "second" mails) - (for-each (lambda (c) - (check-arg 'make-bundle (mail? c) "mail" "(elements of) second" c)) - mails) - (make-bundle state mails)))) + (lambda (low state mails) + (check-arg-list 'make-bundle low world? "world" "first") + (check-arg-list 'make-bundle mails mail? "mail" "third") + (make-bundle low state mails)))) + +;; Symbol Any (Any -> Boolean) String String -> Void +;; raise a TP exception if low is not a list of world? elements +(define (check-arg-list tag low world? msg rank) + (check-arg tag (list? low) (format "list [of ~as]" msg) rank low) + (for-each (lambda (c) + (check-arg tag (world? c) msg (format "(elements of) ~a" rank) c)) + low)) (define-struct mail (to content) #:transparent) diff --git a/collects/2htdp/universe.ss b/collects/2htdp/universe.ss index 33801da892..9d691c54b3 100644 --- a/collects/2htdp/universe.ss +++ b/collects/2htdp/universe.ss @@ -231,9 +231,9 @@ world1 ;; sample worlds world2 world3 - ;; type Bundle = (make-bundle Universe [Listof Mail]) + ;; type Bundle = (make-bundle [Listof World] Universe [Listof Mail]) ;; type Mail = (make-mail World S-expression) - make-bundle ;; Universe [Listof Mail] -> Bundle + make-bundle ;; [Listof World] Universe [Listof Mail] -> Bundle bundle? ;; is this a bundle? make-mail ;; World S-expression -> Mail mail? ;; is this a real mail? @@ -254,10 +254,10 @@ ;; in the console (define-keywords UniSpec - [on-new (function-with-arity 2)] - [on-msg (function-with-arity 3)] - [on-disconnect (function-with-arity 2)] - [to-string (function-with-arity 1)]) + [on-new (function-with-arity 3)] + [on-msg (function-with-arity 4)] + [on-disconnect (function-with-arity 3)] + [to-string (function-with-arity 2)]) (define-syntax (universe stx) (syntax-case stx () @@ -297,15 +297,15 @@ ;; (World World -> U) (U World Msg) -> U (define (universe2 create process) ;; UniState = '() | (list World) | Universe - ;; UniState World -> (cons UniState [Listof (list World S-expression)]) - (define (nu s p) + ;; [Listof World] UniState World -> (cons UniState [Listof (list World S-expression)]) + (define (nu s x p) (cond - [(null? s) (make-bundle (list p) '())] - [(not (pair? s)) (make-bundle s '())] + [(null? s) (make-bundle (list p) '* '())] + [(not (pair? s)) (make-bundle s '* '())] [(null? (rest s)) (create (first s) p)] [else (error 'create "a third world is signing up!")])) (universe '() (on-new nu) (on-msg process) #; - (on-tick (lambda (u) (printf "hello!\n") (list u)) 1))) \ No newline at end of file + (on-tick (lambda (u x) (printf "hello!\n") (list u)) 1))) \ No newline at end of file From a6f08c7399671e13bf9d6b8edd1da5f5bdc63ab4 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Fri, 9 Jan 2009 23:45:05 +0000 Subject: [PATCH 12/38] svn: r13056 --- .../2htdp/scribblings/universe.scrbl | 73 ++++++++++--------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index d6d635c6f1..044a6f82d8 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -915,6 +915,9 @@ Understanding the server's event handling functions demands three @defproc[(world=? [u world?][v world?]) boolean?]{ compares two @emph{world}s for equality.} +defproc[(world-name [w world?]) symbol?]{ + extracts the name from a @emph{world} structure.} + @defthing[world1 world?]{a world for testing your programs} @defthing[world2 world?]{another world for testing your programs} @defthing[world3 world?]{and a third one} @@ -941,14 +944,14 @@ structures: @item{Each event handler produces a @emph{bundle}, which is a structure that contains the @tech{server}'s state and a list of mails to other -worlds. Again, the teachpack provides only the predicate and a constructor: +worlds. Again, the teachpack provides only the predicate and a constructor: @defproc[(bundle? [x any/c]) boolean?]{ determines whether @scheme[x] is a @emph{bundle}.} -@defproc[(make-bundle [state any/c] [mails (listof mail?)]) bundle?]{ - creates a @emph{bundle} from a piece of data that represents a server - state and a list of mails.} +@defproc[(make-bundle [listof world?] [state any/c] [mails (listof mail?)]) bundle?]{ + creates a @emph{bundle} from a list of worlds, a piece of data that represents a server + state, and a list of mails.} } ] @@ -1001,7 +1004,6 @@ A @scheme[universe] expression starts a server. Visually it opens especially useful during the integration of the various pieces of a distributed program. - Now it is possible to explain the clauses in a @scheme[universe] server description. Two of them are mandatory: @@ -1010,22 +1012,26 @@ description. Two of them are mandatory: @item{ @defform[(on-new new-expr) #:contracts - ([new-expr (-> (unsyntax @tech{UniverseState}) world? - (cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{ + ([new-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? bundle?)])]{ tell DrScheme to call the function @scheme[new-expr] every time another world joins the - universe.}} + universe. The event handler is called on the current list of worlds and the + joining world. +}} @item{ @defform[(on-msg msg-expr) #:contracts - ([msg-expr (-> (unsyntax @tech{UniverseState}) world? sexp? - (cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{ + ([msg-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? sexp? bundle?)])]{ - tell DrScheme to apply @scheme[msg-expr] to the current state of the universe, the world - that sent the message, and the message itself. The handler must produce a state of the - universe and a list of mails.} + tell DrScheme to apply @scheme[msg-expr] to the list of currently + participating worlds, the current state of the universe, the world + that sent the message, and the message itself.} } ] + All event handlers produce a @emph{bundle}. The list of worlds in this + @emph{bundle} becomes the server's list of worlds; the state in the bundle + is safe-guarded by the server until the next event; and the mails are + broadcast as specified. The following picture provides a graphical overview of the server's workings. @@ -1039,36 +1045,37 @@ optional handlers: @item{ @defform/none[(on-tick tick-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)])]{ - tell DrScheme to apply @scheme[tick-expr] to the current state of the - universe. The handler is expected to produce a bundle of the new state of - the universe and a list of mails. + ([tick-expr (-> [listof world?] (unsyntax @tech{UniverseState}) bundle?)])]{ + tell DrScheme to apply @scheme[tick-expr] to the current list of + participating worlds and the current state of the + universe. } @defform/none[(on-tick tick-expr rate-expr) #:contracts - ([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)] + ([tick-expr (-> [listof world?] (unsyntax @tech{UniverseState}) bundle?)] [rate-expr natural-number/c])]{ tell DrScheme to apply @scheme[tick-expr] as above but use the specified clock tick rate instead of the default. } + } @item{ @defform[(on-disconnect dis-expr) #:contracts - ([dis-expr (-> (unsyntax @tech{UniverseState}) world? bundle?)])]{ + ([dis-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? bundle?)])]{ tell DrScheme to invoke @scheme[dis-expr] every time a participating - @tech{world} drops its connection to the server. The first argument is the - current state of the universe; the second one is the world that got - disconnected. + @tech{world} drops its connection to the server. The first two arguments + are the current list of participating worlds and the state of the + universe; the third one is the world that got disconnected. } } @item{ @defform[(to-string render-expr) #:contracts - ([render-expr (-> (unsyntax @tech{UniverseState}) string?)])]{ + ([render-expr (-> [listof world?] (unsyntax @tech{UniverseState}) string?)])]{ tell DrScheme to render the state of the universe after each event and to display this string in the universe console. } @@ -1179,18 +1186,18 @@ translates into the design of two functions with the following headers, @(begin #reader scribble/comment-reader (schemeblock -;; @tech{UniverseState} world? -> (make-bundle @tech{UniverseState} [Listof mail?]) +;; @tech{UniverseState} world? -> (make-bundle [Listof world?] @tech{UniverseState} [Listof mail?]) ;; create new @tech{UniverseState} when world w is joining the universe, ;; which is in state s; also send mails as needed (define (add-world s w) ...) -;; @tech{UniverseState} world? MsgW2U -> (make-bundle @tech{UniverseState} [Listof mail?]) +;; @tech{UniverseState} world? MsgW2U -> (make-bundle [Listof world?] @tech{UniverseState} [Listof mail?]) ;; create new @tech{UniverseState} when world w is sending message m ;; to universe in state s; also send mails as needed (define (process s p m) ...) )) -Note how both functions return a bundle. +Note how both functions return a @emph{bundle}. Finally, we must also decide how the messages affect the states of the worlds; which of their callback may send messages and when; and what to do @@ -1272,7 +1279,7 @@ The preceding subsection dictates that our server program starts like this: #reader scribble/comment-reader [schemeblock ;; Result is -;; (make-bundle UniverseState (list (make-mail world? GoMessage))) +;; (make-bundle [Listof world?] UniverseState (list (make-mail world? GoMessage))) ;; UniverseState world? -> Result ;; add world w to the universe, when server is in state u @@ -1298,14 +1305,14 @@ The second step of the design recipe calls for functional examples: [schemeblock ;; an obvious example for adding a world: (check-expect - (add-world '() world1) - (make-bundle (list world1) + (add-world '() '* world1) + (make-bundle (list world1) '* (list (make-mail world1 'it-is-your-turn)))) ;; an example for receiving a message from the active world: (check-expect - (switch (list world1 world2) world1 'it-is-your-turn) - (make-bundle (list world2 world1) + (switch (list world1 world2) '* world1 'it-is-your-turn) + (make-bundle (list world2 world1) '* (list (make-mail world2 'it-is-your-turn)))) ]) @@ -1327,7 +1334,7 @@ message to the first world on this list to get things going: [schemeblock (define (add-world univ wrld) (local ((define univ* (append univ (list wrld)))) - (make-bundle univ* + (make-bundle univ* '* (list (make-mail (first univ*) 'it-is-your-turn))))) ]) @@ -1346,7 +1353,7 @@ Similarly, the protocol says that when @emph{switch} is invoked because a [schemeblock (define (switch univ wrld m) (local ((define univ* (append (rest univ) (list (first univ))))) - (make-bundle univ* + (make-bundle univ* '* (list (make-mail (first univ*) 'it-is-your-turn))))) ]) From 630c8cbc54ef772c7cf1f3abe016afb40671f743 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Sat, 10 Jan 2009 08:50:20 +0000 Subject: [PATCH 13/38] Welcome to a new PLT day. svn: r13057 --- collects/repos-time-stamp/stamp.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collects/repos-time-stamp/stamp.ss b/collects/repos-time-stamp/stamp.ss index e2ca27e5d8..e988e9ee11 100644 --- a/collects/repos-time-stamp/stamp.ss +++ b/collects/repos-time-stamp/stamp.ss @@ -1 +1 @@ -#lang scheme/base (provide stamp) (define stamp "9jan2009") +#lang scheme/base (provide stamp) (define stamp "10jan2009") From 3a3ceb121b200e9a3df468fa1936eaaf9e9820f7 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Sat, 10 Jan 2009 18:17:45 +0000 Subject: [PATCH 14/38] added traces/ps and some code to make automatic layout of the graph possible (see #:layout in the docs for traces) svn: r13058 --- collects/redex/HISTORY | 7 ++ collects/redex/gui.ss | 38 ++++-- collects/redex/private/traces.ss | 202 ++++++++++++++++++++++++------- collects/redex/redex.scrbl | 78 +++++++++++- 4 files changed, 271 insertions(+), 54 deletions(-) diff --git a/collects/redex/HISTORY b/collects/redex/HISTORY index 1a51f5bcc3..cd8b96dea2 100644 --- a/collects/redex/HISTORY +++ b/collects/redex/HISTORY @@ -1,3 +1,10 @@ + - added more coloring arguments to traces: #:scheme-colors? + #:default-arrow-highlight-color, and #:default-arrow-color + + - added the #:layout argument to traces + + - added term-node-set-position! + - Added tracing to metafunctions (see current-traced-metafunctions) - added caching-enabled? parameter (changed how set-cache-size! diff --git a/collects/redex/gui.ss b/collects/redex/gui.ss index 7dfb5151c9..873595fc01 100644 --- a/collects/redex/gui.ss +++ b/collects/redex/gui.ss @@ -33,8 +33,21 @@ #:pred (or/c (any/c . -> . any) (any/c term-node? . -> . any)) #:pp pp-contract - #:colors (listof any/c)) + #:colors (listof (list/c string? string?)) + #:scheme-colors? boolean? + #:layout (-> any/c any/c)) any)] + [traces/ps (->* (reduction-relation? + any/c + (or/c path-string? path?)) + (#:multiple? + boolean? + #:pred (or/c (any/c . -> . any) + (any/c term-node? . -> . any)) + #:pp pp-contract + #:colors (listof any/c) + #:layout (-> any/c any/c)) + any)] [term-node? (-> any/c boolean?)] [term-node-parents (-> term-node? (listof term-node?))] @@ -45,6 +58,11 @@ (or/c string? (is-a?/c color%) false/c) void?)] [term-node-expr (-> term-node? any)] + [term-node-set-position! (-> term-node? real? real? void?)] + [term-node-x (-> term-node? real?)] + [term-node-y (-> term-node? real?)] + [term-node-width (-> term-node? real?)] + [term-node-height (-> term-node? real?)] [stepper (->* (reduction-relation? @@ -55,10 +73,16 @@ (->* (reduction-relation? (cons/c any/c (listof any/c))) (pp-contract) - void?)]) - - -(provide reduction-steps-cutoff initial-font-size initial-char-width - dark-pen-color light-pen-color dark-brush-color light-brush-color - dark-text-color light-text-color + void?)] + + [dark-pen-color (parameter/c (or/c string? (is-a?/c color%)))] + [light-pen-color (parameter/c (or/c string? (is-a?/c color%)))] + [dark-brush-color (parameter/c (or/c string? (is-a?/c color%)))] + [light-brush-color (parameter/c (or/c string? (is-a?/c color%)))] + [dark-text-color (parameter/c (or/c string? (is-a?/c color%)))] + [light-text-color (parameter/c (or/c string? (is-a?/c color%)))] + [initial-font-size (parameter/c number?)] + [initial-char-width (parameter/c number?)]) + +(provide reduction-steps-cutoff default-pretty-printer) \ No newline at end of file diff --git a/collects/redex/private/traces.ss b/collects/redex/private/traces.ss index 5efb8c074e..3bf3888bbd 100644 --- a/collects/redex/private/traces.ss +++ b/collects/redex/private/traces.ss @@ -30,15 +30,87 @@ (define (term-node-expr term-node) (send (term-node-snip term-node) get-expr)) (define (term-node-labels term-node) (send (term-node-snip term-node) get-one-step-labels)) (define (term-node-set-color! term-node r?) - (let loop ([snip (term-node-snip term-node)]) - (parameterize ([current-eventspace (send snip get-my-eventspace)]) - (queue-callback - (λ () - (send (term-node-snip term-node) set-bad r?)))))) + (snip/eventspace + (λ () + (send (term-node-snip term-node) set-bad r?)))) (define (term-node-set-red! term-node r?) (term-node-set-color! term-node (and r? "pink"))) +(define (term-node-set-position! term-node x y) + (snip/eventspace/ed + term-node + (λ (ed) + (when ed + (send ed move-to (term-node-snip term-node) x y))))) + +(define (term-node-width term-node) + (snip/eventspace/ed + term-node + (λ (ed) + (let ([lb (box 0)] + [rb (box 0)] + [snip (term-node-snip term-node)]) + (if (and (send ed get-snip-location snip lb #f #f) + (send ed get-snip-location snip rb #f #t)) + (- (unbox rb) (unbox lb)) + 0))))) + +(define (term-node-height term-node) + (snip/eventspace/ed + term-node + (λ (ed) + (let ([tb (box 0)] + [bb (box 0)] + [snip (term-node-snip term-node)]) + (if (and (send ed get-snip-location snip #f tb #f) + (send ed get-snip-location snip #f bb #t)) + (- (unbox bb) (unbox tb)) + 0))))) + +(define (term-node-x term-node) + (snip/eventspace/ed + term-node + (λ (ed) + (let ([xb (box 0)] + [snip (term-node-snip term-node)]) + (if (send ed get-snip-location snip xb #f #f) + (unbox xb) + 0))))) + +(define (term-node-y term-node) + (snip/eventspace/ed + term-node + (λ (ed) + (let ([yb (box 0)] + [snip (term-node-snip term-node)]) + (if (send ed get-snip-location snip yb #f #f) + (unbox yb) + 0))))) + +(define (snip/eventspace/ed term-node f) + (snip/eventspace + term-node + (λ () + (let* ([snip (term-node-snip term-node)] + [admin (send snip get-admin)]) + (f (and admin (send admin get-editor))))))) + + +(define (snip/eventspace term-node thunk) + (let* ([snip (term-node-snip term-node)] + [eventspace (send snip get-my-eventspace)]) + (cond + [(eq? (current-eventspace) eventspace) + (thunk)] + [else + (let ([c (make-channel)]) + (parameterize ([current-eventspace eventspace]) + (queue-callback + (λ () + (channel-put c (thunk))))) + (channel-get c))]))) + (define initial-font-size (make-parameter (send (send (send (editor:get-standard-style-list) @@ -51,7 +123,39 @@ (define x-spacing 15) (define y-spacing 15) -(define (traces reductions pre-exprs #:multiple? [multiple? #f] #:pred [pred (λ (x) #t)] #:pp [pp default-pretty-printer] #:colors [colors '()]) +(define (traces/ps reductions pre-exprs filename + #:multiple? [multiple? #f] + #:pred [pred (λ (x) #t)] + #:pp [pp default-pretty-printer] + #:default-arrow-colors [default-arrow-colors '()] + #:scheme-colors? [scheme-colors? #t] + #:colors [colors '()] + #:layout [layout void]) + (let ([graph-pb + (traces reductions pre-exprs + #:no-show-frame? #t + #:multiple? multiple? + #:pred pred + #:pp pp + #:default-arrow-colors default-arrow-colors + #:scheme-colors? scheme-colors? + #:colors colors + #:layout layout)] + [ps-setup (make-object ps-setup%)]) + (send ps-setup copy-from (current-ps-setup)) + (send ps-setup set-file filename) + (send ps-setup set-mode 'file) + (parameterize ([current-ps-setup ps-setup]) + (send graph-pb print #t #f 'postscript #f #f)))) + +(define (traces reductions pre-exprs + #:multiple? [multiple? #f] + #:pred [pred (λ (x) #t)] + #:pp [pp default-pretty-printer] + #:colors [colors '()] + #:scheme-colors? [scheme-colors? #t] + #:layout [layout void] + #:no-show-frame? [no-show-frame? #f]) (define exprs (if multiple? pre-exprs (list pre-exprs))) (define main-eventspace (current-eventspace)) (define saved-parameterization (current-parameterization)) @@ -146,14 +250,18 @@ (semaphore-wait s) ans))) + (define default-colors (list (dark-pen-color) (light-pen-color) + (dark-text-color) (light-text-color) + (dark-brush-color) (light-brush-color))) + ;; only changed on the reduction thread ;; frontier : (listof (is-a?/c graph-editor-snip%)) (define frontier (filter (λ (x) x) - (map (lambda (expr) (build-snip snip-cache #f expr pred pp - (dark-pen-color) (light-pen-color) - (dark-text-color) (light-text-color) #f)) + (map (lambda (expr) (apply build-snip + snip-cache #f expr pred pp #f scheme-colors? + default-colors)) exprs))) ;; set-font-size : number -> void @@ -172,38 +280,29 @@ (send snip shrink-down)) (loop (send snip next)))))) - ;; color-spec-list->color-scheme : (list (union string? #f)^4) -> (list string?^4) - ;; converts a list of user-specified colors (including false) into a list of color strings, filling in - ;; falses with the default colors - (define (color-spec-list->color-scheme l) - (map (λ (c d) (or c d)) - l - (list (dark-pen-color) (light-pen-color) (dark-text-color) (light-text-color)))) - + ;; fill-out : (listof X) (listof X) -> (listof X) + ;; produces a list whose length matches defaults but + (define (fill-out l defaults) + (let loop ([l l] + [default defaults]) + (cond + [(null? l) defaults] + [else + (cons (car l) (loop (cdr l) (cdr defaults)))]))) (define name->color-ht (let ((ht (make-hash))) (for-each (λ (c) - (hash-set! ht (car c) - (color-spec-list->color-scheme - (match (cdr c) - [`(,color) - (list color color (dark-text-color) (light-text-color))] - [`(,dark-arrow-color ,light-arrow-color) - (list dark-arrow-color light-arrow-color (dark-text-color) (light-text-color))] - [`(,dark-arrow-color ,light-arrow-color ,text-color) - (list dark-arrow-color light-arrow-color text-color text-color)] - [`(,_ ,_ ,_ ,_) - (cdr c)])))) + (hash-set! ht (car c) (fill-out (cdr c) default-colors))) colors) ht)) - ;; red->colors : string -> (values string string string string) + ;; red->colors : string -> (values string string string string string string) (define (red->colors reduction-name) (apply values (hash-ref name->color-ht reduction-name - (λ () (list (dark-pen-color) (light-pen-color) (dark-text-color) (light-text-color)))))) + default-colors))) ;; reduce-frontier : -> void ;; =reduction thread= @@ -225,11 +324,13 @@ (let-values ([(name sexp) (apply values red+sexp)]) (call-on-eventspace-main-thread (λ () - (let-values ([(dark-arrow-color light-arrow-color dark-label-color light-label-color) + (let-values ([(dark-arrow-color light-arrow-color dark-label-color light-label-color + dark-pen-color + light-pen-color) (red->colors name)]) - (build-snip snip-cache snip sexp pred pp + (build-snip snip-cache snip sexp pred pp name scheme-colors? light-arrow-color dark-arrow-color dark-label-color light-label-color - name)))))) + dark-pen-color light-pen-color)))))) (apply-reduction-relation/tag-with-names reductions (send snip get-expr))))] [new-y (call-on-eventspace-main-thread @@ -239,6 +340,7 @@ (set! col (+ x-spacing (find-rightmost-x graph-pb)))) (begin0 (insert-into col y graph-pb new-snips) + (layout (hash-map snip-cache (lambda (x y) (send y get-term-node)))) (send graph-pb end-edit-sequence) (send status-message set-label (string-append (term-count (count-snips)) "...")))))]) @@ -369,9 +471,12 @@ null))) (out-of-dot-state) ;; make sure the state is initialized right (insert-into init-rightmost-x 0 graph-pb frontier) + (layout (map (lambda (y) (send y get-term-node)) frontier)) (set-font-size (initial-font-size)) (reduce-button-callback) - (send f show #t)) + (if no-show-frame? + graph-pb + (send f show #t))) (define red-sem-frame% (class (frame:standard-menus-mixin (frame:basic-mixin frame%)) @@ -509,20 +614,22 @@ ;; sexp ;; sexp -> boolean ;; (any port number -> void) -;; color ;; (union #f string) +;; color^6 ;; -> (union #f (is-a?/c graph-editor-snip%)) ;; returns #f if a snip corresponding to the expr has already been created. ;; also adds in the links to the parent snip ;; =eventspace main thread= -(define (build-snip cache parent-snip expr pred pp light-arrow-color dark-arrow-color dark-label-color light-label-color name) +(define (build-snip cache parent-snip expr pred pp name scheme-colors? + light-arrow-color dark-arrow-color dark-label-color light-label-color + dark-brush-color light-brush-color) (let-values ([(snip new?) (let/ec k (values (hash-ref cache expr (lambda () - (let ([new-snip (make-snip parent-snip expr pred pp)]) + (let ([new-snip (make-snip parent-snip expr pred pp scheme-colors?)]) (hash-set! cache expr new-snip) (k new-snip #t)))) #f))]) @@ -532,10 +639,14 @@ (add-links/text-colors parent-snip snip (send the-pen-list find-or-create-pen dark-arrow-color 0 'solid) (send the-pen-list find-or-create-pen light-arrow-color 0 'solid) - (send the-brush-list find-or-create-brush (dark-brush-color) 'solid) - (send the-brush-list find-or-create-brush (light-brush-color) 'solid) - (make-object color% dark-label-color) - (make-object color% light-label-color) + (send the-brush-list find-or-create-brush dark-brush-color 'solid) + (send the-brush-list find-or-create-brush light-brush-color 'solid) + (if (is-a? dark-label-color color%) + dark-label-color + (make-object color% dark-label-color)) + (if (is-a? light-label-color color%) + light-label-color + (make-object color% light-label-color)) 0 0 name) (update-badness pred parent-snip (send parent-snip get-expr))) @@ -563,7 +674,7 @@ ;; -> (is-a?/c graph-editor-snip%) ;; unconditionally creates a new graph-editor-snip ;; =eventspace main thread= -(define (make-snip parent-snip expr pred pp) +(define (make-snip parent-snip expr pred pp scheme-colors?) (let* ([text (new program-text%)] [es (instantiate graph-editor-snip% () (char-width (initial-char-width)) @@ -573,6 +684,7 @@ (expr expr))]) (send text set-autowrap-bitmap #f) (send text freeze-colorer) + (send text stop-colorer (not scheme-colors?)) (send es format-expr) es)) @@ -605,12 +717,18 @@ (unbox bt)))) (provide traces + traces/ps term-node? term-node-parents term-node-children term-node-labels term-node-set-red! term-node-set-color! + term-node-set-position! + term-node-x + term-node-y + term-node-width + term-node-height term-node-expr) (provide reduction-steps-cutoff initial-font-size diff --git a/collects/redex/redex.scrbl b/collects/redex/redex.scrbl index 1d9f533dde..7e3101bfe5 100644 --- a/collects/redex/redex.scrbl +++ b/collects/redex/redex.scrbl @@ -1117,13 +1117,21 @@ exploring reduction sequences. [expr (or/c any/c (listof any/c))] [#:multiple? multiple? boolean? #f] [#:pred pred - (or/c (sexp -> any) (sexp term-node? any)) + (or/c (-> sexp any) + (-> sexp term-node? any)) (lambda (x) #t)] [#:pp pp (or/c (any -> string) (any output-port number (is-a?/c text%) -> void)) default-pretty-printer] - [#:colors colors (listof (list string string)) '()]) + [#:colors colors + (listof + (cons/c string + (and/c (listof (or/c string? (is-a?/c color%))) + (lambda (x) (member (length x) '(2 3 4 6))))))] + + [#:scheme-colors? scheme-colors? boolean?] + [#:layout layout (-> (listof term-node?) void)]) void?]{ This function opens a new window and inserts each expression @@ -1163,14 +1171,56 @@ final argument is the text where the port is connected -- characters written to the port go to the end of the editor. The @scheme[colors] argument, if provided, specifies a list of -reduction-name/color-string pairs. The traces gui will color -arrows drawn because of the given reduction name with the -given color instead of using the default color. +reduction-name/color-list pairs. The traces gui will color arrows +drawn because of the given reduction name with the given color instead +of using the default color. + +The @scheme[cdr] of each of the elements of @scheme[colors] is a list +of colors, organized in pairs. The first two colors cover the colors +of the line and the border around the arrow head, the first when the +mouse is over a graph node that is connected to that arrow, and the +second for when the mouse is not over that arrow. Similarly, the next +colors are for the text drawn on the arrow and the last two are for +the color that fills the arrow head. If fewer than six colors are +specified, the colors specified colors are used and then defaults are +filled in for the remaining colors. + + + +The @scheme[scheme-colors?] argument, if @scheme[#t] causes +@scheme[traces] to color the contents of each of the windows according +to DrScheme's Scheme mode color Scheme. If it is @scheme[#f], +@scheme[traces] just uses black for the color scheme. + +The @scheme[layout] argument is called (with all of the terms) each +time a new term is inserted into the window. See also +@scheme[term-node-set-position!]. You can save the contents of the window as a postscript file from the menus. } +@defproc[(traces/ps [reductions reduction-relation?] + [expr (or/c any/c (listof any/c))] + [file (or/c path-string? path?)] + [#:multiple? multiple? boolean? #f] + [#:pred pred + (or/c (-> sexp any) + (-> sexp term-node? any)) + (lambda (x) #t)] + [#:pp pp + (or/c (any -> string) + (any output-port number (is-a?/c text%) -> void)) + default-pretty-printer] + [#:colors colors (listof (list string string)) '()] + [#:layout layout (-> (listof term-node?) void)]) + void?]{ + +The arguments behave just like the function @scheme[traces], but +instead of opening a window to show the reduction graph, it just saves +the reduction graph to the specified @scheme[file]. +} + @defproc[(stepper [reductions reduction-relation?] [t any/c] [pp (or/c (any -> string) @@ -1246,6 +1296,24 @@ not colored specially. Returns the expression in this node. } +@defproc[(term-node-set-position! [tn term-node?] [x (and/c real? positive?)] [y (and/c real? positive?)]) void?]{ + +Sets the position of @scheme[tn] in the graph to (@scheme[x],@scheme[y]). +} + +@defproc[(term-node-x [tn term-node?]) real]{ +Returns the @tt{x} coordinate of @scheme[tn] in the window. +} +@defproc[(term-node-y [tn term-node?]) real]{ +Returns the @tt{y} coordinate of @scheme[tn] in the window. +} +@defproc[(term-node-width [tn term-node?]) real]{ +Returns the width of @scheme[tn] in the window. +} +@defproc[(term-node-height [tn term-node?]) real?]{ +Returns the height of @scheme[tn] in the window. +} + @defproc[(term-node? [v any/c]) boolean?]{ Recognizes term nodes. From e34badc4cf4584d5df5429549a66e029f2f393c6 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Sat, 10 Jan 2009 23:12:52 +0000 Subject: [PATCH 15/38] fixed some typos: svn: r13059 --- collects/redex/private/traces.ss | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/collects/redex/private/traces.ss b/collects/redex/private/traces.ss index 3bf3888bbd..702d70a2ac 100644 --- a/collects/redex/private/traces.ss +++ b/collects/redex/private/traces.ss @@ -127,7 +127,6 @@ #:multiple? [multiple? #f] #:pred [pred (λ (x) #t)] #:pp [pp default-pretty-printer] - #:default-arrow-colors [default-arrow-colors '()] #:scheme-colors? [scheme-colors? #t] #:colors [colors '()] #:layout [layout void]) @@ -137,7 +136,6 @@ #:multiple? multiple? #:pred pred #:pp pp - #:default-arrow-colors default-arrow-colors #:scheme-colors? scheme-colors? #:colors colors #:layout layout)] @@ -146,7 +144,7 @@ (send ps-setup set-file filename) (send ps-setup set-mode 'file) (parameterize ([current-ps-setup ps-setup]) - (send graph-pb print #t #f 'postscript #f #f)))) + (send graph-pb print #t #f 'postscript #f #f #t)))) (define (traces reductions pre-exprs #:multiple? [multiple? #f] From 72b7e59851db6a52447d01f4cba192b0f11f7ac1 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Sat, 10 Jan 2009 23:16:40 +0000 Subject: [PATCH 16/38] fixed eps? argument to pasteboard print method svn: r13060 --- collects/mred/private/editor.ss | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/collects/mred/private/editor.ss b/collects/mred/private/editor.ss index f5c4d3a7bf..1ecb655e25 100644 --- a/collects/mred/private/editor.ss +++ b/collects/mred/private/editor.ss @@ -341,24 +341,24 @@ ((void) after-edit-sequence)) (private* - [sp (lambda (x y z f b?) + [sp (lambda (x y z f b? eps?) ;; let super method report z errors: (let ([zok? (memq z '(standard postscript))]) (when zok? (check-top-level-parent/false '(method editor<%> print) f)) (let ([p (and zok? f (mred->wx f))]) - (as-exit (lambda () (super print x y z p b?))))))]) + (as-exit (lambda () (super print x y z p b? eps?))))))]) (override* [print (entry-point (case-lambda - [() (sp #t #t 'standard #f #t)] - [(x) (sp x #t 'standard #f #t)] - [(x y) (sp x y 'standard #f #t)] - [(x y z) (sp x y z #f #t)] - [(x y z f) (sp x y z f #t)] - [(x y z f b?) (sp x y z f b?)] + [() (sp #t #t 'standard #f #t #f)] + [(x) (sp x #t 'standard #f #t #f)] + [(x y) (sp x y 'standard #f #t #f)] + [(x y z) (sp x y z #f #t #f)] + [(x y z f) (sp x y z f #t #f)] + [(x y z f b?) (sp x y z f b? #f)] [(x y z f b? eps?) (sp x y z f b? eps?)]))] [on-new-box From 538a1e695e3e68c1636e584da1bbd4c4d82dbcd7 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Sat, 10 Jan 2009 23:21:46 +0000 Subject: [PATCH 17/38] svn: r13061 --- collects/redex/private/traces.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collects/redex/private/traces.ss b/collects/redex/private/traces.ss index 702d70a2ac..f2d67391c3 100644 --- a/collects/redex/private/traces.ss +++ b/collects/redex/private/traces.ss @@ -144,7 +144,7 @@ (send ps-setup set-file filename) (send ps-setup set-mode 'file) (parameterize ([current-ps-setup ps-setup]) - (send graph-pb print #t #f 'postscript #f #f #t)))) + (send graph-pb print #f #f 'postscript #f #f #t)))) (define (traces reductions pre-exprs #:multiple? [multiple? #f] From 3ceb88b8a7ea76895b2cbda38b922bf020b882db Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Sat, 10 Jan 2009 23:49:03 +0000 Subject: [PATCH 18/38] fixed a bug intraces/ps svn: r13062 --- collects/redex/private/traces.ss | 45 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/collects/redex/private/traces.ss b/collects/redex/private/traces.ss index f2d67391c3..ebddb6617f 100644 --- a/collects/redex/private/traces.ss +++ b/collects/redex/private/traces.ss @@ -130,21 +130,21 @@ #:scheme-colors? [scheme-colors? #t] #:colors [colors '()] #:layout [layout void]) - (let ([graph-pb - (traces reductions pre-exprs - #:no-show-frame? #t - #:multiple? multiple? - #:pred pred - #:pp pp - #:scheme-colors? scheme-colors? - #:colors colors - #:layout layout)] - [ps-setup (make-object ps-setup%)]) - (send ps-setup copy-from (current-ps-setup)) - (send ps-setup set-file filename) - (send ps-setup set-mode 'file) - (parameterize ([current-ps-setup ps-setup]) - (send graph-pb print #f #f 'postscript #f #f #t)))) + (let-values ([(graph-pb frame) + (traces reductions pre-exprs + #:no-show-frame? #t + #:multiple? multiple? + #:pred pred + #:pp pp + #:scheme-colors? scheme-colors? + #:colors colors + #:layout layout)]) + (let ([ps-setup (make-object ps-setup%)]) + (send ps-setup copy-from (current-ps-setup)) + (send ps-setup set-file filename) + (send ps-setup set-mode 'file) + (parameterize ([current-ps-setup ps-setup]) + (send graph-pb print #f #f 'postscript #f #f #t))))) (define (traces reductions pre-exprs #:multiple? [multiple? #f] @@ -471,10 +471,17 @@ (insert-into init-rightmost-x 0 graph-pb frontier) (layout (map (lambda (y) (send y get-term-node)) frontier)) (set-font-size (initial-font-size)) - (reduce-button-callback) - (if no-show-frame? - graph-pb - (send f show #t))) + (cond + [no-show-frame? + (let ([s (make-semaphore)]) + (thread (λ () + (do-some-reductions) + (semaphore-post s))) + (yield s)) + (values graph-pb f)] + [else + (reduce-button-callback) + (send f show #t)])) (define red-sem-frame% (class (frame:standard-menus-mixin (frame:basic-mixin frame%)) From 3c22ff982b1746180cd52d6204e8ee16accfdf3e Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Sun, 11 Jan 2009 08:50:15 +0000 Subject: [PATCH 19/38] Welcome to a new PLT day. svn: r13063 --- collects/repos-time-stamp/stamp.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collects/repos-time-stamp/stamp.ss b/collects/repos-time-stamp/stamp.ss index e988e9ee11..ef3215a32f 100644 --- a/collects/repos-time-stamp/stamp.ss +++ b/collects/repos-time-stamp/stamp.ss @@ -1 +1 @@ -#lang scheme/base (provide stamp) (define stamp "10jan2009") +#lang scheme/base (provide stamp) (define stamp "11jan2009") From 4180d67e342a35cdbd3b85b36a1827d849656531 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 11 Jan 2009 13:52:26 +0000 Subject: [PATCH 20/38] make scheme/path fuctions work on paths for any playform svn: r13064 --- collects/scheme/path.ss | 29 +++++---- collects/scribblings/gui/color-class.scrbl | 8 ++- collects/scribblings/reference/paths.scrbl | 19 +++--- collects/tests/mzscheme/mzlib-tests.ss | 1 + collects/tests/mzscheme/pathlib.ss | 69 ++++++++++++++++++++++ 5 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 collects/tests/mzscheme/pathlib.ss diff --git a/collects/scheme/path.ss b/collects/scheme/path.ss index d093181713..26ec3e2180 100644 --- a/collects/scheme/path.ss +++ b/collects/scheme/path.ss @@ -113,18 +113,19 @@ (let loop ([path orig-path][rest '()]) (let-values ([(base name dir?) (split-path path)]) (when simple? - (when (or (and base (not (path? base))) - (not (path? name))) + (when (or (and base (not (path-for-some-system? base))) + (not (path-for-some-system? name))) (raise-type-error who - "path in simple form (absolute, complete, and with no same- or up-directory indicators)" + "path (for ay platform) in simple form (absolute, complete, and with no same- or up-directory indicators)" orig-path))) - (if (path? base) + (if (path-for-some-system? base) (loop base (cons name rest)) (cons name rest))))) (define (explode-path orig-path) - (unless (path-string? orig-path) - (raise-type-error 'explode-path "path or string" orig-path)) + (unless (or (path-string? orig-path) + (path-for-some-system? orig-path)) + (raise-type-error 'explode-path "path (for any platform) or string" orig-path)) (do-explode-path 'explode-path orig-path #f)) ;; Arguments must be in simple form @@ -143,20 +144,22 @@ filename))) (define (file-name who name) - (unless (path-string? name) - (raise-type-error who "path or string" name)) + (unless (or (path-string? name) + (path-for-some-system? name)) + (raise-type-error who "path (for any platform) or string" name)) (let-values ([(base file dir?) (split-path name)]) - (and (not dir?) (path? file) file))) + (and (not dir?) (path-for-some-system? file) file))) (define (file-name-from-path name) (file-name 'file-name-from-path name)) (define (path-only name) - (unless (path-string? name) - (raise-type-error 'path-only "path or string" name)) + (unless (or (path-string? name) + (path-for-some-system? name)) + (raise-type-error 'path-only "path (for any platform) or string" name)) (let-values ([(base file dir?) (split-path name)]) - (cond [dir? name] - [(path? base) base] + (cond [dir? (if (string? name) (string->path name) name)] + [(path-for-some-system? base) base] [else #f]))) ;; name can be any string; we just look for a dot diff --git a/collects/scribblings/gui/color-class.scrbl b/collects/scribblings/gui/color-class.scrbl index 118d78f130..07eb8a6582 100644 --- a/collects/scribblings/gui/color-class.scrbl +++ b/collects/scribblings/gui/color-class.scrbl @@ -13,14 +13,16 @@ See @scheme[color-database<%>] for information about obtaining a color object using a color name. -@defconstructor*/make[(([red (integer-in 0 255)] +@defconstructor*/make[(() + ([red (integer-in 0 255)] [green (integer-in 0 255)] [blue (integer-in 0 255)]) ([color-name string?]))]{ Creates a new color with the given RGB values, or matching the given - color name (using ``black'' if the name is not recognized). See - @scheme[color-database<%>] for more information on color names. + color name (using ``black'' if no color is given or if the name is + not recognized). See @scheme[color-database<%>] for more information + on color names. } diff --git a/collects/scribblings/reference/paths.scrbl b/collects/scribblings/reference/paths.scrbl index e5dc1f5f1d..b221a2840b 100644 --- a/collects/scribblings/reference/paths.scrbl +++ b/collects/scribblings/reference/paths.scrbl @@ -494,21 +494,22 @@ to the end.} @note-lib[scheme/path] -@defproc[(explode-path [path path-string?]) - (listof (or/c path? 'up 'same))]{ +@defproc[(explode-path [path (or/c path-string? path-for-some-system?)]) + (listof (or/c path-for-some-system? 'up 'same))]{ Returns the list of path element that constitute @scheme[path]. If @scheme[path] is simplified in the sense of @scheme[simple-form-path], then the result is always a list of paths, and the first element of the list is a root.} -@defproc[(file-name-from-path [path path-string?]) (or/c path? #f)]{ +@defproc[(file-name-from-path [path (or/c path-string? path-for-some-system?)]) + (or/c path-for-some-system? #f)]{ Returns the last element of @scheme[path]. If @scheme[path] syntactically a directory path (see @scheme[split-path]), then then result is @scheme[#f].} -@defproc[(filename-extension [path path-string?]) +@defproc[(filename-extension [path (or/c path-string? path-for-some-system?)]) (or/c bytes? #f)]{ Returns a byte string that is the extension part of the filename in @@ -516,7 +517,9 @@ Returns a byte string that is the extension part of the filename in syntactically a directory (see @scheme[split-path]) or if the path has no extension, @scheme[#f] is returned.} -@defproc[(find-relative-path [base path-string?][path path-string?]) path?]{ +@defproc[(find-relative-path [base (or/c path-string? path-for-some-system?)] + [path (or/c path-string? path-for-some-system?)]) + path-for-some-system?]{ Finds a relative pathname with respect to @scheme[basepath] that names the same file or directory as @scheme[path]. Both @scheme[basepath] @@ -544,10 +547,12 @@ An error is signaled by @scheme[normalize-path] if the input path contains an embedded path for a non-existent directory, or if an infinite cycle of soft links is detected.} -@defproc[(path-only [path path-string?]) (or/c path? #f)]{ +@defproc[(path-only [path (or/c path-string? path-for-some-system?)]) + path-for-some-system?]{ If @scheme[path] is a filename, the file's path is returned. If -@scheme[path] is syntactically a directory, @scheme[#f] is returned.} +@scheme[path] is syntactically a directory, @scheme[path] is returned +(as a path, if it was a string).} @defproc[(simple-form-path [path path-string?]) path?]{ diff --git a/collects/tests/mzscheme/mzlib-tests.ss b/collects/tests/mzscheme/mzlib-tests.ss index 6003409b7e..6e89d5435f 100644 --- a/collects/tests/mzscheme/mzlib-tests.ss +++ b/collects/tests/mzscheme/mzlib-tests.ss @@ -10,6 +10,7 @@ (load-in-sandbox "async-channel.ss") (load-in-sandbox "restart.ss") (load-in-sandbox "string-mzlib.ss") +(load-in-sandbox "pathlib.ss") (load-in-sandbox "filelib.ss") (load-in-sandbox "portlib.ss") (load-in-sandbox "threadlib.ss") diff --git a/collects/tests/mzscheme/pathlib.ss b/collects/tests/mzscheme/pathlib.ss new file mode 100644 index 0000000000..262d83a444 --- /dev/null +++ b/collects/tests/mzscheme/pathlib.ss @@ -0,0 +1,69 @@ + +(load-relative "loadtest.ss") + +(Section 'path) + +(require scheme/path) + +(define (rtest f args result) + (test result f args)) + +;; ---------------------------------------- + +(rtest explode-path "a/b" (list (string->path "a") + (string->path "b"))) +(rtest explode-path "a/../b" (list (string->path "a") + 'up + (string->path "b"))) +(rtest explode-path "./a/b" (list 'same + (string->path "a") + (string->path "b"))) +(rtest explode-path (bytes->path #"./a/b" 'unix) (list 'same + (bytes->path #"a" 'unix) + (bytes->path #"b" 'unix))) +(rtest explode-path (bytes->path #"./a\\b" 'windows) (list 'same + (bytes->path #"a" 'windows) + (bytes->path #"b" 'windows))) + +;; ---------------------------------------- + +(rtest file-name-from-path "a/" #f) +(rtest file-name-from-path "a/b" (string->path "b")) +(rtest file-name-from-path (bytes->path #"a/b" 'unix) (bytes->path #"b" 'unix)) +(rtest file-name-from-path (bytes->path #"a\\b" 'windows) (bytes->path #"b" 'windows)) + +;; ---------------------------------------- + +(rtest filename-extension "a" #f) +(rtest filename-extension "a.sls" #"sls") +(rtest filename-extension (bytes->path #"b/a.sls" 'unix) #"sls") +(rtest filename-extension (bytes->path #"b\\a.sls" 'windows) #"sls") + +;; ---------------------------------------- + +(test (string->path "a") find-relative-path (path->complete-path "b") (path->complete-path "b/a")) +(test (string->path "../../b/a") find-relative-path (path->complete-path "c/b") (path->complete-path "b/a")) +(test (bytes->path #"a" 'unix) find-relative-path (bytes->path #"/r/b" 'unix) (bytes->path #"/r/b/a" 'unix)) +(test (bytes->path #"a" 'windows) find-relative-path (bytes->path #"c:/r/b" 'windows) (bytes->path #"c:/r/b/a" 'windows)) + +;; ---------------------------------------- + +;; normalize-path needs tests + +;; ---------------------------------------- + +(rtest path-only "a/b" (string->path "a/")) +(rtest path-only "a/b/" (string->path "a/b/")) +(rtest path-only "a/.." (string->path "a/..")) +(rtest path-only (bytes->path #"a/z" 'unix) (bytes->path #"a/" 'unix)) +(rtest path-only (bytes->path #"a/z/" 'unix) (bytes->path #"a/z/" 'unix)) +(rtest path-only (bytes->path #"a/z" 'windows) (bytes->path #"a/" 'windows)) +(rtest path-only (bytes->path #"a/z/" 'windows) (bytes->path #"a/z/" 'windows)) + +;; ---------------------------------------- + +;; simple-form-path needs tests + +;; ---------------------------------------- + +(report-errs) From 2530e04720b9252299ec509dbe5ca03515c0c8ed Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 11 Jan 2009 14:47:51 +0000 Subject: [PATCH 21/38] add some-system-path<->string functions to scheme/path svn: r13065 --- collects/scheme/path.ss | 19 +++++++++++++- collects/scribblings/reference/paths.scrbl | 29 ++++++++++++++++++++-- collects/tests/mzscheme/pathlib.ss | 10 ++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/collects/scheme/path.ss b/collects/scheme/path.ss index 26ec3e2180..f047a1ebf0 100644 --- a/collects/scheme/path.ss +++ b/collects/scheme/path.ss @@ -6,7 +6,9 @@ normalize-path filename-extension file-name-from-path - path-only) + path-only + some-system-path->string + string->some-system-path) (define (simple-form-path p) (unless (path-string? p) @@ -168,3 +170,18 @@ [name (and name (path->bytes name))]) (cond [(and name (regexp-match #rx#"[.]([^.]+)$" name)) => cadr] [else #f]))) + +(define (some-system-path->string path) + (unless (path-for-some-system? path) + (raise-type-error 'some-system-path->string "path (for any platform)" path)) + (bytes->string/utf-8 (path->bytes path))) + +(define (string->some-system-path path kind) + (unless (string? path) + (raise-type-error 'string->some-system-path "string" path)) + (unless (or (eq? kind 'unix) + (eq? kind 'windows)) + (raise-type-error 'string->some-system-path "'unix or 'windows" kind)) + (bytes->path (string->bytes/utf-8 path) kind)) + + diff --git a/collects/scribblings/reference/paths.scrbl b/collects/scribblings/reference/paths.scrbl index b221a2840b..068983d6f1 100644 --- a/collects/scribblings/reference/paths.scrbl +++ b/collects/scribblings/reference/paths.scrbl @@ -65,7 +65,9 @@ Beware that the current locale might not encode every string, in which case @scheme[string->path] can produce the same path for different @scheme[str]s. See also @scheme[string->path-element], which should be used instead of @scheme[string->path] when a string represents a -single path element.} +single path element. + +See also @scheme[string->some-system-path].} @defproc[(bytes->path [bstr bytes?] [type (or/c 'unix 'windows) (system-path-convention-type)]) @@ -97,7 +99,9 @@ Furthermore, for display and sorting based on individual path elements (such as pathless file names), use @scheme[path-element->string], instead, to avoid special encodings use to represent some relative paths. See @secref["windowspaths"] for specific information about -the conversion of Windows paths.} +the conversion of Windows paths. + +See also @scheme[some-system-path->string].} @defproc[(path->bytes [path path?]) bytes?]{ @@ -560,6 +564,27 @@ Returns @scheme[(simplify-path (path->complete-path path))], which ensures that the result is a complete path containing no up- or same-directory indicators.} +@defproc[(some-system-path->string [path path-for-some-system?]) + string?]{ + +Converts @scheme[path] to a string using a UTF-8 encoding of the +path's bytes. + +Use this function when working with paths for a different system +(whose encoding of pathnames might be unrelated to the current +locale's encoding) and when starting and ending with strings.} + +@defproc[(string->some-system-path [str string?] + [kind (or/c 'unix 'windows)]) + path-for-some-system?]{ + +Converts @scheme[str] to a @scheme[kind] path using a UTF-8 encoding +of the path's bytes. + +Use this function when working with paths for a different system +(whose encoding of pathnames might be unrelated to the current +locale's encoding) and when starting and ending with strings.} + @;------------------------------------------------------------------------ @include-section["unix-paths.scrbl"] @include-section["windows-paths.scrbl"] diff --git a/collects/tests/mzscheme/pathlib.ss b/collects/tests/mzscheme/pathlib.ss index 262d83a444..a1f53be883 100644 --- a/collects/tests/mzscheme/pathlib.ss +++ b/collects/tests/mzscheme/pathlib.ss @@ -66,4 +66,14 @@ ;; ---------------------------------------- +(test "a" some-system-path->string (string->path "a")) +(test "a" some-system-path->string (bytes->path #"a" 'unix)) +(test "a" some-system-path->string (bytes->path #"a" 'windows)) +(test #t path-for-some-system? (string->some-system-path "a" 'unix)) +(test #t path-for-some-system? (string->some-system-path "a" 'windows)) +(test "a" some-system-path->string (string->some-system-path "a" 'unix)) +(test "a" some-system-path->string (string->some-system-path "a" 'windows)) + +;; ---------------------------------------- + (report-errs) From 72b272ebd01f6ded5fbd0177827824b432dcbcd4 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 11 Jan 2009 15:23:13 +0000 Subject: [PATCH 22/38] fix typo in example (PR 10018) svn: r13066 --- collects/scribblings/gui/win-overview.scrbl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/collects/scribblings/gui/win-overview.scrbl b/collects/scribblings/gui/win-overview.scrbl index 84a55aa032..5bb75cfd8b 100644 --- a/collects/scribblings/gui/win-overview.scrbl +++ b/collects/scribblings/gui/win-overview.scrbl @@ -355,8 +355,8 @@ with the following program: [alignment '(center center)])) (code:comment #, @t{Add @onscreen{Cancel} and @onscreen{Ok} buttons to the horizontal panel}) -(new button% [parent parent] [label "Cancel"]) -(new button% [parent parent] [label "Ok"]) +(new button% [parent panel] [label "Cancel"]) +(new button% [parent panel] [label "Ok"]) (code:comment #, @t{Show the dialog}) (send dialog #,(:: dialog% show) #t) From 9a177b251e71fb66003a314f9c9466560f72c0ce Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 11 Jan 2009 15:39:54 +0000 Subject: [PATCH 23/38] use 'system-position-ok-before-cancel?' in GUI overview example svn: r13067 --- collects/scribblings/gui/area-container-intf.scrbl | 3 ++- collects/scribblings/gui/win-overview.scrbl | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/collects/scribblings/gui/area-container-intf.scrbl b/collects/scribblings/gui/area-container-intf.scrbl index 11d83be8e8..75e3cc16d6 100644 --- a/collects/scribblings/gui/area-container-intf.scrbl +++ b/collects/scribblings/gui/area-container-intf.scrbl @@ -71,7 +71,8 @@ Gets or sets the border margin for the container in pixels. This } -@defmethod[(change-children [filter ((listof (is-a?/c subarea<%>)) . -> . (listof (is-a?/c subarea<%>)))]) +@defmethod[(change-children [filter ((listof (is-a?/c subarea<%>)) + . -> . (listof (is-a?/c subarea<%>)))]) void?]{ Takes a filter procedure and changes the container's list of diff --git a/collects/scribblings/gui/win-overview.scrbl b/collects/scribblings/gui/win-overview.scrbl index 5bb75cfd8b..a187e14fad 100644 --- a/collects/scribblings/gui/win-overview.scrbl +++ b/collects/scribblings/gui/win-overview.scrbl @@ -357,6 +357,8 @@ with the following program: (code:comment #, @t{Add @onscreen{Cancel} and @onscreen{Ok} buttons to the horizontal panel}) (new button% [parent panel] [label "Cancel"]) (new button% [parent panel] [label "Ok"]) +(when (system-position-ok-before-cancel?) + (send panel #,(:: area-container<%> change-children) reverse)) (code:comment #, @t{Show the dialog}) (send dialog #,(:: dialog% show) #t) From d954df380f4814619c881ea031102ec21c24c106 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Mon, 12 Jan 2009 08:50:13 +0000 Subject: [PATCH 24/38] Welcome to a new PLT day. svn: r13068 --- collects/repos-time-stamp/stamp.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collects/repos-time-stamp/stamp.ss b/collects/repos-time-stamp/stamp.ss index ef3215a32f..70606307e7 100644 --- a/collects/repos-time-stamp/stamp.ss +++ b/collects/repos-time-stamp/stamp.ss @@ -1 +1 @@ -#lang scheme/base (provide stamp) (define stamp "11jan2009") +#lang scheme/base (provide stamp) (define stamp "12jan2009") From ab5d16d55b5b448453fbecba88d749e347995ba3 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 12 Jan 2009 13:31:07 +0000 Subject: [PATCH 25/38] fix arity messages constructed internally for structure procs (PR 10019) svn: r13069 --- src/mzscheme/src/error.c | 4 ++++ src/mzscheme/src/schpriv.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mzscheme/src/error.c b/src/mzscheme/src/error.c index 8237049fba..4422763fbb 100644 --- a/src/mzscheme/src/error.c +++ b/src/mzscheme/src/error.c @@ -1217,6 +1217,10 @@ char *scheme_make_arity_expect_string(Scheme_Object *proc, } name = scheme_get_proc_name((Scheme_Object *)proc, &namelen, 1); #endif + } else if (SCHEME_STRUCTP(proc)) { + name = proc; + mina = -1; + maxa = 0; } else { Scheme_Closure_Data *data; diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index 48207e915a..301079be72 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -362,7 +362,7 @@ extern mz_proc_thread *scheme_master_proc_thread; extern THREAD_LOCAL mz_proc_thread *proc_thread_self; #endif -extern int scheme_no_stack_overflow; +extern THREAD_LOCAL int scheme_no_stack_overflow; typedef struct Scheme_Thread_Set { Scheme_Object so; From ebc1bf47525df2c96e4772897ed1f2d95e2de900 Mon Sep 17 00:00:00 2001 From: Jay McCarthy Date: Mon, 12 Jan 2009 17:01:46 +0000 Subject: [PATCH 26/38] Limiting svn: r13070 --- collects/web-server/scribblings/faq.scrbl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/collects/web-server/scribblings/faq.scrbl b/collects/web-server/scribblings/faq.scrbl index 1c1c31d6ca..dc9702e062 100644 --- a/collects/web-server/scribblings/faq.scrbl +++ b/collects/web-server/scribblings/faq.scrbl @@ -107,11 +107,21 @@ The Web Server will start on port 443 (which can be overridden with the @exec{-p There is no built-in option for this, but you can easily accomplish it if you assemble your own dispatcher by wrapping it in @scheme[call-with-semaphore]: @schemeblock[ +(require + (prefix-in private: + web-server/private/web-server-structs)) (define (make-limit-dispatcher num inner) - (let ([sem (make-semaphore num)]) - (lambda (conn req) - (call-with-semaphore sem - (lambda () (inner conn req)))))) + (let ([sem (make-semaphore num)]) + (lambda (conn req) + (parameterize + ([current-custodian + (private:current-server-custodian)]) + (thread + (lambda () + (call-with-semaphore + sem + (lambda () + (inner conn req))))))))) ] Once this function is available, rather than providing @scheme[james-gordon] as your dispatcher, you provide: From c22b57000402ce4499613767dbcd87351459186e Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 17:30:44 +0000 Subject: [PATCH 27/38] svn: r13071 --- .../teachpack/2htdp/scribblings/server2.ss | 2 +- .../2htdp/scribblings/universe.scrbl | 92 ++++++++++-------- collects/teachpack/world.png | Bin 19925 -> 0 bytes 3 files changed, 52 insertions(+), 42 deletions(-) delete mode 100644 collects/teachpack/world.png diff --git a/collects/teachpack/2htdp/scribblings/server2.ss b/collects/teachpack/2htdp/scribblings/server2.ss index 427a7c22ed..2bf45e143c 100644 --- a/collects/teachpack/2htdp/scribblings/server2.ss +++ b/collects/teachpack/2htdp/scribblings/server2.ss @@ -10,7 +10,7 @@ (define program (apply vl-append (map (lambda (t) (text t '() (- FT 2))) - (list (format "(universe ~a ~a)" initialize proc-msg))))) + (list (format "(universe [on-new ~a] [on-msg ~a])" initialize proc-msg))))) (define Program (cc-superimpose diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index 044a6f82d8..d16ed79e53 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -835,7 +835,7 @@ The @scheme[on-receive] clause of a @scheme[big-bang] specifies the event handle The diagram below summarizes the extensions of this section in graphical form. -@image["universe.png"] +@image["world.png"] A registered world program may send a message to the universe server at any time by returning a @tech{Package} from an event handler. The @@ -853,16 +853,15 @@ When messages are sent from any of the worlds to the universe or vice versa, the receiving @tech{server} or @tech{world} program take care of them. @; ----------------------------------------------------------------------------- - @section[#:tag "universe-server"]{The Universe Server} A @deftech{server} is the central control program of a @tech{universe} and deals with receiving and sending of messages between the world programs that participate in the @tech{universe}. Like a @tech{world} program, a server is a program that reacts to events, though to different - events. There are two primary kinds of events: when a new @tech{world} - program joins the @tech{universe} that the server controls and when a - @tech{world} sends a message. + events than @tech{world}s. The two primary kinds of events are the + appearance of a new @tech{world} program in the @tech{universe} + and the receipt of a message from a @tech{world} program. The teachpack provides a mechanism for designating event handlers for servers that is quite similar to the mechanism for describing @tech{world} @@ -897,8 +896,9 @@ This section first introduces some basic forms of data that the @; ----------------------------------------------------------------------------- @subsection{Worlds and Messages} -Understanding the server's event handling functions demands three - concepts. +Understanding the server's event handling functions demands several data + representations: that of (a connection to) a @tech{world} program and that + of a response of a handler to an event. @itemize[ @@ -915,7 +915,7 @@ Understanding the server's event handling functions demands three @defproc[(world=? [u world?][v world?]) boolean?]{ compares two @emph{world}s for equality.} -defproc[(world-name [w world?]) symbol?]{ +@defproc[(world-name [w world?]) symbol?]{ extracts the name from a @emph{world} structure.} @defthing[world1 world?]{a world for testing your programs} @@ -931,9 +931,20 @@ for universe programs. For example: ] } -@item{A @emph{mail} represents a message from an event handler to a -world. The teachpack provides only a predicate and a constructor for these -structures: +@item{Each event handler produces a @emph{bundle}, which is a structure + that contains the list of @emph{world}s to keep track of; the + @tech{server}'s remaining state; and a list of mails to other + worlds: + +@defproc[(bundle? [x any/c]) boolean?]{ + determines whether @scheme[x] is a @emph{bundle}.} + +@defproc[(make-bundle [low (listof world?)] [state any/c] [mails (listof mail?)]) bundle?]{ + creates a @emph{bundle} from a list of worlds, a piece of data that represents a server + state, and a list of mails.} + +A @emph{mail} represents a message from an event handler to a world. The +teachpack provides only a predicate and a constructor for these structures: @defproc[(mail? [x any/c]) boolean?]{ determines whether @scheme[x] is a @emph{mail}.} @@ -942,33 +953,22 @@ structures: creates a @emph{mail} from a @emph{world} and an @tech{S-expression}.} } -@item{Each event handler produces a @emph{bundle}, which is a structure -that contains the @tech{server}'s state and a list of mails to other -worlds. Again, the teachpack provides only the predicate and a constructor: - -@defproc[(bundle? [x any/c]) boolean?]{ - determines whether @scheme[x] is a @emph{bundle}.} - -@defproc[(make-bundle [listof world?] [state any/c] [mails (listof mail?)]) bundle?]{ - creates a @emph{bundle} from a list of worlds, a piece of data that represents a server - state, and a list of mails.} - -} ] @; ----------------------------------------------------------------------------- @subsection{Universe Descriptions} A @tech{server} keeps track of information about the @tech{universe} that - it manages. Of course, what kind of information it tracks and how it is - represented depends on the situation and the programmer, just as with - @tech{world} programs. + it manages. One kind of tracked information is obviously the collection of + participating world programs, but in general the kind of information that + a server tracks and how the information is represented depends on the + situation and the programmer, just as with @tech{world} programs. -@deftech{UniverseState} @scheme[any/c] represent the server's state For running +@deftech{UniverseState} @scheme[any/c] represents the server's state For running @tech{universe}s, the teachpack demands that you come up with a data definition for (your state of the) @tech{server}. Any piece of data can represent the state. We just assume that you introduce a data definition -for the possible states and that your transformation functions are designed +for the possible states and that your event handlers are designed according to the design recipe for this data definition. The @tech{server} itself is created with a description that includes the @@ -996,7 +996,7 @@ registration of new worlds, how it disconnects worlds, how it sends messages from one world to the rest of the registered worlds, and how it renders its current state as a string.} -A @scheme[universe] expression starts a server. Visually it opens +Evaluating a @scheme[universe] expression starts a server. Visually it opens a console window on which you can see that worlds join, which messages are received from which world, and which messages are sent to which world. For convenience, the console also has two buttons: one for shutting down a @@ -1004,8 +1004,8 @@ A @scheme[universe] expression starts a server. Visually it opens especially useful during the integration of the various pieces of a distributed program. -Now it is possible to explain the clauses in a @scheme[universe] server -description. Two of them are mandatory: +The mandatory clauses of a @scheme[universe] server description are +@scheme[on-new] and @scheme[on-msg]: @itemize[ @@ -1015,8 +1015,11 @@ description. Two of them are mandatory: ([new-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? bundle?)])]{ tell DrScheme to call the function @scheme[new-expr] every time another world joins the universe. The event handler is called on the current list of worlds and the - joining world. -}} + joining world, which isn't on the list yet. In particular, the handler may + reject a @tech{world} program from participating in a @tech{universe}, + simply by not including it in the resulting @scheme[bundle] structure. The + handler may still send one message to the world that attempts to join. } +} @item{ @defform[(on-msg msg-expr) @@ -1024,18 +1027,25 @@ description. Two of them are mandatory: ([msg-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? sexp? bundle?)])]{ tell DrScheme to apply @scheme[msg-expr] to the list of currently - participating worlds, the current state of the universe, the world - that sent the message, and the message itself.} + participating worlds @scheme[low], the current state of the universe, the world + @scheme[w] that sent the message, and the message itself. Note that + @scheme[w] is guaranteed to be on the list @scheme[low]. } -] - All event handlers produce a @emph{bundle}. The list of worlds in this - @emph{bundle} becomes the server's list of worlds; the state in the bundle - is safe-guarded by the server until the next event; and the mails are - broadcast as specified. +}] + + All proper event handlers produce a @emph{bundle}. The list of worlds in + this @emph{bundle} becomes the server's list of worlds, meaning that only + the server listens only to messages from "approved" worlds. The state in + the bundle is safe-guarded by the server until the next event, and the + mails are broadcast as specified. The following picture provides a graphical overview of the server's workings. -@image["server2.png"] +@; ----------------------------------------------------------------------------- +@;; THE PICTURE IS WRONG +@; ----------------------------------------------------------------------------- + +@image["server.png"] In addition to the mandatory handlers, a program may wish to add some optional handlers: diff --git a/collects/teachpack/world.png b/collects/teachpack/world.png deleted file mode 100644 index 82dd678265d584fc645a40f2b9201fab3e50adb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19925 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 A1^@s6 From ba5b8de58a7796ba587680105b0bc8c4c6af8db7 Mon Sep 17 00:00:00 2001 From: Jay McCarthy Date: Mon, 12 Jan 2009 17:44:02 +0000 Subject: [PATCH 28/38] Limit dispatcher svn: r13072 --- collects/web-server/dispatchers/limit.ss | 46 +++++++++++++++ .../web-server/scribblings/dispatchers.scrbl | 59 +++++++++++++++++++ collects/web-server/scribblings/faq.scrbl | 26 +------- 3 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 collects/web-server/dispatchers/limit.ss diff --git a/collects/web-server/dispatchers/limit.ss b/collects/web-server/dispatchers/limit.ss new file mode 100644 index 0000000000..8cfe48cc6e --- /dev/null +++ b/collects/web-server/dispatchers/limit.ss @@ -0,0 +1,46 @@ +#lang scheme +(require "dispatch.ss") +(provide/contract + [interface-version dispatcher-interface-version/c] + [make (number? dispatcher/c . -> . dispatcher/c)]) + +(define interface-version 'v1) +(define (make num inner) + (define-struct in-req (partner reply-ch)) + (define in-ch (make-channel)) + (define-struct out-req (partner)) + (define out-ch (make-channel)) + (define limit-manager + (thread + (lambda () + (let loop ([i 0] + [partners empty]) + (apply sync + (if (< i num) + (handle-evt in-ch + (lambda (req) + (channel-put (in-req-reply-ch req) #t) + (loop (add1 i) + (list* (in-req-partner req) partners)))) + never-evt) + (handle-evt out-ch + (lambda (req) + (loop (sub1 i) + (remq (out-req-partner req) partners)))) + (map (lambda (p) + (handle-evt (thread-dead-evt p) + (lambda _ + (loop (sub1 i) (remq p partners))))) + partners)))))) + (define (in) + (define reply (make-channel)) + (channel-put in-ch (make-in-req (current-thread) reply)) + (channel-get reply)) + (define (out) + (channel-put out-ch (make-out-req (current-thread)))) + (lambda (conn req) + (dynamic-wind + in + (lambda () + (inner conn req)) + out))) diff --git a/collects/web-server/scribblings/dispatchers.scrbl b/collects/web-server/scribblings/dispatchers.scrbl index 1622cee48c..efb98175fb 100644 --- a/collects/web-server/scribblings/dispatchers.scrbl +++ b/collects/web-server/scribblings/dispatchers.scrbl @@ -388,3 +388,62 @@ a URL that refreshes the password file, servlet cache, etc.} dispatcher/c]{ Returns a dispatcher that prints memory usage on every request. }} + +@; ------------------------------------------------------------ +@section[#:tag "limit.ss"]{Limiting Requests} +@a-dispatcher[web-server/dispatchers/limit + @elem{provides a wrapper dispatcher that limits how many requests are serviced at once.}]{ + +@defproc[(make [limit number?] + [inner dispatcher/c]) + dispatcher/c]{ + Returns a dispatcher that defers to @scheme[inner] for work, but will forward a maximum of @scheme[limit] requests concurrently. +}} + +@(require (for-label + web-server/web-server + web-server/http + (prefix-in limit: web-server/dispatchers/limit) + (prefix-in filter: web-server/dispatchers/dispatch-filter) + (prefix-in sequencer: web-server/dispatchers/dispatch-sequencer))) + +Consider this example: +@schememod[ + scheme + +(require web-server/web-server + web-server/http + web-server/http/response + (prefix-in limit: web-server/dispatchers/limit) + (prefix-in filter: web-server/dispatchers/dispatch-filter) + (prefix-in sequencer: web-server/dispatchers/dispatch-sequencer)) + +(serve #:dispatch + (sequencer:make + (filter:make + #rx"/limited" + (limit:make + 5 + (lambda (conn req) + (output-response/method + conn + (make-response/full + 200 "Okay" + (current-seconds) TEXT/HTML-MIME-TYPE + empty + (list (format "hello world ~a" + (sort (build-list 100000 (λ x (random 1000))) + <)))) + (request-method req))))) + (lambda (conn req) + (output-response/method + conn + (make-response/full 200 "Okay" + (current-seconds) TEXT/HTML-MIME-TYPE + empty + (list "Unlimited")) + (request-method req)))) + #:port 8080) + +(do-not-return) +] diff --git a/collects/web-server/scribblings/faq.scrbl b/collects/web-server/scribblings/faq.scrbl index dc9702e062..cb9fc203d5 100644 --- a/collects/web-server/scribblings/faq.scrbl +++ b/collects/web-server/scribblings/faq.scrbl @@ -104,28 +104,4 @@ The Web Server will start on port 443 (which can be overridden with the @exec{-p @section{How do I limit the number of requests serviced at once by the Web Server?} -There is no built-in option for this, but you can easily accomplish it if you assemble your own dispatcher -by wrapping it in @scheme[call-with-semaphore]: -@schemeblock[ -(require - (prefix-in private: - web-server/private/web-server-structs)) -(define (make-limit-dispatcher num inner) - (let ([sem (make-semaphore num)]) - (lambda (conn req) - (parameterize - ([current-custodian - (private:current-server-custodian)]) - (thread - (lambda () - (call-with-semaphore - sem - (lambda () - (inner conn req))))))))) -] - -Once this function is available, rather than providing @scheme[james-gordon] as your dispatcher, you provide: -@scheme[(make-limit-dispatch 50 james-gordon)] (if you only want 50 concurrent requests.) One interesting -application of this pattern is to have a limit on certain kinds of requests. For example, you could have a -limit of 50 servlet requests, but no limit on filesystem requests. - +Refer to @secref["limit.ss"]. From 687eecd43c4fee0a0c03098a1785836cbc683360 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 20:28:12 +0000 Subject: [PATCH 29/38] svn: r13073 --- collects/teachpack/server.png | Bin 0 -> 29063 bytes collects/teachpack/{universe.png => world.png} | Bin 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 collects/teachpack/server.png rename collects/teachpack/{universe.png => world.png} (100%) diff --git a/collects/teachpack/server.png b/collects/teachpack/server.png new file mode 100644 index 0000000000000000000000000000000000000000..894bb0712246a757016092a3ce1277832836fb49 GIT binary patch literal 29063 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 literal 0 HcmV?d00001 diff --git a/collects/teachpack/universe.png b/collects/teachpack/world.png similarity index 100% rename from collects/teachpack/universe.png rename to collects/teachpack/world.png From 0e8cf2e1609aba4370ecf3649436a4548234185f Mon Sep 17 00:00:00 2001 From: Casey Klein Date: Mon, 12 Jan 2009 20:53:58 +0000 Subject: [PATCH 30/38] Updated docs to reflect that `check' is provided as `redex-check'. svn: r13074 --- collects/redex/redex.scrbl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/collects/redex/redex.scrbl b/collects/redex/redex.scrbl index 7e3101bfe5..467a38c27e 100644 --- a/collects/redex/redex.scrbl +++ b/collects/redex/redex.scrbl @@ -1042,7 +1042,7 @@ The optional keyword argument @scheme[attempt-num-expr] decisions made during generation (e.g., the expected length of @pattech[pattern-sequence]s increases with @scheme[attempt-num-expr]).} -@defform/subs[(check language #, @|ttpattern| property-expr kw-arg ...) +@defform/subs[(redex-check language #, @|ttpattern| property-expr kw-arg ...) ([kw-arg (code:line #:attempts attempts-expr) (code:line #:source metafunction) (code:line #:source relation-expr)]) @@ -1051,19 +1051,19 @@ decisions made during generation (e.g., the expected length of [relation-expr reduction-relation?])]{ Searches for a counterexample to @scheme[property-expr], interpreted as a predicate universally quantified over its free -@pattech[term]-variables. @scheme[check] chooses substitutions for +@pattech[term]-variables. @scheme[redex-check] chooses substitutions for these free @pattech[term]-variables by generating random terms matching @scheme[pattern] and extracting the sub-terms bound by the @pattech[names] and non-terminals in @scheme[pattern]. -@scheme[check] generates at most @scheme[attempts-expr] (default @scheme[100]) +@scheme[redex-check] generates at most @scheme[attempts-expr] (default @scheme[100]) random terms in its search. The size and complexity of terms it generates gradually increases with each failed attempt. -When the optional @scheme[#:source] argument is present, @scheme[check] +When the optional @scheme[#:source] argument is present, @scheme[redex-check] generates @math{10%} of its terms by randomly choosing a pattern from the left-hand sides the definition of the supplied metafunction or relation. -@scheme[check] raises an exception if a term generated from an alternate +@scheme[redex-check] raises an exception if a term generated from an alternate pattern does not match the @scheme[pattern].} @defproc[(check-reduction-relation From 17ad24945b9d7d0e4ce650df6da2873fe70a0076 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 12 Jan 2009 21:46:40 +0000 Subject: [PATCH 31/38] syntax-local-lift-require svn: r13075 --- .../scribblings/reference/stx-trans.scrbl | 18 +++ collects/scribblings/reference/syntax.scrbl | 2 +- collects/sirmail/readr.ss | 2 +- doc/release-notes/mzscheme/HISTORY.txt | 6 +- src/mred/wxme/wx_mline.cxx | 10 +- src/mzscheme/src/env.c | 99 ++++++++++++- src/mzscheme/src/error.c | 2 +- src/mzscheme/src/eval.c | 40 ++++-- src/mzscheme/src/module.c | 133 ++++++++++++++++-- src/mzscheme/src/schminc.h | 4 +- src/mzscheme/src/schpriv.h | 13 +- src/mzscheme/src/schvers.h | 4 +- 12 files changed, 293 insertions(+), 40 deletions(-) diff --git a/collects/scribblings/reference/stx-trans.scrbl b/collects/scribblings/reference/stx-trans.scrbl index a7183c2278..9ca81d5210 100644 --- a/collects/scribblings/reference/stx-trans.scrbl +++ b/collects/scribblings/reference/stx-trans.scrbl @@ -340,6 +340,24 @@ eventually expanded in an expression context. @transform-time[]} +@defproc[(syntax-local-lift-require [quoted-raw-require-spec any/c][stx syntax?]) + syntax?]{ + +Lifts a @scheme[#%require] form corresponding to +@scheme[quoted-raw-require-spec] to the top-level or to the top of the +module currently being expanded, wrapping it with @scheme[for-meta] if +the current expansion context is not @tech{phase level} 0. + +The resulting syntax object is the same as @scheme[stx], except that a +fresh @tech{syntax mark} is added. The same @tech{syntax mark} is +added to the lifted @scheme[#%require] form, so that the +@scheme[#%require] form can bind uses of imported identifiers in the +resulting syntax object (assuming that the lexical information of +@scheme[stx] includes the binding environment into which the +@scheme[#%require] is lifted). + +@transform-time[]} + @defproc[(syntax-local-name) (or/c symbol? #f)]{ Returns an inferred name for the expression position being diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index 77ed5e2701..59b70b3eaa 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -606,7 +606,7 @@ export name, though the same binding can be specified with the multiple symbolic names.} -@defform[(for-meta require-spec ...)]{See @scheme[require] and @scheme[provide].} +@defform[(for-meta phase-level require-spec ...)]{See @scheme[require] and @scheme[provide].} @defform[(for-syntax require-spec ...)]{See @scheme[require] and @scheme[provide].} @defform[(for-template require-spec ...)]{See @scheme[require] and @scheme[provide].} @defform[(for-label require-spec ...)]{See @scheme[require] and @scheme[provide].} diff --git a/collects/sirmail/readr.ss b/collects/sirmail/readr.ss index 08553388dd..8ede4cd3e5 100644 --- a/collects/sirmail/readr.ss +++ b/collects/sirmail/readr.ss @@ -1018,7 +1018,7 @@ (lambda (w e) (purge-marked/update-headers))) (send global-keymap add-function "gc" - (lambda (w e) (collect-garbage) (collect-garbage))) + (lambda (w e) (collect-garbage) (collect-garbage) (dump-memory-stats))) (send global-keymap add-function "show-memory-graph" (lambda (w e) (show-memory-graph))) diff --git a/doc/release-notes/mzscheme/HISTORY.txt b/doc/release-notes/mzscheme/HISTORY.txt index ebfcfd7801..28df148eb8 100644 --- a/doc/release-notes/mzscheme/HISTORY.txt +++ b/doc/release-notes/mzscheme/HISTORY.txt @@ -1,6 +1,5 @@ -Somewhere in there: - function contracts now preserve tail recursion in many cases; the - 'any' contract is no longer special. +Version 4.1.3.10 +Added syntax-local-lift-require Version 4.1.3.8 Added procedure-rename @@ -15,6 +14,7 @@ Version 4.1.3.6 Memory accounting changed to bias charges to parent instead of children Version 4.1.3.3 +Function contracts preserve tail recursion in many cases Added compile-context-preservation-enabled Added exception-backtrace support for x86_84+JIT Added scheme/package, scheme/splicing diff --git a/src/mred/wxme/wx_mline.cxx b/src/mred/wxme/wx_mline.cxx index afaa853190..60b7ac05cf 100644 --- a/src/mred/wxme/wx_mline.cxx +++ b/src/mred/wxme/wx_mline.cxx @@ -321,7 +321,7 @@ void wxMediaLine::Delete(wxMediaLine **root) else x = v->right; - x->parent = v->parent; + x->parent = v->parent; /* x could be NIL; fixup at end */ if (PTREQ(v->parent, NIL)) *root = x; @@ -448,6 +448,11 @@ void wxMediaLine::Delete(wxMediaLine **root) SET_BLACK(x); } + if (PTRNE(NIL->parent, NIL)) { + /* fixup: we set NIL's parent above */ + NIL->parent = NIL; + } + right = left = NIL; DELETE_OBJ this; } @@ -594,7 +599,8 @@ wxMediaParagraph *wxMediaLine::GetParagraphStyle(Bool *first) } else { \ node = node->parent; \ } \ - } \ + } + void wxMediaLine::SetLength(long len) { diff --git a/src/mzscheme/src/env.c b/src/mzscheme/src/env.c index 2cd890ec5c..90aff15d8e 100644 --- a/src/mzscheme/src/env.c +++ b/src/mzscheme/src/env.c @@ -110,6 +110,7 @@ static Scheme_Object *local_module_expanding_provides(int argc, Scheme_Object *a static Scheme_Object *local_lift_expr(int argc, Scheme_Object *argv[]); static Scheme_Object *local_lift_context(int argc, Scheme_Object *argv[]); static Scheme_Object *local_lift_end_statement(int argc, Scheme_Object *argv[]); +static Scheme_Object *local_lift_require(int argc, Scheme_Object *argv[]); static Scheme_Object *make_introducer(int argc, Scheme_Object *argv[]); static Scheme_Object *local_make_delta_introduce(int argc, Scheme_Object *argv[]); static Scheme_Object *make_set_transformer(int argc, Scheme_Object *argv[]); @@ -550,6 +551,7 @@ static void make_kernel_env(void) GLOBAL_PRIM_W_ARITY("syntax-local-lift-expression", local_lift_expr, 1, 1, env); GLOBAL_PRIM_W_ARITY("syntax-local-lift-context", local_lift_context, 0, 0, env); GLOBAL_PRIM_W_ARITY("syntax-local-lift-module-end-declaration", local_lift_end_statement, 1, 1, env); + GLOBAL_PRIM_W_ARITY("syntax-local-lift-require", local_lift_require, 2, 2, env); { Scheme_Object *sym; @@ -1366,7 +1368,7 @@ scheme_add_compilation_binding(int index, Scheme_Object *val, Scheme_Comp_Env *f } void scheme_frame_captures_lifts(Scheme_Comp_Env *env, Scheme_Lift_Capture_Proc cp, Scheme_Object *data, - Scheme_Object *end_stmts, Scheme_Object *context_key) + Scheme_Object *end_stmts, Scheme_Object *context_key, Scheme_Object *requires) { Scheme_Lift_Capture_Proc *pp; Scheme_Object *vec; @@ -1374,16 +1376,45 @@ void scheme_frame_captures_lifts(Scheme_Comp_Env *env, Scheme_Lift_Capture_Proc pp = (Scheme_Lift_Capture_Proc *)scheme_malloc_atomic(sizeof(Scheme_Lift_Capture_Proc)); *pp = cp; - vec = scheme_make_vector(5, NULL); + vec = scheme_make_vector(7, NULL); SCHEME_VEC_ELS(vec)[0] = scheme_null; SCHEME_VEC_ELS(vec)[1] = (Scheme_Object *)pp; SCHEME_VEC_ELS(vec)[2] = data; SCHEME_VEC_ELS(vec)[3] = end_stmts; SCHEME_VEC_ELS(vec)[4] = context_key; + SCHEME_VEC_ELS(vec)[5] = (requires ? requires : scheme_false); + SCHEME_VEC_ELS(vec)[6] = scheme_null; /* accumulated requires */ COMPILE_DATA(env)->lifts = vec; } +void scheme_propagate_require_lift_capture(Scheme_Comp_Env *orig_env, Scheme_Comp_Env *env) +{ + while (orig_env) { + if ((COMPILE_DATA(orig_env)->lifts) + && SCHEME_TRUEP(SCHEME_VEC_ELS(COMPILE_DATA(orig_env)->lifts)[5])) + break; + orig_env = orig_env->next; + } + + if (orig_env) { + Scheme_Object *vec, *p; + + p = scheme_make_raw_pair(NULL, (Scheme_Object *)orig_env); + + vec = scheme_make_vector(7, NULL); + SCHEME_VEC_ELS(vec)[0] = scheme_false; + SCHEME_VEC_ELS(vec)[1] = scheme_void; + SCHEME_VEC_ELS(vec)[2] = scheme_void; + SCHEME_VEC_ELS(vec)[3] = scheme_false; + SCHEME_VEC_ELS(vec)[4] = scheme_false; + SCHEME_VEC_ELS(vec)[5] = p; /* (rcons NULL env) => continue with env */ + SCHEME_VEC_ELS(vec)[6] = scheme_null; + + COMPILE_DATA(env)->lifts = vec; + } +} + Scheme_Object *scheme_frame_get_lifts(Scheme_Comp_Env *env) { return SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[0]; @@ -1394,6 +1425,11 @@ Scheme_Object *scheme_frame_get_end_statement_lifts(Scheme_Comp_Env *env) return SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[3]; } +Scheme_Object *scheme_frame_get_require_lifts(Scheme_Comp_Env *env) +{ + return SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[6]; +} + void scheme_add_local_syntax(int cnt, Scheme_Comp_Env *env) { Scheme_Object **ns, **vs; @@ -4748,6 +4784,10 @@ local_lift_expr(int argc, Scheme_Object *argv[]) env = env->next; } + if (env) + if (SCHEME_FALSEP(SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[0])) + env = NULL; + if (!env) scheme_raise_exn(MZEXN_FAIL_CONTRACT, "syntax-local-lift-expression: no lift target"); @@ -4851,6 +4891,61 @@ local_lift_end_statement(int argc, Scheme_Object *argv[]) return scheme_void; } +static Scheme_Object *local_lift_require(int argc, Scheme_Object *argv[]) +{ + Scheme_Comp_Env *env; + Scheme_Object *local_mark, *mark, *data, *pr, *form; + long phase; + + if (!SCHEME_STXP(argv[1])) + scheme_wrong_type("syntax-local-lift-require", "syntax", 1, argc, argv); + + env = scheme_current_thread->current_local_env; + local_mark = scheme_current_thread->current_local_mark; + phase = env->genv->phase; + + if (!env) + scheme_raise_exn(MZEXN_FAIL_CONTRACT, + "syntax-local-lift-require: not currently transforming"); + + data = NULL; + + while (env) { + if (COMPILE_DATA(env)->lifts + && SCHEME_TRUEP(SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[5])) { + data = SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[5]; + if (SCHEME_RPAIRP(data) + && !SCHEME_CAR(data)) { + env = (Scheme_Comp_Env *)SCHEME_CDR(data); + } else + break; + } else + env = env->next; + } + + if (!env) + scheme_raise_exn(MZEXN_FAIL_CONTRACT, + "syntax-local-lift-requires: could not find target context"); + + + mark = scheme_new_mark(); + + if (SCHEME_RPAIRP(data)) + form = scheme_parse_lifted_require(argv[0], phase, mark, SCHEME_CAR(data)); + else + form = scheme_toplevel_require_for_expand(argv[0], phase, env, mark); + + pr = scheme_make_pair(form, SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[6]); + SCHEME_VEC_ELS(COMPILE_DATA(env)->lifts)[6] = pr; + + form = argv[1]; + form = scheme_add_remove_mark(form, local_mark); + form = scheme_add_remove_mark(form, mark); + form = scheme_add_remove_mark(form, local_mark); + + return form; +} + static Scheme_Object * make_set_transformer(int argc, Scheme_Object *argv[]) { diff --git a/src/mzscheme/src/error.c b/src/mzscheme/src/error.c index 4422763fbb..446d809fe4 100644 --- a/src/mzscheme/src/error.c +++ b/src/mzscheme/src/error.c @@ -1218,7 +1218,7 @@ char *scheme_make_arity_expect_string(Scheme_Object *proc, name = scheme_get_proc_name((Scheme_Object *)proc, &namelen, 1); #endif } else if (SCHEME_STRUCTP(proc)) { - name = proc; + name = (const char *)proc; mina = -1; maxa = 0; } else { diff --git a/src/mzscheme/src/eval.c b/src/mzscheme/src/eval.c index e93bcc8f90..2fc414ca14 100644 --- a/src/mzscheme/src/eval.c +++ b/src/mzscheme/src/eval.c @@ -4911,7 +4911,7 @@ static void *compile_k(void) int writeable, for_eval, rename, enforce_consts, comp_flags; Scheme_Env *genv; Scheme_Compile_Info rec, rec2; - Scheme_Object *o, *tl_queue; + Scheme_Object *o, *rl, *tl_queue; Scheme_Compilation_Top *top; Resolve_Prefix *rp; Resolve_Info *ri; @@ -4973,7 +4973,8 @@ static void *compile_k(void) find one, break it up to eval first expression before the rest. */ while (1) { - scheme_frame_captures_lifts(cenv, scheme_make_lifted_defn, scheme_sys_wraps(cenv), scheme_false, scheme_false); + scheme_frame_captures_lifts(cenv, scheme_make_lifted_defn, scheme_sys_wraps(cenv), + scheme_false, scheme_false, scheme_null); form = scheme_check_immediate_macro(form, cenv, &rec, 0, 0, &gval, NULL, NULL); @@ -4989,10 +4990,13 @@ static void *compile_k(void) } else break; } else { + rl = scheme_frame_get_require_lifts(cenv); o = scheme_frame_get_lifts(cenv); - if (!SCHEME_NULLP(o)) { + if (!SCHEME_NULLP(o) + || !SCHEME_NULLP(rl)) { tl_queue = scheme_make_pair(form, tl_queue); tl_queue = scheme_append(o, tl_queue); + tl_queue = scheme_append(rl, tl_queue); form = SCHEME_CAR(tl_queue); tl_queue = SCHEME_CDR(tl_queue); } @@ -5010,7 +5014,8 @@ static void *compile_k(void) Scheme_Object *l, *prev_o = NULL; while (1) { - scheme_frame_captures_lifts(cenv, scheme_make_lifted_defn, scheme_sys_wraps(cenv), scheme_false, scheme_false); + scheme_frame_captures_lifts(cenv, scheme_make_lifted_defn, scheme_sys_wraps(cenv), + scheme_false, scheme_false, scheme_null); scheme_init_compile_recs(&rec, 0, &rec2, 1); @@ -5031,10 +5036,13 @@ static void *compile_k(void) /* If any definitions were lifted in the process of compiling o, we need to fold them in. */ l = scheme_frame_get_lifts(cenv); - if (!SCHEME_NULLP(l)) { - l = icons(scheme_datum_to_syntax(begin_symbol, scheme_false, scheme_sys_wraps(cenv), 0, 0), - l); - form = scheme_datum_to_syntax(l, scheme_false, scheme_false, 0, 0); + rl = scheme_frame_get_require_lifts(cenv); + if (!SCHEME_NULLP(l) + || !SCHEME_NULLP(rl)) { + l = scheme_append(rl, l); + rl = icons(scheme_datum_to_syntax(begin_symbol, scheme_false, scheme_sys_wraps(cenv), 0, 0), + rl); + form = scheme_datum_to_syntax(rl, scheme_false, scheme_false, 0, 0); prev_o = o; } else break; @@ -6213,7 +6221,7 @@ compile_expand_expr_lift_to_let(Scheme_Object *form, Scheme_Comp_Env *env, context_key = scheme_generate_lifts_key(); - scheme_frame_captures_lifts(inserted, pair_lifted, (Scheme_Object *)ip, scheme_false, context_key); + scheme_frame_captures_lifts(inserted, pair_lifted, (Scheme_Object *)ip, scheme_false, context_key, NULL); if (rec[drec].comp) { scheme_init_compile_recs(rec, drec, recs, 2); @@ -8877,7 +8885,9 @@ static void *expand_k(void) erec1.comp_flags = comp_flags; if (catch_lifts_key) - scheme_frame_captures_lifts(env, scheme_make_lifted_defn, scheme_sys_wraps(env), scheme_false, catch_lifts_key); + scheme_frame_captures_lifts(env, scheme_make_lifted_defn, scheme_sys_wraps(env), + scheme_false, catch_lifts_key, + (!as_local && catch_lifts_key) ? scheme_null : NULL); if (just_to_top) { Scheme_Object *gval; @@ -8886,9 +8896,12 @@ static void *expand_k(void) obj = scheme_expand_expr(obj, env, &erec1, 0); if (catch_lifts_key) { - Scheme_Object *l; + Scheme_Object *l, *rl; l = scheme_frame_get_lifts(env); - if (SCHEME_PAIRP(l)) { + rl = scheme_frame_get_require_lifts(env); + if (SCHEME_PAIRP(l) + || SCHEME_PAIRP(rl)) { + l = scheme_append(rl, l); obj = add_lifts_as_begin(obj, l, env); SCHEME_EXPAND_OBSERVE_LIFT_LOOP(erec1.observer,obj); if ((depth >= 0) || as_local) @@ -9189,6 +9202,7 @@ do_local_expand(const char *name, int for_stx, int catch_lifts, int for_expr, in if (for_stx) { scheme_prepare_exp_env(env->genv); env = scheme_new_comp_env(env->genv->exp_env, env->insp, 0); + scheme_propagate_require_lift_capture(orig_env, env); } if (for_expr) @@ -9322,7 +9336,7 @@ do_local_expand(const char *name, int for_stx, int catch_lifts, int for_expr, in if (catch_lifts_key) scheme_frame_captures_lifts(env, scheme_make_lifted_defn, scheme_sys_wraps(env), scheme_false, - catch_lifts_key); + catch_lifts_key, NULL); memset(drec, 0, sizeof(drec)); drec[0].value_name = scheme_false; /* or scheme_current_thread->current_local_name ? */ diff --git a/src/mzscheme/src/module.c b/src/mzscheme/src/module.c index 98efadf023..2398ea2ba4 100644 --- a/src/mzscheme/src/module.c +++ b/src/mzscheme/src/module.c @@ -5749,6 +5749,76 @@ static Scheme_Object *add_lifted_defn(Scheme_Object *data, Scheme_Object **_id, return scheme_make_lifted_defn(scheme_sys_wraps(env), _id, expr, _env); } +static Scheme_Object *make_require_form(Scheme_Object *module_path, long phase, Scheme_Object *mark) +{ + Scheme_Object *e = module_path; + + if (phase != 0) { + e = scheme_make_pair(for_meta_symbol, + scheme_make_pair(scheme_make_integer(phase), + scheme_make_pair(e, + scheme_null))); + } + e = scheme_make_pair(require_stx, scheme_make_pair(e, scheme_null)); + e = scheme_datum_to_syntax(e, scheme_false, scheme_false, 0, 0); + + e = scheme_add_remove_mark(e, mark); + + return e; +} + +Scheme_Object *scheme_parse_lifted_require(Scheme_Object *module_path, + long phase, + Scheme_Object *mark, + void *data) +{ + Scheme_Object *e; + Scheme_Object *base_modidx = (Scheme_Object *)((void **)data)[1]; + Scheme_Env *env = (Scheme_Env *)((void **)data)[2]; + Scheme_Module *for_m = (Scheme_Module *)((void **)data)[3]; + Scheme_Object *rns = (Scheme_Object *)((void **)data)[4]; + Scheme_Object *post_ex_rns = (Scheme_Object *)((void **)data)[5]; + void *tables = ((void **)data)[6]; + Scheme_Object *redef_modname = (Scheme_Object *)((void **)data)[7]; + int *all_simple = (int *)((void **)data)[8]; + + e = make_require_form(module_path, phase, mark); + + parse_requires(e, base_modidx, env, for_m, + rns, post_ex_rns, + check_require_name, tables, + redef_modname, + 0, 0, 1, 0, + all_simple); + + return e; +} + +static Scheme_Object *package_require_data(Scheme_Object *base_modidx, + Scheme_Env *env, + Scheme_Module *for_m, + Scheme_Object *rns, Scheme_Object *post_ex_rns, + void *data, + Scheme_Object *redef_modname, + int *all_simple) +{ + void **vals; + + vals = MALLOC_N(void*, 9); + vals[0] = NULL; /* this slot is available */ + vals[1] = base_modidx; + vals[2] = env; + vals[3] = for_m; + vals[4] = rns; + vals[5] = post_ex_rns; + vals[6] = data; + vals[7] = redef_modname; + vals[8] = all_simple; + + return scheme_make_raw_pair((Scheme_Object *)vals, NULL); +} + + static void flush_definitions(Scheme_Env *genv) { if (genv->syntax) { @@ -5786,9 +5856,10 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Object *exclude_hint = scheme_false, *lift_data; Scheme_Object **exis, **et_exis, **exsis; Scheme_Object *lift_ctx; + Scheme_Object *lifted_reqs = scheme_null, *req_data; int exicount, et_exicount, exsicount; char *exps, *et_exps; - int all_simple_renames = 1; + int *all_simple_renames; int maybe_has_lifts = 0; int reprovide_kernel; Scheme_Object *redef_modname; @@ -5931,6 +6002,15 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, maybe_has_lifts = 0; lift_ctx = scheme_generate_lifts_key(); + all_simple_renames = (int *)scheme_malloc_atomic(sizeof(int)); + *all_simple_renames = 1; + + req_data = package_require_data(self_modidx, env->genv, env->genv->module, + rn_set, post_ex_rn_set, + tables, + redef_modname, + all_simple_renames); + /* Pass 1 */ /* Partially expand all expressions, and process definitions, requires, @@ -5949,7 +6029,8 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, p = (maybe_has_lifts ? scheme_frame_get_end_statement_lifts(xenv) : scheme_null); - scheme_frame_captures_lifts(xenv, scheme_make_lifted_defn, scheme_sys_wraps(xenv), p, lift_ctx); + scheme_frame_captures_lifts(xenv, scheme_make_lifted_defn, scheme_sys_wraps(xenv), + p, lift_ctx, req_data); maybe_has_lifts = 1; { @@ -5966,11 +6047,13 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, e = scheme_expand_expr(e, xenv, &erec1, 0); } + lifted_reqs = scheme_append(scheme_frame_get_require_lifts(xenv), lifted_reqs); + fst = scheme_frame_get_lifts(xenv); if (!SCHEME_NULLP(fst)) { /* Expansion lifted expressions, so add them to the front and try again. */ - all_simple_renames = 0; + *all_simple_renames = 0; fm = SCHEME_STX_CDR(fm); e = scheme_add_rename(e, post_ex_rn_set); fm = scheme_named_map_1(NULL, add_a_rename, fm, post_ex_rn_set); @@ -6066,7 +6149,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, /* Add a renaming: */ if (!SAME_OBJ(SCHEME_STX_VAL(orig_name), name)) { scheme_extend_module_rename(post_ex_rn, self_modidx, name, name, self_modidx, name, 0, NULL, NULL, 0); - all_simple_renames = 0; + *all_simple_renames = 0; } else scheme_extend_module_rename(rn, self_modidx, name, name, self_modidx, name, 0, NULL, NULL, 0); @@ -6102,6 +6185,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, scheme_prepare_exp_env(env->genv); eenv = scheme_new_comp_env(env->genv->exp_env, env->insp, 0); + scheme_frame_captures_lifts(eenv, NULL, NULL, scheme_false, scheme_false, req_data); oenv = (for_stx ? eenv : env); @@ -6148,7 +6232,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, if (!SAME_OBJ(SCHEME_STX_VAL(orig_name), name)) { scheme_extend_module_rename(for_stx ? post_ex_et_rn : post_ex_rn, self_modidx, name, name, self_modidx, name, for_stx ? 1 : 0, NULL, NULL, 0); - all_simple_renames = 0; + *all_simple_renames = 0; } else scheme_extend_module_rename(for_stx ? et_rn : rn, self_modidx, name, name, self_modidx, name, for_stx ? 1 : 0, NULL, NULL, 0); @@ -6186,6 +6270,8 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, } m = scheme_compile_expr_lift_to_let(code, eenv, &mrec, 0); + lifted_reqs = scheme_append(scheme_frame_get_require_lifts(eenv), lifted_reqs); + oi = scheme_optimize_info_create(); oi->context = (Scheme_Object *)env->genv->module; if (!(rec[drec].comp_flags & COMP_CAN_INLINE)) @@ -6243,7 +6329,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, check_require_name, tables, redef_modname, 0, 0, 1, 0, - &all_simple_renames); + all_simple_renames); if (rec[drec].comp) e = NULL; @@ -6361,7 +6447,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, l = (maybe_has_lifts ? scheme_frame_get_end_statement_lifts(cenv) : scheme_null); - scheme_frame_captures_lifts(cenv, add_lifted_defn, lift_data, l, lift_ctx); + scheme_frame_captures_lifts(cenv, add_lifted_defn, lift_data, l, lift_ctx, req_data); maybe_has_lifts = 1; if (kind == 2) @@ -6380,6 +6466,8 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, erec1.value_name = scheme_false; e = scheme_expand_expr(e, nenv, &erec1, 0); } + + lifted_reqs = scheme_append(scheme_frame_get_require_lifts(xenv), lifted_reqs); l = scheme_frame_get_lifts(cenv); if (SCHEME_NULLP(l)) { @@ -6389,7 +6477,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, p = SCHEME_CDR(p); } else { /* Lifts - insert them and try again */ - all_simple_renames = 0; + *all_simple_renames = 0; SCHEME_EXPAND_OBSERVE_MODULE_LIFT_LOOP(observer, scheme_copy_list(l)); e = scheme_make_pair(e, scheme_make_integer(0)); /* don't re-compile/-expand */ SCHEME_CAR(p) = e; @@ -6632,7 +6720,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, env->genv->module->indirect_provides = exis; env->genv->module->num_indirect_provides = exicount; - if (all_simple_renames) { + if (*all_simple_renames) { env->genv->module->indirect_syntax_provides = exsis; env->genv->module->num_indirect_syntax_provides = exsicount; } else { @@ -6645,7 +6733,7 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, env->genv->module->comp_prefix = cenv->prefix; - if (all_simple_renames) { + if (*all_simple_renames) { env->genv->module->rn_stx = scheme_true; } @@ -6659,6 +6747,13 @@ static Scheme_Object *do_module_begin(Scheme_Object *form, Scheme_Comp_Env *env, } p = SCHEME_STX_CAR(form); + + /* Add lifted requires */ + if (!SCHEME_NULLP(lifted_reqs)) { + lifted_reqs = scheme_reverse(lifted_reqs); + first = scheme_append(lifted_reqs, first); + } + return scheme_datum_to_syntax(cons(p, first), form, form, 0, 2); } } @@ -9045,10 +9140,10 @@ static Scheme_Object *do_require(Scheme_Object *form, Scheme_Comp_Env *env, 0, 0, 0, 0, NULL); - if (rec[drec].comp) { + if (rec && rec[drec].comp) { /* Dummy lets us access a top-level environment: */ dummy = scheme_make_environment_dummy(env); - + scheme_compile_rec_done_local(rec, drec); scheme_default_compile_rec(rec, drec); return scheme_make_syntax_compiled(REQUIRE_EXPD, @@ -9071,6 +9166,20 @@ require_expand(Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Expand_Info *er return do_require(form, env, erec, drec); } +Scheme_Object *scheme_toplevel_require_for_expand(Scheme_Object *module_path, + long phase, + Scheme_Comp_Env *cenv, + Scheme_Object *mark) +{ + Scheme_Object *form; + + form = make_require_form(module_path, phase, mark); + + do_require(form, cenv, NULL, 0); + + return form; +} + /**********************************************************************/ /* dummy forms */ /**********************************************************************/ diff --git a/src/mzscheme/src/schminc.h b/src/mzscheme/src/schminc.h index 5f08fc194b..33581e2922 100644 --- a/src/mzscheme/src/schminc.h +++ b/src/mzscheme/src/schminc.h @@ -11,9 +11,9 @@ EXPECTED_PRIM_COUNT to the new value, and then USE_COMPILED_STARTUP can be set to 1 again. */ -#define USE_COMPILED_STARTUP 1 +#define USE_COMPILED_STARTUP 0 -#define EXPECTED_PRIM_COUNT 945 +#define EXPECTED_PRIM_COUNT 946 #ifdef MZSCHEME_SOMETHING_OMITTED # undef USE_COMPILED_STARTUP diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index 301079be72..ccd049a4ca 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -2065,11 +2065,22 @@ Scheme_Object *scheme_env_frame_uid(Scheme_Comp_Env *env); typedef Scheme_Object *(*Scheme_Lift_Capture_Proc)(Scheme_Object *, Scheme_Object **, Scheme_Object *, Scheme_Comp_Env *); void scheme_frame_captures_lifts(Scheme_Comp_Env *env, Scheme_Lift_Capture_Proc cp, Scheme_Object *data, - Scheme_Object *end_stmts, Scheme_Object *context_key); + Scheme_Object *end_stmts, Scheme_Object *context_key, Scheme_Object *require_lifts); +void scheme_propagate_require_lift_capture(Scheme_Comp_Env *orig_env, Scheme_Comp_Env *env); Scheme_Object *scheme_frame_get_lifts(Scheme_Comp_Env *env); Scheme_Object *scheme_frame_get_end_statement_lifts(Scheme_Comp_Env *env); +Scheme_Object *scheme_frame_get_require_lifts(Scheme_Comp_Env *env); Scheme_Object *scheme_generate_lifts_key(void); +Scheme_Object *scheme_toplevel_require_for_expand(Scheme_Object *module_path, + long phase, + Scheme_Comp_Env *cenv, + Scheme_Object *mark); +Scheme_Object *scheme_parse_lifted_require(Scheme_Object *module_path, + long phase, + Scheme_Object *mark, + void *data); + void scheme_add_local_syntax(int cnt, Scheme_Comp_Env *env); void scheme_set_local_syntax(int pos, Scheme_Object *name, Scheme_Object *val, Scheme_Comp_Env *env); diff --git a/src/mzscheme/src/schvers.h b/src/mzscheme/src/schvers.h index 0583c45695..cd5cfe3196 100644 --- a/src/mzscheme/src/schvers.h +++ b/src/mzscheme/src/schvers.h @@ -13,12 +13,12 @@ consistently.) */ -#define MZSCHEME_VERSION "4.1.3.9" +#define MZSCHEME_VERSION "4.1.3.10" #define MZSCHEME_VERSION_X 4 #define MZSCHEME_VERSION_Y 1 #define MZSCHEME_VERSION_Z 3 -#define MZSCHEME_VERSION_W 9 +#define MZSCHEME_VERSION_W 10 #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W) From 0b4a67fc216b1d20547e8b1ca79ea266736d965c Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 22:10:39 +0000 Subject: [PATCH 32/38] svn: r13076 --- .../2htdp/scribblings/universe.scrbl | 130 +++++++--- collects/teachpack/balls.ss | 59 +++++ collects/teachpack/door.ss | 59 +++++ collects/teachpack/nuworld.ss | 119 +++++++++ collects/teachpack/server.ss | 228 ++++++++++++++++++ collects/teachpack/server2.png | Bin 17544 -> 0 bytes collects/teachpack/universe2.png | Bin 19411 -> 0 bytes collects/teachpack/world.png | Bin 28263 -> 15606 bytes collects/teachpack/world.ss | 200 +++++++++++++++ 9 files changed, 758 insertions(+), 37 deletions(-) create mode 100644 collects/teachpack/balls.ss create mode 100644 collects/teachpack/door.ss create mode 100644 collects/teachpack/nuworld.ss create mode 100644 collects/teachpack/server.ss delete mode 100644 collects/teachpack/server2.png delete mode 100644 collects/teachpack/universe2.png create mode 100644 collects/teachpack/world.ss diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index d16ed79e53..3547e2a548 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -1146,7 +1146,7 @@ From the perspective of the @tech{universe}, the design of a protocol is about the design of data representations for tracking universe information in the server and the participating worlds and the design of a data representation for messages. As for the latter, we know that they must be - @tech{S-expression}s, but of course @tech{world} programs don't send all + @tech{S-expression}s, but usually @tech{world} programs don't send all kinds of @tech{S-expression}s. The data definitions for messages must therefore select a subset of suitable @tech{S-expression}s. As for the state of the server and the worlds, they must reflect how they currently @@ -1164,8 +1164,8 @@ server tracks, call it @tech{UniverseState};} to the universe;} @item{data definitions for the messages that are sent from the server to -the worlds and vice versa. Let's call them @deftech{MsgS2W} for messages -from the server to the worlds and @deftech{MsgW2S} for the other direction; +the worlds and vice versa. Let's call them @deftech{S2W} for messages +from the server to the worlds and @deftech{W2S} for the other direction; in the most general case you may need one pair per world.} ] @@ -1185,7 +1185,22 @@ The second step of a protocol design is to figure out which major state of the world. A good tool for writing down these agreements is an interaction diagram. -(interaction diagrams: tbd) + +@verbatim{ + + Server World1 World2 + | | | + | 'go | | + |<------------------| | + | 'go | | + |------------------------------------------>| + | | | + | | | +} + + Each vertical line is the life line of a @tech{world} program or the + @tech{server}. Each horizontal arrow denotes a message sent from one + @tech{universe} participant to another. The design of the protocol, especially the data definitions, have direct implications for the design of event handling functions. For example, in @@ -1196,19 +1211,20 @@ translates into the design of two functions with the following headers, @(begin #reader scribble/comment-reader (schemeblock -;; @tech{UniverseState} world? -> (make-bundle [Listof world?] @tech{UniverseState} [Listof mail?]) -;; create new @tech{UniverseState} when world w is joining the universe, -;; which is in state s; also send mails as needed +;; Bundle is +;; (make-bundle [Listof world?] UniverseState [Listof mail?]) + +;; [Listof world?] UniverseState world? -> Bundle +;; compute next list of worlds and new @tech{UniverseState} +;; when world w is joining the universe, which is in state s; (define (add-world s w) ...) -;; @tech{UniverseState} world? MsgW2U -> (make-bundle [Listof world?] @tech{UniverseState} [Listof mail?]) -;; create new @tech{UniverseState} when world w is sending message m -;; to universe in state s; also send mails as needed +;; [Listof world?] UniverseState world? W2U -> Bundle +;; compute next list of worlds and new @tech{UniverseState} +;; when world w is sending message m to universe in state s (define (process s p m) ...) )) -Note how both functions return a @emph{bundle}. - Finally, we must also decide how the messages affect the states of the worlds; which of their callback may send messages and when; and what to do with the messages a world receives. Because this step is difficult to @@ -1228,10 +1244,14 @@ As for the server's state, it must obviously keep track of all @tech{world}s tha are passive. Of course, initially the @tech{universe} is empty, i.e., there are no @tech{world}s and, at that point, the server has nothing to track. -While there are many different useful ways of representing such a @tech{universe}, - we choose to introduce @tech{UniverseState} as a list of @tech{world}s, and we - interpret non-empty lists as those where the first @tech{world} is active and the - remainder are the passive @tech{world}s. As for the two possible events, +While there are many different useful ways of representing such a + @tech{universe}, we just use the list of @emph{worlds} that is handed to + each handler and that handlers return via their bundles. The + @tech{UniverseState} itself is useless for this trivial example. We + interpret non-empty lists as those where the first @tech{world} is active + and the remainder are the passive @tech{world}s. As for the two possible + events, + @itemize[ @item{it is natural to add new @tech{world}s to the end of the list; and} @@ -1263,6 +1283,34 @@ for this part of a @tech{world}'s state until we design its ``local'' behavior.} which it may ignore. When it is done with its turn, it will send a message. +@verbatim{ + Server + | World1 + |<==================| + | 'it-is-your-turn | + |------------------>| + | | World2 + |<==========================================| + | 'done | | + |<------------------| | + | 'it-is-your-turn | | + |------------------------------------------>| + | | | + | | | + | 'done | | + |<------------------------------------------| + | 'it-is-your-turn | | + |------------------>| | + | | | + | | | +} + +Here the double-lines (horizontal) denote the registration step, the others + are message exchanges. The diagram thus shows how the @tech{server} + decides to make the first registered world the active one and to enlist + all others as they join. + + @; ----------------------------------------------------------------------------- @subsection{Designing the Ball Server} @@ -1273,7 +1321,7 @@ The preceding subsection dictates that our server program starts like this: [schemeblock ;; teachpack: universe.ss -;; UniverseState is [Listof world?] +;; UniverseState is '* ;; StopMessage is 'done. ;; GoMessage is 'it-is-your-turn. ]) @@ -1289,24 +1337,22 @@ The preceding subsection dictates that our server program starts like this: #reader scribble/comment-reader [schemeblock ;; Result is -;; (make-bundle [Listof world?] UniverseState (list (make-mail world? GoMessage))) +;; (make-bundle [Listof world?] '* (list (make-mail world? GoMessage))) -;; UniverseState world? -> Result +;; [Listof world?] UniverseState world? -> Result ;; add world w to the universe, when server is in state u (define (add-world u w) ...) -;; UniverseState world? StopMessage -> Result +;; [Listof world?] UniverseState world? StopMessage -> Result ;; world w sent message m when server is in state u (define (switch u w m) ...) ]) Although we could have re-used the generic contracts from this documentation, we also know from our protocol that our server sends a -message to exactly one world. For this reason, both functions return the -same kind of result: a bundle that contains the new state of the server -(@tech{UniverseState}) and a list that contains a single mail. These contracts -are just refinements of the generic ones. (A type-oriented programmer would -say that the contracts here are subtypes of the generic ones.) +message to exactly one world. Note how these contracts are just refinements +of the generic ones. (A type-oriented programmer would say that the +contracts here are subtypes of the generic ones.) The second step of the design recipe calls for functional examples: @@ -1316,13 +1362,15 @@ The second step of the design recipe calls for functional examples: ;; an obvious example for adding a world: (check-expect (add-world '() '* world1) - (make-bundle (list world1) '* + (make-bundle (list world1) + '* (list (make-mail world1 'it-is-your-turn)))) ;; an example for receiving a message from the active world: (check-expect (switch (list world1 world2) '* world1 'it-is-your-turn) - (make-bundle (list world2 world1) '* + (make-bundle (list world2 world1) + '* (list (make-mail world2 'it-is-your-turn)))) ]) @@ -1335,23 +1383,24 @@ Exercise: Create additional examples for the two functions based on our protocol. The protocol tells us that @emph{add-world} just adds the given -@emph{world} structure---recall that this a data representation of the -actual @tech{world} program---to the @tech{UniverseState} and then sends a -message to the first world on this list to get things going: + @emph{world} structure---recall that this a data representation of the + actual @tech{world} program---to the given list of worlds. It then sends a + message to the first world on this list to get things going: @(begin #reader scribble/comment-reader [schemeblock -(define (add-world univ wrld) +(define (add-world univ state wrld) (local ((define univ* (append univ (list wrld)))) - (make-bundle univ* '* + (make-bundle univ* + '* (list (make-mail (first univ*) 'it-is-your-turn))))) ]) Because @emph{univ*} contains at least @emph{wrld}, it is acceptable to create a mail to @scheme[(first univ*)]. Of course, this same reasoning also implies that if @emph{univ} isn't empty, its first element is an -active world and has already received such a message. +active world and is about to receive a second @scheme['it-is-your-turn] message. Similarly, the protocol says that when @emph{switch} is invoked because a @tech{world} program sends a message, the data representation of the @@ -1361,15 +1410,16 @@ Similarly, the protocol says that when @emph{switch} is invoked because a @(begin #reader scribble/comment-reader [schemeblock -(define (switch univ wrld m) +(define (switch univ state wrld m) (local ((define univ* (append (rest univ) (list (first univ))))) - (make-bundle univ* '* + (make-bundle univ* + '* (list (make-mail (first univ*) 'it-is-your-turn))))) ]) As before, appending the first world to the end of the list guarantees - that there is at least this one world on the next @tech{UniverseState} - (state). It is therefore acceptable to create a mail for this world. + that there is at least this one world on this list. It is therefore + acceptable to create a mail for this world. Exercise: The function definition simply assumes that @emph{wrld} is @scheme[world=?] to @scheme[(first univ)] and that the received message @@ -1382,6 +1432,12 @@ Exercise: The function definition simply assumes that @emph{wrld} is depends on the context. For now, stop the @tech{universe} at this point, but consider alternative solutions, too.) +Exercise: An alternative state representation would equate + @tech{UniverseState} with @emph{world} structures, keeping track of the + active world. The list of world in the server would track the passive + worlds only. Design appropriate @scheme[add-world] and @scheme[switch] + functions. + @; ----------------------------------------------------------------------------- @subsection{Designing the Ball World} diff --git a/collects/teachpack/balls.ss b/collects/teachpack/balls.ss new file mode 100644 index 0000000000..a0e3bda180 --- /dev/null +++ b/collects/teachpack/balls.ss @@ -0,0 +1,59 @@ +;; The first three lines of this file were inserted by DrScheme. They record metadata +;; about the language level of this file in a form that our tools can easily process. +#reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname balls) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ()))) +(require (lib "world.ss" "htdp")) + +;; constants +(define height 50) +(define delta 80) +(define width (+ delta (* 2 height))) + +(define left (quotient height 2)) +(define right (+ height delta left)) + +;; World = (make-posn left Number) | (make-posn right Number) + +(define server (text "server" 11 'black)) +(define server* (overlay server (nw:rectangle (image-width server) (image-height server) 'outline 'black))) + +;; visual constants +(define bg + (place-image + (text "universe" 11 'green) + 60 0 + (place-image + server* + (+ height 15) 20 + (place-image + (text "left" 11 'blue) + 10 10 + (place-image + (text "right" 11 'red) + (+ height delta 10) 10 + (place-image + (nw:rectangle delta height 'solid 'white) + height 0 + (place-image + (nw:rectangle width height 'solid 'gray) + 0 0 + (empty-scene width height)))))))) + +(define ball (circle 3 'solid 'red)) + +;; World -> Scene +(define (draw w) + (place-image ball (posn-x w) (posn-y w) bg)) + + +;; World -> World +(define (tick w) + (local ((define y (posn-y w)) + (define x (posn-x w))) + (cond + [(> y 0) (make-posn x (- y 1))] + [(= x left) (make-posn right height)] + [(= x right) (make-posn left height)]))) + +(big-bang width height 1/66 (make-posn left height) true) +(on-redraw draw) +(on-tick-event tick) diff --git a/collects/teachpack/door.ss b/collects/teachpack/door.ss new file mode 100644 index 0000000000..6fd029e6a5 --- /dev/null +++ b/collects/teachpack/door.ss @@ -0,0 +1,59 @@ +#lang slideshow + +(require slideshow/pict) + +(define DELTA 40) +(define FT 12) + +; (fsa "unlock" "lock" "push" "tick") +(define (fsa L C O unlock lock push tick) + (define (make-state txt) + (define t (text txt '() FT)) + (define e (rounded-rectangle (+ 10 (pict-width t)) (+ 10 (pict-height t)))) + (cc-superimpose t e)) + + (define locked (make-state L)) + (define closed (make-state C)) + (define open (make-state O)) + + (define bg (rectangle (+ (pict-width locked) (* 2 DELTA)) + (+ (pict-height locked) + (pict-height closed) + (pict-height open) + (* 3 DELTA)))) + + (define width (pict-width bg)) + + (define (center base state y) + (define w (pict-width state)) + (define d (quotient (- width w) 2)) + (pin-over base d y state)) + + (define nx + (center + (center + (center + bg locked (/ DELTA 2)) + closed + (+ (/ DELTA 2) (pict-height locked) DELTA)) + open + (+ (/ DELTA 2) DELTA (pict-height locked) DELTA (pict-height closed)))) + + (define (add-labeled-arrow nx locked lb-find closed lt-find txt) + (define-values (x0 y0) (lb-find nx locked)) + (define-values (x1 y1) (lt-find nx closed)) + (define lbl (text txt '() (- FT 2))) + (define wlbl (pict-width lbl)) + (define hlbl (pict-height lbl)) + (define x (- x0 (/ wlbl 2))) + (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) + (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) + + (define l1 (add-labeled-arrow nx locked lb-find closed lt-find unlock)) + (define l2 (add-labeled-arrow l1 closed lb-find open lt-find push)) + (define l3 (add-labeled-arrow l2 open rt-find closed rb-find tick)) + (define l4 (add-labeled-arrow l3 closed rt-find locked rb-find lock)) + l4) + +(fsa "locked" "closed" "open" "unlock" "lock" "push" "time") +(fsa "'locked" "'closed" "'open" "#\\u" "#\\l" "#\\space" "tick") \ No newline at end of file diff --git a/collects/teachpack/nuworld.ss b/collects/teachpack/nuworld.ss new file mode 100644 index 0000000000..cbda2823b6 --- /dev/null +++ b/collects/teachpack/nuworld.ss @@ -0,0 +1,119 @@ +#lang slideshow + +(require slideshow/pict mred/mred) + +(define DELTA 80) +(define FT 12) + +(define txt + '("(big-bang World_0" + " (on-draw render WIDTH HEIGHT)" + " (on-tick tock RATE)" + " (on-mouse click)" + " (on-key react))" + )) + +(define program + (apply vl-append (map (lambda (t) (text t '() (- FT 2))) txt))) + +(define Program + (cc-superimpose + (rectangle (+ 5 (pict-width program)) (+ 5 (pict-height program))) + program)) + +(define (make-state txt) + (define t (text txt '() FT)) + (define e (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t)))) + (cc-superimpose t e)) + +(define False (text "FALSE" '() FT)) +(define True (text "TRUE" '() FT)) +(define BOOL (rectangle (+ 5 (pict-width False)) (+ 5 (pict-height False)))) + +;; String Boolean -> Pict +(define (make-state0 txt b) + ;; create the basic state + (define t (text txt '() FT)) + (define s (if b + (cc-superimpose + (rounded-rectangle (+ 5 (pict-width t)) (+ (- DELTA 5) (pict-height t))) + t) + t)) + (define w + (cc-superimpose + s + (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t))))) + ;; add the boolean + (define bb (cc-superimpose (if b True False) BOOL)) + (define ar (add-labeled-arrow (vc-append DELTA bb w) w ct-find bb cb-find "done")) + (define scene (text "Scene" '() FT)) + (define sc (cc-superimpose scene (rectangle (+ 20 (pict-width scene)) (+ 30 (pict-height scene))))) + (define br (add-labeled-arrow (vc-append DELTA ar sc) ar cb-find sc ct-find "render")) + br) + +(define (add-labeled-arrow nx locked lb-find closed lt-find txt) + (define-values (x0 y0) (lb-find nx locked)) + (define-values (x1 y1) (lt-find nx closed)) + (define lbl (text txt '() (- FT 2))) + (define wlbl (pict-width lbl)) + (define hlbl (pict-height lbl)) + (define x (- x0 (/ wlbl 2))) + (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) + (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) + +(define (h-labeled-arrow t) + (define tock (text t '() (- FT 2))) + (define blk (blank (+ DELTA 4) 2)) + (vc-append tock (pin-arrow-line 4.0 blk blk lc-find blk rc-find))) + +(define arrows + (vc-append (h-labeled-arrow "tock") + (h-labeled-arrow "click") + (h-labeled-arrow "react"))) + +(define state0 (make-state0 "World_0" #f)) +(define state1 (make-state0 "World_1" #f)) +(define dots (cc-superimpose (blank (pict-width state1) (pict-height state1)) (text "..." '() FT))) +(define state2 (make-state0 "World_N-1" #f)) +(define stateN (make-state0 "World_N" #t)) +(define states (list state0 arrows state1 arrows dots arrows state2 arrows stateN)) + +(define bg (blank (+ (apply + (map pict-width states)) + DELTA #;(* (length states) DELTA)) + (+ (pict-height state0) DELTA))) + +(define (center base state x) + (define w (pict-height state)) + (define d (quotient (- width w) 2)) + (pin-over base x d state)) + +(define width (pict-height bg)) + +(define x (* 1/2 DELTA)) +(define xx + (foldl (lambda (f ls s) + (define y (center s f x)) + (set! x (+ x ls)) + y) + bg + states + (map (lambda (x) (+ (pict-width x) #;(* 1/1 DELTA))) states))) + +(define the-image (ct-superimpose xx Program)) + +(define image-bm + (make-object bitmap% + (inexact->exact (round (pict-width the-image))) + (inexact->exact (round (pict-height the-image))))) + +(send image-bm ok?) + +(define image-dc + (new bitmap-dc% [bitmap image-bm])) +(send image-dc clear) + +(draw-pict the-image image-dc 0.0 0.0) + +(send image-bm save-file "world.png" 'png) + +the-image diff --git a/collects/teachpack/server.ss b/collects/teachpack/server.ss new file mode 100644 index 0000000000..b8d3d790e4 --- /dev/null +++ b/collects/teachpack/server.ss @@ -0,0 +1,228 @@ +#lang slideshow + +(require slideshow/pict) + +(define DELTA 80) +(define FT 12) + +(define prgm + '("(universe UniState_0" + " (on-new register)" + " (on-msg process)" + " (on-dis disconnect)" + " (on-tick tock)" + " (to-string render))")) + +(define program + (apply vl-append (map (lambda (t) (text t '() (- FT 2))) prgm))) + +(define Program + (cc-superimpose + (rectangle (+ 5 (pict-width program)) (+ 5 (pict-height program))) + program)) + +(define (make-state txt) + (define t (text txt '() FT)) + (define e (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t)))) + (cc-superimpose t e)) + +(define False (text "FALSE" '() FT)) +(define True (text "TRUE" '() FT)) +(define BOOL (rectangle (+ 5 (pict-width False)) (+ 5 (pict-height False)))) + +;; String Boolean -> Pict +(define (make-state0 txt b) + ;; create the basic state + (define t (text txt '() FT)) + (define s (if b + (cc-superimpose + (rounded-rectangle (+ 5 (pict-width t)) (+ (- DELTA 5) (pict-height t))) + t) + t)) + (define w + (cc-superimpose + s + (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t))))) + ;; add the boolean + (define bb (cc-superimpose (if b True False) BOOL)) + (define ar0 (add-labeled-arrow (vc-append DELTA bb w) w ct-find bb cb-find "done")) + ;; HIDE the arrow and done + (define ar (cb-superimpose w (blank (pict-width ar0) (pict-height ar0)))) + (define scene (text "string" '() FT)) + (define sc (cc-superimpose scene (rectangle (+ 20 (pict-width scene)) (+ 30 (pict-height scene))))) + (define br (add-labeled-arrow (vc-append DELTA ar sc) ar cb-find sc ct-find "render")) + br) + +(define (add-labeled-arrow nx locked lb-find closed lt-find txt) + (define-values (x0 y0) (lb-find nx locked)) + (define-values (x1 y1) (lt-find nx closed)) + (define lbl (text txt '() (- FT 2))) + (define wlbl (pict-width lbl)) + (define hlbl (pict-height lbl)) + (define x (- x0 (/ wlbl 2))) + (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) + (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) + +(define (h-labeled-arrow t) + (define tock (text t '() (- FT 2))) + (define blk (blank (+ DELTA 4) 2)) + (vc-append tock (pin-arrow-line 4.0 blk blk lc-find blk rc-find))) + +(define message (text "Message" '() FT)) +(define (make-Message) + (cc-superimpose message (rectangle (+ 20 (pict-width message)) (+ 30 (pict-height message))))) + +(define Message (vc-append (make-Message) (arrowhead 4 (* 1/2 pi)))) +(define MessageK (vc-append (arrowhead 4 (* 3/2 pi)) (make-Message))) + +(define M (rb-superimpose Message (blank DELTA DELTA))) +(define K (rb-superimpose MessageK (blank DELTA DELTA))) + +(define (make-arrows M) + (define Tock (h-labeled-arrow "register")) + (define Click (h-labeled-arrow "tock")) + (define Clack (h-labeled-arrow "disconnect")) + (define Receive (h-labeled-arrow "process")) + (values Tock Click Clack Receive (vc-append (blank DELTA (/ DELTA 2)) Tock Click Clack Receive M))) + +(define-values (TockM ClickM ClackM ReceiveM arrowsR) (make-arrows M)) +(define-values (TockK ClickK ClackK ReceiveK arrowsL) (make-arrows K)) + +(define state0 (make-state0 "UniState_0" #f)) +(define state1 (make-state0 "UniState_1" #f)) +(define Server (hc-append (arrowhead 4 0) (cc-superimpose (cloud 160 80) (text "UNIVERSE" '() FT )))) +(define world (cc-superimpose (cloud 80 40) (text "world" '() FT ))) +(define dots (vc-append + (cc-superimpose (blank (pict-width state1) (pict-height state1)) (text "..." '() FT)) + world + Server)) +(define state2 (make-state0 "UniState_N-1" #f)) +(define stateN (make-state0 "UniState_N" #t)) +(define states (list state1 arrowsL dots arrowsR state2)) + +(define bg (blank (+ (apply + (map pict-width states)) DELTA) + (+ (pict-height state0) DELTA))) + +(define (center base state x) + (define w (pict-height state)) + (define d (quotient (- width w) 2)) + (pin-over base x d state)) + +(define width (pict-height bg)) + +(define x (* 1/2 DELTA)) +(define xx + (foldl (lambda (f ls s) + (define y (center s f x)) + (set! x (+ x ls)) + y) + bg + states + (map (lambda (x) (+ (pict-width x) #;(* 1/1 DELTA))) states))) + +(define zz xx) + +(require mred/mred) + +(define the-image + (ct-superimpose Program + (lt-superimpose + (dc (lambda (dc x y) + (define-values (mx my) (cb-find zz MessageK)) + (define-values (tx ty) (ct-find zz MessageK)) + (define-values (sx sy) (lc-find zz Server)) + (define-values (tockx tocky) (lb-find zz TockK)) + (define-values (clickx clicky) (lb-find zz ClickK)) + (define-values (clackx clacky) (lb-find zz ClackK)) + (define-values (rx ry) (lb-find zz ReceiveK)) + (define (add-curve rx ry) + (set! dcp (make-object dc-path%)) + (set! cx (max rx tx)) + (set! cy (min ry ty)) + (send dcp move-to tx ty) + (send dcp curve-to tx ty cx cy rx ry) + (send dc draw-path dcp)) + (define dcp (make-object dc-path%)) + ;; --- draw arc from Message to Server + (define cx (min sx mx)) + (define cy (max sy my)) + (send dc set-smoothing 'aligned) + (send dcp move-to mx my) + (send dcp curve-to mx my cx cy sx sy) + (send dc draw-path dcp) + ;; --- draw arc from Message to Receiver + (add-curve tockx tocky) + (add-curve clickx clicky) + (add-curve clackx clacky) + (add-curve rx ry) + ;; --- + dc) + (pict-width zz) (pict-height zz)) + (lt-superimpose + (lt-superimpose + zz + (dc (lambda (dc x y) + (define-values (mx my) (cb-find zz world)) + (define-values (tx ty) (ct-find zz world)) + (define-values (sx sy) (rc-find zz Server)) + (define-values (rx ry) (rb-find zz ReceiveM)) + (define dcp (make-object dc-path%)) + ;; --- draw arc from Message to Server + (define cx (max sx mx)) + (define cy (max sy my)) +#| + (send dc set-smoothing 'aligned) + (send dcp move-to mx my) + (send dcp curve-to mx my cx cy sx sy) + (send dc draw-path dcp) +|# + ;; --- draw arc from Message to Receiver + (set! dcp (make-object dc-path%)) + (set! cx (min rx tx)) + (set! cy (min ry ty)) + (send dcp move-to tx ty) + (send dcp curve-to tx ty cx cy rx ry) + (send dc draw-path dcp) + ;; --- + dc) + (pict-width zz) (pict-height zz))) + (dc (lambda (dc x y) + (define-values (mx my) (cb-find zz Message)) + (define-values (tx ty) (ct-find zz Message)) + (define-values (sx sy) (rc-find zz Server)) + (define-values (rx ry) (rb-find zz ReceiveM)) + (define dcp (make-object dc-path%)) + ;; --- draw arc from Message to Server + (define cx (max sx mx)) + (define cy (max sy my)) + (send dc set-smoothing 'aligned) + (send dcp move-to mx my) + (send dcp curve-to mx my cx cy sx sy) + (send dc draw-path dcp) + ;; --- draw arc from Message to Receiver + (set! dcp (make-object dc-path%)) + (set! cx (min rx tx)) + (set! cy (min ry ty)) + (send dcp move-to tx ty) + (send dcp curve-to tx ty cx cy rx ry) + (send dc draw-path dcp) + ;; --- + dc) + (pict-width zz) (pict-height zz)))))) + +(define image-bm + (make-object bitmap% + (inexact->exact (round (pict-width the-image))) + (inexact->exact (round (pict-height the-image))))) + +(send image-bm ok?) + +(define image-dc + (new bitmap-dc% [bitmap image-bm])) +(send image-dc clear) + +(draw-pict the-image image-dc 0.0 0.0) + +(send image-bm save-file "server.png" 'png) + +the-image diff --git a/collects/teachpack/server2.png b/collects/teachpack/server2.png deleted file mode 100644 index 99f02cea21628645569df1d6db48de7ce89b3774..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17544 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 KY?{pV`~L&xx4gap diff --git a/collects/teachpack/universe2.png b/collects/teachpack/universe2.png deleted file mode 100644 index 875756366493ec9ed26d02d3c36bae1d5742bbff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19411 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 diff --git a/collects/teachpack/world.png b/collects/teachpack/world.png index 81cb2ef2dbcd442e4f7a3ad083fdc2f934622372..2b215663af7eec24a24618fc866879ec02c4e92b 100644 GIT binary patch literal 15606 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 diff --git a/collects/teachpack/world.ss b/collects/teachpack/world.ss new file mode 100644 index 0000000000..f9c397e534 --- /dev/null +++ b/collects/teachpack/world.ss @@ -0,0 +1,200 @@ +#lang slideshow + +(require slideshow/pict) + +(define DELTA 80) +(define FT 12) + +(define prgm + '("(big-bang World_0" + " (on-draw render WIDTH HEIGHT)" + " (on-tick tock RATE)" + " (on-mouse click)" + " (on-key react)" + " (on-receive receive)" + " (register LOCALHOST 'jimbob))")) + + +(define program + (apply vl-append (map (lambda (t) (text t '() (- FT 2))) prgm))) + +(define Program + (cc-superimpose + (rectangle (+ 5 (pict-width program)) (+ 5 (pict-height program))) + program)) + +(define (make-state txt) + (define t (text txt '() FT)) + (define e (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t)))) + (cc-superimpose t e)) + +(define False (text "FALSE" '() FT)) +(define True (text "TRUE" '() FT)) +(define BOOL (rectangle (+ 5 (pict-width False)) (+ 5 (pict-height False)))) + +;; String Boolean -> Pict +(define (make-state0 txt b) + ;; create the basic state + (define t (text txt '() FT)) + (define s (if b + (cc-superimpose + (rounded-rectangle (+ 5 (pict-width t)) (+ (- DELTA 5) (pict-height t))) + t) + t)) + (define w + (cc-superimpose + s + (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t))))) + ;; add the boolean + (define bb (cc-superimpose (if b True False) BOOL)) + (define ar (add-labeled-arrow (vc-append DELTA bb w) w ct-find bb cb-find "done")) + (define scene (text "Scene" '() FT)) + (define sc (cc-superimpose scene (rectangle (+ 20 (pict-width scene)) (+ 30 (pict-height scene))))) + (define br (add-labeled-arrow (vc-append DELTA ar sc) ar cb-find sc ct-find "render")) + br) + +(define (add-labeled-arrow nx locked lb-find closed lt-find txt) + (define-values (x0 y0) (lb-find nx locked)) + (define-values (x1 y1) (lt-find nx closed)) + (define lbl (text txt '() (- FT 2))) + (define wlbl (pict-width lbl)) + (define hlbl (pict-height lbl)) + (define x (- x0 (/ wlbl 2))) + (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) + (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) + +(define (h-labeled-arrow t) + (define tock (text t '() (- FT 2))) + (define blk (blank (+ DELTA 4) 2)) + (vc-append tock (pin-arrow-line 4.0 blk blk lc-find blk rc-find))) + +(define message (text "Message" '() FT)) +(define (make-Message) + (cc-superimpose message (rectangle (+ 20 (pict-width message)) (+ 30 (pict-height message))))) + +(define Message (vc-append (make-Message) (arrowhead 4 (* 1/2 pi)))) +(define MessageK (vc-append (arrowhead 4 (* 3/2 pi)) (make-Message))) + +(define M (rb-superimpose Message (blank DELTA DELTA))) +(define K (rb-superimpose MessageK (blank DELTA DELTA))) + +(define (make-arrows M) + (define Tock (h-labeled-arrow "tock")) + (define Click (h-labeled-arrow "click")) + (define Clack (h-labeled-arrow "react")) + (define Receive (h-labeled-arrow "receive")) + (values Tock Click Clack Receive (vc-append (blank DELTA (/ DELTA 2)) Tock Click Clack Receive M))) + +(define-values (TockM ClickM ClackM ReceiveM arrowsR) (make-arrows M)) +(define-values (TockK ClickK ClackK ReceiveK arrowsL) (make-arrows K)) + +(define state0 (make-state0 "World_0" #f)) +(define state1 (make-state0 "World_1" #f)) +(define Server (hc-append (arrowhead 4 0) (cc-superimpose (cloud 160 80) (text "SERVER" '() FT )))) +(define dots (vc-append + (cc-superimpose (blank (pict-width state1) (pict-height state1)) (text "..." '() FT)) + Server)) +(define state2 (make-state0 "World_N-1" #f)) +(define stateN (make-state0 "World_N" #t)) +(define states (list state1 arrowsL dots arrowsR state2)) + +(define bg (blank (+ (apply + (map pict-width states)) DELTA) + (+ (pict-height state0) DELTA))) + +(define (center base state x) + (define w (pict-height state)) + (define d (quotient (- width w) 2)) + (pin-over base x d state)) + +(define width (pict-height bg)) + +(define x (* 1/2 DELTA)) +(define xx + (foldl (lambda (f ls s) + (define y (center s f x)) + (set! x (+ x ls)) + y) + bg + states + (map (lambda (x) (+ (pict-width x) #;(* 1/1 DELTA))) states))) + +(define zz xx) + +(require mred/mred) + +(define the-image + (ct-superimpose Program + (lt-superimpose + (dc (lambda (dc x y) + (define-values (mx my) (cb-find zz MessageK)) + (define-values (tx ty) (ct-find zz MessageK)) + (define-values (sx sy) (lc-find zz Server)) + (define-values (tockx tocky) (lb-find zz TockK)) + (define-values (clickx clicky) (lb-find zz ClickK)) + (define-values (clackx clacky) (lb-find zz ClackK)) + (define-values (rx ry) (lb-find zz ReceiveK)) + (define (add-curve rx ry) + (set! dcp (make-object dc-path%)) + (set! cx (max rx tx)) + (set! cy (min ry ty)) + (send dcp move-to tx ty) + (send dcp curve-to tx ty cx cy rx ry) + (send dc draw-path dcp)) + (define dcp (make-object dc-path%)) + ;; --- draw arc from Message to Server + (define cx (min sx mx)) + (define cy (max sy my)) + (send dc set-smoothing 'aligned) + (send dcp move-to mx my) + (send dcp curve-to mx my cx cy sx sy) + (send dc draw-path dcp) + ;; --- draw arc from Message to Receiver + (add-curve tockx tocky) + (add-curve clickx clicky) + (add-curve clackx clacky) + (add-curve rx ry) + ;; --- + dc) + (pict-width zz) (pict-height zz)) + (lt-superimpose + zz + (dc (lambda (dc x y) + (define-values (mx my) (cb-find zz Message)) + (define-values (tx ty) (ct-find zz Message)) + (define-values (sx sy) (rc-find zz Server)) + (define-values (rx ry) (rb-find zz ReceiveM)) + (define dcp (make-object dc-path%)) + ;; --- draw arc from Message to Server + (define cx (max sx mx)) + (define cy (max sy my)) + (send dc set-smoothing 'aligned) + (send dcp move-to mx my) + (send dcp curve-to mx my cx cy sx sy) + (send dc draw-path dcp) + ;; --- draw arc from Message to Receiver + (set! dcp (make-object dc-path%)) + (set! cx (min rx tx)) + (set! cy (min ry ty)) + (send dcp move-to tx ty) + (send dcp curve-to tx ty cx cy rx ry) + (send dc draw-path dcp) + ;; --- + dc) + (pict-width zz) (pict-height zz)))))) + +(define image-bm + (make-object bitmap% + (inexact->exact (round (pict-width the-image))) + (inexact->exact (round (pict-height the-image))))) + +(send image-bm ok?) + +(define image-dc + (new bitmap-dc% [bitmap image-bm])) +(send image-dc clear) + +(draw-pict the-image image-dc 0.0 0.0) + +(send image-bm save-file "universe.png" 'png) + +the-image From d871eeb91dd5c26d8d80a5deb4127eae81824f41 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 22:13:58 +0000 Subject: [PATCH 33/38] svn: r13077 --- collects/teachpack/2htdp/scribblings/balls.ss | 59 ------ collects/teachpack/2htdp/scribblings/fsa.ss | 59 ------ .../teachpack/2htdp/scribblings/server2.ss | 181 ---------------- .../teachpack/2htdp/scribblings/universe.ss | 200 ------------------ 4 files changed, 499 deletions(-) delete mode 100644 collects/teachpack/2htdp/scribblings/balls.ss delete mode 100644 collects/teachpack/2htdp/scribblings/fsa.ss delete mode 100644 collects/teachpack/2htdp/scribblings/server2.ss delete mode 100644 collects/teachpack/2htdp/scribblings/universe.ss diff --git a/collects/teachpack/2htdp/scribblings/balls.ss b/collects/teachpack/2htdp/scribblings/balls.ss deleted file mode 100644 index a0e3bda180..0000000000 --- a/collects/teachpack/2htdp/scribblings/balls.ss +++ /dev/null @@ -1,59 +0,0 @@ -;; The first three lines of this file were inserted by DrScheme. They record metadata -;; about the language level of this file in a form that our tools can easily process. -#reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname balls) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ()))) -(require (lib "world.ss" "htdp")) - -;; constants -(define height 50) -(define delta 80) -(define width (+ delta (* 2 height))) - -(define left (quotient height 2)) -(define right (+ height delta left)) - -;; World = (make-posn left Number) | (make-posn right Number) - -(define server (text "server" 11 'black)) -(define server* (overlay server (nw:rectangle (image-width server) (image-height server) 'outline 'black))) - -;; visual constants -(define bg - (place-image - (text "universe" 11 'green) - 60 0 - (place-image - server* - (+ height 15) 20 - (place-image - (text "left" 11 'blue) - 10 10 - (place-image - (text "right" 11 'red) - (+ height delta 10) 10 - (place-image - (nw:rectangle delta height 'solid 'white) - height 0 - (place-image - (nw:rectangle width height 'solid 'gray) - 0 0 - (empty-scene width height)))))))) - -(define ball (circle 3 'solid 'red)) - -;; World -> Scene -(define (draw w) - (place-image ball (posn-x w) (posn-y w) bg)) - - -;; World -> World -(define (tick w) - (local ((define y (posn-y w)) - (define x (posn-x w))) - (cond - [(> y 0) (make-posn x (- y 1))] - [(= x left) (make-posn right height)] - [(= x right) (make-posn left height)]))) - -(big-bang width height 1/66 (make-posn left height) true) -(on-redraw draw) -(on-tick-event tick) diff --git a/collects/teachpack/2htdp/scribblings/fsa.ss b/collects/teachpack/2htdp/scribblings/fsa.ss deleted file mode 100644 index 6fd029e6a5..0000000000 --- a/collects/teachpack/2htdp/scribblings/fsa.ss +++ /dev/null @@ -1,59 +0,0 @@ -#lang slideshow - -(require slideshow/pict) - -(define DELTA 40) -(define FT 12) - -; (fsa "unlock" "lock" "push" "tick") -(define (fsa L C O unlock lock push tick) - (define (make-state txt) - (define t (text txt '() FT)) - (define e (rounded-rectangle (+ 10 (pict-width t)) (+ 10 (pict-height t)))) - (cc-superimpose t e)) - - (define locked (make-state L)) - (define closed (make-state C)) - (define open (make-state O)) - - (define bg (rectangle (+ (pict-width locked) (* 2 DELTA)) - (+ (pict-height locked) - (pict-height closed) - (pict-height open) - (* 3 DELTA)))) - - (define width (pict-width bg)) - - (define (center base state y) - (define w (pict-width state)) - (define d (quotient (- width w) 2)) - (pin-over base d y state)) - - (define nx - (center - (center - (center - bg locked (/ DELTA 2)) - closed - (+ (/ DELTA 2) (pict-height locked) DELTA)) - open - (+ (/ DELTA 2) DELTA (pict-height locked) DELTA (pict-height closed)))) - - (define (add-labeled-arrow nx locked lb-find closed lt-find txt) - (define-values (x0 y0) (lb-find nx locked)) - (define-values (x1 y1) (lt-find nx closed)) - (define lbl (text txt '() (- FT 2))) - (define wlbl (pict-width lbl)) - (define hlbl (pict-height lbl)) - (define x (- x0 (/ wlbl 2))) - (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) - (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) - - (define l1 (add-labeled-arrow nx locked lb-find closed lt-find unlock)) - (define l2 (add-labeled-arrow l1 closed lb-find open lt-find push)) - (define l3 (add-labeled-arrow l2 open rt-find closed rb-find tick)) - (define l4 (add-labeled-arrow l3 closed rt-find locked rb-find lock)) - l4) - -(fsa "locked" "closed" "open" "unlock" "lock" "push" "time") -(fsa "'locked" "'closed" "'open" "#\\u" "#\\l" "#\\space" "tick") \ No newline at end of file diff --git a/collects/teachpack/2htdp/scribblings/server2.ss b/collects/teachpack/2htdp/scribblings/server2.ss deleted file mode 100644 index 2bf45e143c..0000000000 --- a/collects/teachpack/2htdp/scribblings/server2.ss +++ /dev/null @@ -1,181 +0,0 @@ -#lang slideshow - -(require slideshow/pict) - -(define DELTA 80) -(define FT 12) - -(define initialize "register") -(define proc-msg "process") - -(define program - (apply vl-append (map (lambda (t) (text t '() (- FT 2))) - (list (format "(universe [on-new ~a] [on-msg ~a])" initialize proc-msg))))) - -(define Program - (cc-superimpose - (rectangle (+ 5 (pict-width program)) (+ 5 (pict-height program))) - program)) - -;; String Boolean -> Pict -(define (make-state0 txt b) - ;; create the basic state - (define t (text txt '() FT)) - (cc-superimpose t (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t))))) - -(define (add-labeled-arrow nx locked lb-find closed lt-find txt) - (define-values (x0 y0) (lb-find nx locked)) - (define-values (x1 y1) (lt-find nx closed)) - (define lbl (text txt '() (- FT 2))) - (define wlbl (pict-width lbl)) - (define hlbl (pict-height lbl)) - (define x (- x0 (/ wlbl 2))) - (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) - (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) - -(define (h-labeled-arrow t) - (define tock (text t '() (- FT 2))) - (define blk (blank (+ DELTA 4) 2)) - (vc-append tock (pin-arrow-line 4.0 blk blk lc-find blk rc-find))) - -(define message (text "Message" '() FT)) -(define (make-Message) - (cc-superimpose message (rectangle (+ 20 (pict-width message)) (+ 30 (pict-height message))))) - -(define Message (vc-append (make-Message) (arrowhead 4 (* 1/2 pi)))) -(define MessageK (vc-append (arrowhead 4 (* 3/2 pi)) (make-Message))) -(define MessageI (vc-append (arrowhead 4 (* 3/2 pi)) (make-Message))) - -(define M (rb-superimpose Message (blank DELTA DELTA))) -(define K (rb-superimpose MessageK (blank DELTA DELTA))) -(define I (rb-superimpose MessageI (blank DELTA DELTA))) - -(define (make-arrows M lbl) - (define Tock (h-labeled-arrow lbl)) - (values Tock (vc-append (blank DELTA (/ DELTA 2)) Tock M))) - -(define-values (TockM arrowsR) (make-arrows M proc-msg)) -(define-values (TockK arrowsL) (make-arrows K proc-msg)) -(define-values (init arrows) (make-arrows I initialize)) - -(define state0 (make-state0 "Server_0" #f)) -(define state2 (make-state0 "Server_N-1" #f)) -(define Univrs (hc-append (arrowhead 4 0) (cc-superimpose (cloud 160 80) (text "Universe" '() FT )))) -(define dots (vc-append - (blank (pict-width state2) (quotient (pict-height state2) 1)) - (text "..." '() FT) - (blank (pict-width state2) (* (pict-height state2))) - Univrs)) - -(define states (list arrows - state0 - arrowsL - dots - arrowsR - state2 - (h-labeled-arrow proc-msg))) - -(define bg (blank (+ (apply + (map pict-width states)) DELTA) (pict-height dots))) - -(define (center base state x) - (define w (pict-height state)) - (define d (quotient (- (pict-height bg) w) 2)) - (pin-over base x d state)) - -(define x (* 1/2 DELTA)) -(define xx - (foldl (lambda (f ls s) - (define y (center s f x)) - (set! x (+ x ls)) - y) - bg - states - (map pict-width states))) - -(define zz (ct-superimpose xx Program)) - -(require mred/mred) - -(define the-image - (lt-superimpose - (dc (lambda (dc x y) - (define-values (mx my) (cb-find zz MessageK)) - (define-values (tx ty) (ct-find zz MessageK)) - (define-values (ix iy) (ct-find zz MessageI)) - (define-values (jx jy) (cb-find zz MessageI)) - (define-values (sx sy) (lc-find zz Univrs)) - (define-values (tockx tocky) (lb-find zz TockK)) - (define-values (initx inity) (lb-find zz init)) - (define (add-curve rx ry) - (set! dcp (make-object dc-path%)) - (set! cx (max rx tx)) - (set! cy (min ry ty)) - (send dcp move-to tx ty) - (send dcp curve-to tx ty cx cy rx ry) - (send dc draw-path dcp)) - (define dcp (make-object dc-path%)) - ;; --- draw arc from Message to Server - (define cx (min sx mx)) - (define cy (max sy my)) - (send dc set-smoothing 'aligned) - (send dcp move-to mx my) - (send dcp curve-to mx my cx cy sx sy) - (send dc draw-path dcp) - (set! dcp (make-object dc-path%)) - (set! cx (min sx jx)) - (set! cy (max sy jy)) - (send dc set-smoothing 'aligned) - (send dcp move-to jx jy) - (send dcp curve-to jx jy cx cy sx sy) - (send dc draw-path dcp) -;; --- draw arc from Message to Receiver - (add-curve tockx tocky) - (set! tx ix) (set! ty iy) - (add-curve initx inity) - ;; --- - dc) - (pict-width zz) (pict-height zz)) - (lt-superimpose - zz - (dc (lambda (dc x y) - (define-values (mx my) (cb-find zz Message)) - (define-values (tx ty) (ct-find zz Message)) - (define-values (sx sy) (rc-find zz Univrs)) - (define-values (tockx tocky) (rb-find zz TockM)) - (define (add-curve rx ry) - (set! dcp (make-object dc-path%)) - (set! cx (min rx tx)) - (set! cy (min ry ty)) - (send dcp move-to tx ty) - (send dcp curve-to tx ty cx cy rx ry) - (send dc draw-path dcp)) - (define dcp (make-object dc-path%)) - ;; --- draw arc from Message to Server - (define cx (max sx mx)) - (define cy (max sy my)) - (send dc set-smoothing 'aligned) - (send dcp move-to mx my) - (send dcp curve-to mx my cx cy sx sy) - (send dc draw-path dcp) - ;; --- draw arc from Message to Receiver - (add-curve tockx tocky) - ;; --- - dc) - (pict-width zz) (pict-height zz))))) - -(define image-bm - (make-object bitmap% - (inexact->exact (round (pict-width the-image))) - (inexact->exact (round (pict-height the-image))))) - -(send image-bm ok?) - -(define image-dc - (new bitmap-dc% [bitmap image-bm])) -(send image-dc clear) - -(draw-pict the-image image-dc 0.0 0.0) - -(send image-bm save-file "server2.png" 'png) - -the-image \ No newline at end of file diff --git a/collects/teachpack/2htdp/scribblings/universe.ss b/collects/teachpack/2htdp/scribblings/universe.ss deleted file mode 100644 index f9c397e534..0000000000 --- a/collects/teachpack/2htdp/scribblings/universe.ss +++ /dev/null @@ -1,200 +0,0 @@ -#lang slideshow - -(require slideshow/pict) - -(define DELTA 80) -(define FT 12) - -(define prgm - '("(big-bang World_0" - " (on-draw render WIDTH HEIGHT)" - " (on-tick tock RATE)" - " (on-mouse click)" - " (on-key react)" - " (on-receive receive)" - " (register LOCALHOST 'jimbob))")) - - -(define program - (apply vl-append (map (lambda (t) (text t '() (- FT 2))) prgm))) - -(define Program - (cc-superimpose - (rectangle (+ 5 (pict-width program)) (+ 5 (pict-height program))) - program)) - -(define (make-state txt) - (define t (text txt '() FT)) - (define e (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t)))) - (cc-superimpose t e)) - -(define False (text "FALSE" '() FT)) -(define True (text "TRUE" '() FT)) -(define BOOL (rectangle (+ 5 (pict-width False)) (+ 5 (pict-height False)))) - -;; String Boolean -> Pict -(define (make-state0 txt b) - ;; create the basic state - (define t (text txt '() FT)) - (define s (if b - (cc-superimpose - (rounded-rectangle (+ 5 (pict-width t)) (+ (- DELTA 5) (pict-height t))) - t) - t)) - (define w - (cc-superimpose - s - (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t))))) - ;; add the boolean - (define bb (cc-superimpose (if b True False) BOOL)) - (define ar (add-labeled-arrow (vc-append DELTA bb w) w ct-find bb cb-find "done")) - (define scene (text "Scene" '() FT)) - (define sc (cc-superimpose scene (rectangle (+ 20 (pict-width scene)) (+ 30 (pict-height scene))))) - (define br (add-labeled-arrow (vc-append DELTA ar sc) ar cb-find sc ct-find "render")) - br) - -(define (add-labeled-arrow nx locked lb-find closed lt-find txt) - (define-values (x0 y0) (lb-find nx locked)) - (define-values (x1 y1) (lt-find nx closed)) - (define lbl (text txt '() (- FT 2))) - (define wlbl (pict-width lbl)) - (define hlbl (pict-height lbl)) - (define x (- x0 (/ wlbl 2))) - (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) - (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) - -(define (h-labeled-arrow t) - (define tock (text t '() (- FT 2))) - (define blk (blank (+ DELTA 4) 2)) - (vc-append tock (pin-arrow-line 4.0 blk blk lc-find blk rc-find))) - -(define message (text "Message" '() FT)) -(define (make-Message) - (cc-superimpose message (rectangle (+ 20 (pict-width message)) (+ 30 (pict-height message))))) - -(define Message (vc-append (make-Message) (arrowhead 4 (* 1/2 pi)))) -(define MessageK (vc-append (arrowhead 4 (* 3/2 pi)) (make-Message))) - -(define M (rb-superimpose Message (blank DELTA DELTA))) -(define K (rb-superimpose MessageK (blank DELTA DELTA))) - -(define (make-arrows M) - (define Tock (h-labeled-arrow "tock")) - (define Click (h-labeled-arrow "click")) - (define Clack (h-labeled-arrow "react")) - (define Receive (h-labeled-arrow "receive")) - (values Tock Click Clack Receive (vc-append (blank DELTA (/ DELTA 2)) Tock Click Clack Receive M))) - -(define-values (TockM ClickM ClackM ReceiveM arrowsR) (make-arrows M)) -(define-values (TockK ClickK ClackK ReceiveK arrowsL) (make-arrows K)) - -(define state0 (make-state0 "World_0" #f)) -(define state1 (make-state0 "World_1" #f)) -(define Server (hc-append (arrowhead 4 0) (cc-superimpose (cloud 160 80) (text "SERVER" '() FT )))) -(define dots (vc-append - (cc-superimpose (blank (pict-width state1) (pict-height state1)) (text "..." '() FT)) - Server)) -(define state2 (make-state0 "World_N-1" #f)) -(define stateN (make-state0 "World_N" #t)) -(define states (list state1 arrowsL dots arrowsR state2)) - -(define bg (blank (+ (apply + (map pict-width states)) DELTA) - (+ (pict-height state0) DELTA))) - -(define (center base state x) - (define w (pict-height state)) - (define d (quotient (- width w) 2)) - (pin-over base x d state)) - -(define width (pict-height bg)) - -(define x (* 1/2 DELTA)) -(define xx - (foldl (lambda (f ls s) - (define y (center s f x)) - (set! x (+ x ls)) - y) - bg - states - (map (lambda (x) (+ (pict-width x) #;(* 1/1 DELTA))) states))) - -(define zz xx) - -(require mred/mred) - -(define the-image - (ct-superimpose Program - (lt-superimpose - (dc (lambda (dc x y) - (define-values (mx my) (cb-find zz MessageK)) - (define-values (tx ty) (ct-find zz MessageK)) - (define-values (sx sy) (lc-find zz Server)) - (define-values (tockx tocky) (lb-find zz TockK)) - (define-values (clickx clicky) (lb-find zz ClickK)) - (define-values (clackx clacky) (lb-find zz ClackK)) - (define-values (rx ry) (lb-find zz ReceiveK)) - (define (add-curve rx ry) - (set! dcp (make-object dc-path%)) - (set! cx (max rx tx)) - (set! cy (min ry ty)) - (send dcp move-to tx ty) - (send dcp curve-to tx ty cx cy rx ry) - (send dc draw-path dcp)) - (define dcp (make-object dc-path%)) - ;; --- draw arc from Message to Server - (define cx (min sx mx)) - (define cy (max sy my)) - (send dc set-smoothing 'aligned) - (send dcp move-to mx my) - (send dcp curve-to mx my cx cy sx sy) - (send dc draw-path dcp) - ;; --- draw arc from Message to Receiver - (add-curve tockx tocky) - (add-curve clickx clicky) - (add-curve clackx clacky) - (add-curve rx ry) - ;; --- - dc) - (pict-width zz) (pict-height zz)) - (lt-superimpose - zz - (dc (lambda (dc x y) - (define-values (mx my) (cb-find zz Message)) - (define-values (tx ty) (ct-find zz Message)) - (define-values (sx sy) (rc-find zz Server)) - (define-values (rx ry) (rb-find zz ReceiveM)) - (define dcp (make-object dc-path%)) - ;; --- draw arc from Message to Server - (define cx (max sx mx)) - (define cy (max sy my)) - (send dc set-smoothing 'aligned) - (send dcp move-to mx my) - (send dcp curve-to mx my cx cy sx sy) - (send dc draw-path dcp) - ;; --- draw arc from Message to Receiver - (set! dcp (make-object dc-path%)) - (set! cx (min rx tx)) - (set! cy (min ry ty)) - (send dcp move-to tx ty) - (send dcp curve-to tx ty cx cy rx ry) - (send dc draw-path dcp) - ;; --- - dc) - (pict-width zz) (pict-height zz)))))) - -(define image-bm - (make-object bitmap% - (inexact->exact (round (pict-width the-image))) - (inexact->exact (round (pict-height the-image))))) - -(send image-bm ok?) - -(define image-dc - (new bitmap-dc% [bitmap image-bm])) -(send image-dc clear) - -(draw-pict the-image image-dc 0.0 0.0) - -(send image-bm save-file "universe.png" 'png) - -the-image From bdd29b22cfd8c2097828e912a6354f727a269c78 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 22:14:15 +0000 Subject: [PATCH 34/38] svn: r13078 --- .../teachpack/2htdp/scribblings/nuworld.ss | 119 ------------------ 1 file changed, 119 deletions(-) delete mode 100644 collects/teachpack/2htdp/scribblings/nuworld.ss diff --git a/collects/teachpack/2htdp/scribblings/nuworld.ss b/collects/teachpack/2htdp/scribblings/nuworld.ss deleted file mode 100644 index 56a536a350..0000000000 --- a/collects/teachpack/2htdp/scribblings/nuworld.ss +++ /dev/null @@ -1,119 +0,0 @@ -#lang slideshow - -(require slideshow/pict mred/mred) - -(define DELTA 80) -(define FT 12) - -(define txt - '("(big-bang World_0" - " (on-draw render WIDTH HEIGHT)" - " (on-tick tock RATE)" - " (on-mouse click)" - " (on-key react))" - )) - -(define program - (apply vl-append (map (lambda (t) (text t '() (- FT 2))) txt))) - -(define Program - (cc-superimpose - (rectangle (+ 5 (pict-width program)) (+ 5 (pict-height program))) - program)) - -(define (make-state txt) - (define t (text txt '() FT)) - (define e (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t)))) - (cc-superimpose t e)) - -(define False (text "FALSE" '() FT)) -(define True (text "TRUE" '() FT)) -(define BOOL (rectangle (+ 5 (pict-width False)) (+ 5 (pict-height False)))) - -;; String Boolean -> Pict -(define (make-state0 txt b) - ;; create the basic state - (define t (text txt '() FT)) - (define s (if b - (cc-superimpose - (rounded-rectangle (+ 5 (pict-width t)) (+ (- DELTA 5) (pict-height t))) - t) - t)) - (define w - (cc-superimpose - s - (rounded-rectangle (+ 10 (pict-width t)) (+ DELTA (pict-height t))))) - ;; add the boolean - (define bb (cc-superimpose (if b True False) BOOL)) - (define ar (add-labeled-arrow (vc-append DELTA bb w) w ct-find bb cb-find "done")) - (define scene (text "Scene" '() FT)) - (define sc (cc-superimpose scene (rectangle (+ 20 (pict-width scene)) (+ 30 (pict-height scene))))) - (define br (add-labeled-arrow (vc-append DELTA ar sc) ar cb-find sc ct-find "render")) - br) - -(define (add-labeled-arrow nx locked lb-find closed lt-find txt) - (define-values (x0 y0) (lb-find nx locked)) - (define-values (x1 y1) (lt-find nx closed)) - (define lbl (text txt '() (- FT 2))) - (define wlbl (pict-width lbl)) - (define hlbl (pict-height lbl)) - (define x (- x0 (/ wlbl 2))) - (define y (+ y0 (/ ( - y1 y0 hlbl) 2))) - (pin-over (pin-arrow-line 4.0 nx locked lb-find closed lt-find) x y lbl)) - -(define (h-labeled-arrow t) - (define tock (text t '() (- FT 2))) - (define blk (blank (+ DELTA 4) 2)) - (vc-append tock (pin-arrow-line 4.0 blk blk lc-find blk rc-find))) - -(define arrows - (vc-append (h-labeled-arrow "tock") - (h-labeled-arrow "click") - (h-labeled-arrow "react"))) - -(define state0 (make-state0 "World_0" #f)) -(define state1 (make-state0 "World_1" #f)) -(define dots (cc-superimpose (blank (pict-width state1) (pict-height state1)) (text "..." '() FT))) -(define state2 (make-state0 "World_N-1" #f)) -(define stateN (make-state0 "World_N" #t)) -(define states (list state0 arrows state1 arrows dots arrows state2 arrows stateN)) - -(define bg (blank (+ (apply + (map pict-width states)) - DELTA #;(* (length states) DELTA)) - (+ (pict-height state0) DELTA))) - -(define (center base state x) - (define w (pict-height state)) - (define d (quotient (- width w) 2)) - (pin-over base x d state)) - -(define width (pict-height bg)) - -(define x (* 1/2 DELTA)) -(define xx - (foldl (lambda (f ls s) - (define y (center s f x)) - (set! x (+ x ls)) - y) - bg - states - (map (lambda (x) (+ (pict-width x) #;(* 1/1 DELTA))) states))) - -(define the-image (ct-superimpose xx Program)) - -(define image-bm - (make-object bitmap% - (inexact->exact (round (pict-width the-image))) - (inexact->exact (round (pict-height the-image))))) - -(send image-bm ok?) - -(define image-dc - (new bitmap-dc% [bitmap image-bm])) -(send image-dc clear) - -(draw-pict the-image image-dc 0.0 0.0) - -(send image-bm save-file "nuworld.png" 'png) - -the-image From f07803c3cdb52f084f232c3d2b9c70e36e338c49 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 12 Jan 2009 22:16:08 +0000 Subject: [PATCH 35/38] fix lifting bug introduced in previous commit svn: r13079 --- src/mzscheme/src/eval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mzscheme/src/eval.c b/src/mzscheme/src/eval.c index 2fc414ca14..17d1ae7b7b 100644 --- a/src/mzscheme/src/eval.c +++ b/src/mzscheme/src/eval.c @@ -5039,7 +5039,7 @@ static void *compile_k(void) rl = scheme_frame_get_require_lifts(cenv); if (!SCHEME_NULLP(l) || !SCHEME_NULLP(rl)) { - l = scheme_append(rl, l); + rl = scheme_append(rl, l); rl = icons(scheme_datum_to_syntax(begin_symbol, scheme_false, scheme_sys_wraps(cenv), 0, 0), rl); form = scheme_datum_to_syntax(rl, scheme_false, scheme_false, 0, 0); From 2b0daee31c28168a057140ac4d679cc38a6b9b07 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 22:22:08 +0000 Subject: [PATCH 36/38] svn: r13080 --- collects/2htdp/private/universe.ss | 3 ++- collects/2htdp/private/world.ss | 3 ++- collects/2htdp/test/world0-stops.ss | 5 +++++ collects/2htdp/universe.ss | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 collects/2htdp/test/world0-stops.ss diff --git a/collects/2htdp/private/universe.ss b/collects/2htdp/private/universe.ss index d170551ffa..7fc5426de7 100644 --- a/collects/2htdp/private/universe.ss +++ b/collects/2htdp/private/universe.ss @@ -61,7 +61,7 @@ (define u (bundle-state r)) (set! worlds (bundle-low r)) (set! universe u) - (unless (boolean? to-string) (send gui add (to-string u))) + (unless (boolean? to-string) (send gui add (to-string worlds u))) (broadcast (bundle-mails r)))))) (def/cback private (pmsg world received) on-msg) @@ -219,6 +219,7 @@ (provide world? ;; Any -> Boolean world=? ;; World World -> Boolean + world-name ;; World -> Symbol world1 ;; sample worlds world2 world3) diff --git a/collects/2htdp/private/world.ss b/collects/2htdp/private/world.ss index b45eaa0dd9..6daa9e326f 100644 --- a/collects/2htdp/private/world.ss +++ b/collects/2htdp/private/world.ss @@ -278,7 +278,8 @@ ;; ------------------------------------------------------------------------- ;; initialize the world and run (super-new) - (start!))))) + (start!) + (when (stop-when world) (stop! world)))))) ;; ----------------------------------------------------------------------------- (define-runtime-path break-btn:path '(lib "icons/break.png")) diff --git a/collects/2htdp/test/world0-stops.ss b/collects/2htdp/test/world0-stops.ss new file mode 100644 index 0000000000..a50c191bf2 --- /dev/null +++ b/collects/2htdp/test/world0-stops.ss @@ -0,0 +1,5 @@ +;; The first three lines of this file were inserted by DrScheme. They record metadata +;; about the language level of this file in a form that our tools can easily process. +#reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname world0-stops) (read-case-sensitive #t) (teachpacks ((lib "universe.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "universe.ss" "teachpack" "2htdp"))))) + +(big-bang 0 (stop-when zero?) (on-tick add1)) \ No newline at end of file diff --git a/collects/2htdp/universe.ss b/collects/2htdp/universe.ss index 9d691c54b3..f8182421f8 100644 --- a/collects/2htdp/universe.ss +++ b/collects/2htdp/universe.ss @@ -228,6 +228,7 @@ ;; type World world? ;; Any -> Boolean world=? ;; World World -> Boolean + world-name ;; World -> Symbol world1 ;; sample worlds world2 world3 From d7d93250f3506ade655c2d6f2f2c36f419c39aab Mon Sep 17 00:00:00 2001 From: Casey Klein Date: Mon, 12 Jan 2009 22:50:09 +0000 Subject: [PATCH 37/38] Added examples to `redex-check' documentation. svn: r13081 --- collects/redex/redex.scrbl | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/collects/redex/redex.scrbl b/collects/redex/redex.scrbl index 467a38c27e..34c0415cd6 100644 --- a/collects/redex/redex.scrbl +++ b/collects/redex/redex.scrbl @@ -1011,20 +1011,20 @@ an association list mapping names to application counts.} @examples[ #:eval redex-eval - (define-language addition - (e (+ number ...))) - (define reduce + (define-language empty-lang) + + (define equals (reduction-relation - addition + empty-lang (--> (+) 0 "zero") (--> (+ number) number) (--> (+ number_1 number_2 number ...) (+ ,(+ (term number_1) (term number_2)) number ...) "add"))) - (let ([coverage (make-coverage reduce)]) + (let ([coverage (make-coverage equals)]) (parameterize ([relation-coverage coverage]) - (apply-reduction-relation* reduce (term (+ 1 2 3))) + (apply-reduction-relation* equals (term (+ 1 2 3))) (covered-cases coverage)))] @defform*[[(generate-term language #, @|ttpattern| size-exp) @@ -1056,6 +1056,31 @@ these free @pattech[term]-variables by generating random terms matching @scheme[pattern] and extracting the sub-terms bound by the @pattech[names] and non-terminals in @scheme[pattern]. +@examples[ +#:eval redex-eval + (define-language empty-lang) + + (random-seed 0) + + (redex-check + empty-lang + ((number_1 ...) + (number_2 ...)) + (equal? (reverse (append (term (number_1 ...)) + (term (number_2 ...)))) + (append (reverse (term (number_1 ...))) + (reverse (term (number_2 ...)))))) + + (redex-check + empty-lang + ((number_1 ...) + (number_2 ...)) + (equal? (reverse (append (term (number_1 ...)) + (term (number_2 ...)))) + (append (reverse (term (number_2 ...))) + (reverse (term (number_1 ...))))) + #:attempts 200)] + @scheme[redex-check] generates at most @scheme[attempts-expr] (default @scheme[100]) random terms in its search. The size and complexity of terms it generates gradually increases with each failed attempt. From 3d3bcfe2f742a73eadb60409f3e87d6f863912ee Mon Sep 17 00:00:00 2001 From: Ryan Culpepper Date: Tue, 13 Jan 2009 00:43:47 +0000 Subject: [PATCH 38/38] macro stepper: cleaned up column-width detection/resizing svn: r13082 --- .../macro-debugger/syntax-browser/display.ss | 233 +++++++++--------- .../macro-debugger/syntax-browser/prefs.ss | 3 - .../macro-debugger/syntax-browser/widget.ss | 9 +- collects/macro-debugger/view/frame.ss | 1 - 4 files changed, 119 insertions(+), 127 deletions(-) diff --git a/collects/macro-debugger/syntax-browser/display.ss b/collects/macro-debugger/syntax-browser/display.ss index 79ade18f4d..06e04ff2ed 100644 --- a/collects/macro-debugger/syntax-browser/display.ss +++ b/collects/macro-debugger/syntax-browser/display.ss @@ -9,34 +9,68 @@ (provide print-syntax-to-editor code-style) -;; print-syntax-to-editor : syntax text controller<%> -> display<%> -(define (print-syntax-to-editor stx text controller config) - (new display% (syntax stx) (text text) (controller controller) (config config))) - ;; FIXME: assumes text never moves +;; print-syntax-to-editor : syntax text controller<%> config number number +;; -> display<%> +(define (print-syntax-to-editor stx text controller config columns insertion-point) + (define output-port (open-output-string/count-lines)) + (define range + (pretty-print-syntax stx output-port + (send controller get-primary-partition) + (send config get-colors) + (send config get-suffix-option) + columns)) + (define output-string (get-output-string output-port)) + (define output-length (sub1 (string-length output-string))) ;; skip final newline + (fixup-parentheses output-string range) + (let ([display + (new display% + (text text) + (controller controller) + (config config) + (range range) + (start-position insertion-point) + (end-position (+ insertion-point output-length)))]) + (send text begin-edit-sequence) + (send text insert output-length output-string insertion-point) + (add-clickbacks text range controller insertion-point) + (set-standard-font text config insertion-point (+ insertion-point output-length)) + (send display initialize) + (send text end-edit-sequence) + display)) + +;; add-clickbacks : text% range% controller<%> number -> void +(define (add-clickbacks text range controller insertion-point) + (for ([range (send range all-ranges)]) + (let ([stx (range-obj range)] + [start (range-start range)] + [end (range-end range)]) + (send text set-clickback (+ insertion-point start) (+ insertion-point end) + (lambda (_1 _2 _3) + (send controller set-selected-syntax stx)))))) + +;; set-standard-font : text% config number number -> void +(define (set-standard-font text config start end) + (send text change-style + (code-style text (send config get-syntax-font-size)) + start end)) + ;; display% (define display% (class* object% (display<%>) - (init ((stx syntax))) (init-field text) (init-field controller) (init-field config) + (init-field range) + (init-field start-position) + (init-field end-position) - (define start-anchor (new anchor-snip%)) - (define end-anchor (new anchor-snip%)) - (define range #f) (define extra-styles (make-hasheq)) - ;; render-syntax : syntax -> void - (define/public (render-syntax stx) - (with-unlock text - (send text delete (get-start-position) (get-end-position)) - (set! range - (print-syntax stx text controller config - (lambda () (get-start-position)) - (lambda () (get-end-position)))) - (apply-primary-partition-styles)) + ;; initialize : -> void + (define/public (initialize) + (apply-primary-partition-styles) (refresh)) ;; refresh : -> void @@ -45,7 +79,7 @@ (with-unlock text (send* text (begin-edit-sequence) - (change-style unhighlight-d (get-start-position) (get-end-position))) + (change-style unhighlight-d start-position end-position)) (apply-extra-styles) (let ([selected-syntax (send controller get-selected-syntax)]) (apply-secondary-partition-styles selected-syntax) @@ -53,29 +87,15 @@ (send* text (end-edit-sequence)))) - ;; cached-start-position : number - (define cached-start-position #f) - - ;; get-start-position : -> number - (define/public-final (get-start-position) - (unless cached-start-position - (set! cached-start-position (send text get-snip-position start-anchor))) - cached-start-position) - - ;; get-end-position : -> number - (define/public-final (get-end-position) - (send text get-snip-position end-anchor)) - - ;; relative->text-position : number -> number - ;; FIXME: might be slow to find start every time! - (define/public-final (relative->text-position pos) - (+ pos (get-start-position))) - - ;; Styling - ;; get-range : -> range<%> (define/public (get-range) range) + ;; get-start-position : -> number + (define/public (get-start-position) start-position) + + ;; get-end-position : -> number + (define/public (get-end-position) end-position) + ;; highlight-syntaxes : (list-of syntax) string -> void (define/public (highlight-syntaxes stxs hi-color) (let ([style-delta (highlight-style-delta hi-color #f)]) @@ -89,11 +109,50 @@ (add-extra-styles stx (list underline-style-delta))) (refresh)) + ;; add-extra-styles : syntax (listof style) -> void (define/public (add-extra-styles stx styles) (hash-set! extra-styles stx (append (hash-ref extra-styles stx null) styles))) + ;; Primary styles + ;; (Done once on initialization, never repeated) + + ;; apply-primary-partition-styles : -> void + ;; Changes the foreground color according to the primary partition. + ;; Only called once, when the syntax is first drawn. + (define/private (apply-primary-partition-styles) + (define (color-style color) + (let ([delta (new style-delta%)]) + (send delta set-delta-foreground color) + delta)) + (define color-styles (list->vector (map color-style (send config get-colors)))) + (define overflow-style (color-style "darkgray")) + (define color-partition (send controller get-primary-partition)) + (define offset start-position) + (for-each + (lambda (range) + (let ([stx (range-obj range)] + [start (range-start range)] + [end (range-end range)]) + (send text change-style + (primary-style stx color-partition color-styles overflow-style) + (+ offset start) + (+ offset end)))) + (send range all-ranges))) + + ;; primary-style : syntax partition (vector-of style-delta%) style-delta% + ;; -> style-delta% + (define/private (primary-style stx partition color-vector overflow) + (let ([n (send partition get-partition stx)]) + (cond [(< n (vector-length color-vector)) + (vector-ref color-vector n)] + [else + overflow]))) + + ;; Secondary Styling + ;; May change in response to user actions + ;; apply-extra-styles : -> void ;; Applies externally-added styles (such as highlighting) (define/private (apply-extra-styles) @@ -131,101 +190,35 @@ (relative->text-position (car r)) (relative->text-position (cdr r)))) - ;; Primary styles - - ;; apply-primary-partition-styles : -> void - ;; Changes the foreground color according to the primary partition. - ;; Only called once, when the syntax is first drawn. - (define/private (apply-primary-partition-styles) - (define (color-style color) - (let ([delta (new style-delta%)]) - (send delta set-delta-foreground color) - delta)) - (define color-styles (list->vector (map color-style (send config get-colors)))) - (define overflow-style (color-style "darkgray")) - (define color-partition (send controller get-primary-partition)) - (define offset (get-start-position)) - (for-each - (lambda (range) - (let ([stx (range-obj range)] - [start (range-start range)] - [end (range-end range)]) - (send text change-style - (primary-style stx color-partition color-styles overflow-style) - (+ offset start) - (+ offset end)))) - (send range all-ranges))) - - ;; primary-style : syntax partition (vector-of style-delta%) style-delta% - ;; -> style-delta% - (define/private (primary-style stx partition color-vector overflow) - (let ([n (send partition get-partition stx)]) - (cond [(< n (vector-length color-vector)) - (vector-ref color-vector n)] - [else - overflow]))) + ;; relative->text-position : number -> number + (define/private (relative->text-position pos) + (+ pos start-position)) ;; Initialize (super-new) - (send text insert start-anchor) - (send text insert end-anchor) - (render-syntax stx) (send controller add-syntax-display this))) -;; print-syntax : syntax text% controller config (-> number) (-> number) -;; -> range% -(define (print-syntax stx text controller config - get-start-position get-end-position) - (define primary-partition (send controller get-primary-partition)) - (define real-output-port (make-text-port text get-end-position)) - (define output-port (open-output-string)) - (define colors (send config get-colors)) - (define suffix-option (send config get-suffix-option)) - (define columns (send config get-columns)) - - (port-count-lines! output-port) - (let ([range (pretty-print-syntax stx output-port primary-partition - colors suffix-option columns)]) - (write-string (get-output-string output-port) real-output-port) - (let ([end (get-end-position)]) - ;; Pretty printer always inserts final newline; we remove it here. - (send text delete (sub1 end) end)) - (let ([offset (get-start-position)]) - (fixup-parentheses text range offset) - (for-each - (lambda (range) - (let* ([stx (range-obj range)] - [start (range-start range)] - [end (range-end range)]) - (send text set-clickback (+ offset start) (+ offset end) - (lambda (_1 _2 _3) - (send controller set-selected-syntax stx))))) - (send range all-ranges))) - ;; Set font to standard - (send text change-style - (code-style text (send config get-syntax-font-size)) - (get-start-position) - (get-end-position)) - range)) - -;; fixup-parentheses : text range -> void -(define (fixup-parentheses text range offset) +;; fixup-parentheses : string range -> void +(define (fixup-parentheses string range) (define (fixup r) (let ([stx (range-obj r)] - [start (+ offset (range-start r))] - [end (+ offset (range-end r))]) + [start (range-start r)] + [end (range-end r)]) (when (and (syntax? stx) (pair? (syntax-e stx))) (case (syntax-property stx 'paren-shape) ((#\[) - (replace start #\[) - (replace (sub1 end) #\])) + (string-set! string start #\[) + (string-set! string (sub1 end) #\])) ((#\{) - (replace start #\{) - (replace (sub1 end) #\})))))) - (define (replace pos char) - (send text insert char pos (add1 pos))) + (string-set! string start #\{) + (string-set! string (sub1 end) #\})))))) (for-each fixup (send range all-ranges))) +(define (open-output-string/count-lines) + (let ([os (open-output-string)]) + (port-count-lines! os) + os)) + ;; code-style : text<%> number/#f -> style<%> (define (code-style text font-size) (let* ([style-list (send text get-style-list)] diff --git a/collects/macro-debugger/syntax-browser/prefs.ss b/collects/macro-debugger/syntax-browser/prefs.ss index 2ef4287f9c..fe31a40cc2 100644 --- a/collects/macro-debugger/syntax-browser/prefs.ss +++ b/collects/macro-debugger/syntax-browser/prefs.ss @@ -22,9 +22,6 @@ (define prefs-base% (class object% - ;; columns : number - (field/notify columns (new notify-box% (value 60))) - ;; suffix-option : SuffixOption (field/notify suffix-option (new notify-box% (value 'over-limit))) diff --git a/collects/macro-debugger/syntax-browser/widget.ss b/collects/macro-debugger/syntax-browser/widget.ss index d202d2e6d6..29559e1c89 100644 --- a/collects/macro-debugger/syntax-browser/widget.ss +++ b/collects/macro-debugger/syntax-browser/widget.ss @@ -143,7 +143,7 @@ (for ([binder-r (send range get-ranges binder)]) (for ([id-r (send range get-ranges id)]) (add-binding-arrow start binder-r id-r definite?))))))) - display)) + (void))) (define/private (add-binding-arrow start binder-r id-r definite?) (if definite? @@ -189,14 +189,17 @@ ;; internal-add-syntax : syntax -> display (define/private (internal-add-syntax stx) (with-unlock -text - (let ([display (print-syntax-to-editor stx -text controller config)]) + (let ([display + (print-syntax-to-editor stx -text controller config + (calculate-columns) + (send -text last-position))]) (send* -text (insert "\n") ;;(scroll-to-position current-position) ) display))) - (define/public (calculate-columns) + (define/private (calculate-columns) (define style (code-style -text (send config get-syntax-font-size))) (define char-width (send style get-text-width (send -ecanvas get-dc))) (define-values (canvas-w canvas-h) (send -ecanvas get-client-size)) diff --git a/collects/macro-debugger/view/frame.ss b/collects/macro-debugger/view/frame.ss index 4cd2f150c2..29688ba4f2 100644 --- a/collects/macro-debugger/view/frame.ss +++ b/collects/macro-debugger/view/frame.ss @@ -54,7 +54,6 @@ (define/override (on-size w h) (send config set-width w) (send config set-height h) - (send config set-columns (send (send widget get-view) calculate-columns)) (send widget update/preserve-view)) (define warning-panel