#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
htdp/error
(rename-in lang/prim (first-order->higher-order f2h)))
(provide (all-from-out "my-private-world.ss")
show-it)
(provide
launch-many-worlds
)
(provide
sexp? scene? )
(define-keywords AllSpec
[on-tick (function-with-arity
1
except
[(_ x rate)
#'(list (proc> 'on-tick (f2h x) 1)
(num> 'on-tick rate positive? "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)
(when (free-identifier=? kw #'record?)
(syntax-case #'E ()
[(V) (set! rec? #'V)]
[_ (err 'record? stx)])))]
[args (->args stx (syntax (clause ...)) AllSpec WldSpec ->rec? "world")])
#`(parameterize ([current-eventspace (make-eventspace)])
(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) (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 #`(parameterize ([current-eventspace (make-eventspace)])
(send (new universe% [universe0 u] #,@args) last))]))]))