#lang scheme/gui
(require (for-syntax 2htdp/private/syn-aux
(rename-in lang/prim (first-order->higher-order f2h)))
2htdp/private/syn-aux-aux
2htdp/private/syn-aux
2htdp/private/check-aux
"my-private-world.ss"
2htdp/private/universe
2htdp/private/launch-many-worlds
2htdp/private/universe-image 2htdp/private/stop
htdp/error
(rename-in lang/prim (first-order->higher-order f2h)))
(provide (all-from-out "my-private-world.ss")
show-it)
(provide
(rename-out (make-stop-the-world stop-with)))
(provide
launch-many-worlds
)
(provide
sexp? )
(define-keywords AllSpec
[on-tick (function-with-arity
1
except
[(_ x rate)
#'(list (proc> 'on-tick (f2h x) 1)
(num> 'on-tick rate (lambda (x)
(and (real? x) (positive? x)))
"pos. number" "rate"))])]
[state (expr-with-check bool> "expected a boolean (show state or not)")]
[check-with (function-with-arity 1)])
(provide big-bang make-package package? run-movie mouse-event? mouse=? key-event? key=? LOCALHOST )
(provide-higher-order-primitive
run-simulation (create-scene) )
(provide-higher-order-primitive
animate (create-scene) )
(define MOUSE-EVTS
'("button-down"
"button-up"
"drag"
"move"
"enter"
"leave"))
(define KEY-EVTS
'("left"
"right"
"up"
"down"
"release"
"start"
"cancel"
"clear"
"shift"
"control"
"menu"
"pause"
"capital"
"prior"
"next"
"end"
"home"
"escape"
"select"
"print"
"execute"
"snapshot"
"insert"
"help"
"numpad0" "numpad1" "numpad2" "numpad3" "numpad4"
"numpad5" "numpad6" "numpad7" "numpad8" "numpad9"
"numpad-enter" "multiply" "add" "separator" "subtract" "decimal" "divide"
"f1" "f2" "f3" "f4" "f5" "f6" "f7" "f8" "f9" "f10" "f11" "f12" "f13"
"f14" "f15" "f16" "f17" "f18" "f19" "f20" "f21" "f22" "f23" "f24"
"numlock"
"scroll"
"wheel-up"
"wheel-down"))
(define-keywords WldSpec
[on-draw (function-with-arity
1
except
[(_ f width height)
#'(list (proc> 'on-draw (f2h f) 1)
(nat> 'on-draw width "width")
(nat> 'on-draw height "height"))])]
[on-mouse (function-with-arity 4)]
[on-key (function-with-arity 2)]
[on-receive (function-with-arity 2)]
[stop-when (function-with-arity
1
except
[(_ stop? last-picture)
#'(list (proc> 'stop-when (f2h stop?) 1)
(proc> 'stop-when (f2h last-picture) 1))])]
[record? (expr-with-check bool> "expected a boolean (to record? or not)")]
[name (expr-with-check string> "expected a name (string) for the world")]
[register (expr-with-check ip> "expected a host (ip address)")])
(define-syntax (big-bang stx)
(define world0 "big-bang needs at least an initial world")
(syntax-case stx ()
[(big-bang) (raise-syntax-error #f world0 stx)]
[(big-bang w clause ...)
(let* ([rec? #'#f]
[->rec?
(lambda (kw E)
(when (free-identifier=? kw #'record?)
(syntax-case E ()
[(V) (set! rec? #'V)]
[_ (err '#'record? stx)])))]
[args
(->args stx (syntax (clause ...)) AllSpec WldSpec ->rec? "world")])
#`(let* ([esp (make-eventspace)]
[thd (eventspace-handler-thread esp)])
(with-handlers ((exn:break? (lambda (x) (break-thread thd))))
(parameterize ([current-eventspace esp])
(let ([o (new (if #,rec? aworld% world%) [world0 w] #,@args)])
(send o last))))))]))
(define (run-simulation f)
(check-proc 'run-simulation f 1 "first" "one argument")
(big-bang 1 (on-tick add1) (on-draw f)))
(define animate run-simulation)
(define (run-movie r m*)
(check-arg 'run-movie (positive? r) "positive number" "first" r)
(check-arg 'run-movie (list? m*) "list (of images)" "second" m*)
(for-each (lambda (m) (check-image 'run-movie m "first" "list of images")) m*)
(let* ([fst (car m*)]
[wdt (image-width fst)]
[hgt (image-height fst)])
(big-bang
m*
(on-tick rest r)
(on-draw (lambda (m) (if (empty? m) (text "The End" 22 'red) (first m))))
(stop-when empty?))))
(define (mouse-event? a) (and (string? a) (pair? (member a MOUSE-EVTS))))
(define (mouse=? k m)
(check-arg 'mouse=? (mouse-event? k) 'MouseEvent "first" k)
(check-arg 'mouse=? (mouse-event? m) 'MouseEvent "second" m)
(string=? k m))
(define (key-event? k)
(and (string? k) (or (= (string-length k) 1) (pair? (member k KEY-EVTS)))))
(define (key=? k m)
(check-arg 'key=? (key-event? k) 'KEY-EVTS "first" k)
(check-arg 'key=? (key-event? m) 'KEY-EVTS "second" m)
(string=? k m))
(define LOCALHOST "127.0.0.1")
(provide
iworld? iworld=? iworld-name iworld1 iworld2
iworld3
make-bundle bundle? make-mail mail? universe )
(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)])
(define-syntax (universe stx)
(define legal "not a legal clause in a universe description")
(syntax-case stx ()
[(universe) (raise-syntax-error #f "not a legal universe description" stx)]
[(universe u) (raise-syntax-error #f "not a legal universe description" stx)]
[(universe u bind ...)
(let*
([args (->args stx (syntax (bind ...)) AllSpec UniSpec void "universe")]
[domain (map (compose syntax-e car) args)])
(cond
[(not (memq 'on-new domain))
(raise-syntax-error #f "missing on-new clause" stx)]
[(not (memq 'on-msg domain))
(raise-syntax-error #f "missing on-msg clause" stx)]
[else #`(let* ([esp (make-eventspace)]
[thd (eventspace-handler-thread esp)])
(with-handlers ((exn:break? (lambda (x) (break-thread thd))))
(parameterize ([current-eventspace esp])
(send (new universe% [universe0 u] #,@args) last))))]))]))