stxclass:
added call to internal-definition-seal in lib added static-of stxclass ported class-iop from macros planet package svn: r13086
This commit is contained in:
parent
cba8e0d079
commit
ccfc18829f
|
@ -69,6 +69,20 @@
|
||||||
#:pattern 'static
|
#:pattern 'static
|
||||||
#:reason "not an identifier"))))
|
#:reason "not an identifier"))))
|
||||||
|
|
||||||
|
(define-basic-syntax-class (static-of name pred)
|
||||||
|
([value 0])
|
||||||
|
(lambda (x name pred)
|
||||||
|
(let/ec escape
|
||||||
|
(define (bad)
|
||||||
|
(escape (fail-sc x
|
||||||
|
#:pattern 'name
|
||||||
|
#:reason (format "not bound as ~a" name))))
|
||||||
|
(if (identifier? x)
|
||||||
|
(let ([value (syntax-local-value x bad)])
|
||||||
|
(unless (pred value) (bad))
|
||||||
|
(list value))
|
||||||
|
(bad)))))
|
||||||
|
|
||||||
(define-basic-syntax-class struct-name
|
(define-basic-syntax-class struct-name
|
||||||
([descriptor 0]
|
([descriptor 0]
|
||||||
[constructor 0]
|
[constructor 0]
|
||||||
|
|
|
@ -185,7 +185,9 @@
|
||||||
[args (cdr p)])
|
[args (cdr p)])
|
||||||
(unless (equal? (length (sc-inputs stxclass)) (length args))
|
(unless (equal? (length (sc-inputs stxclass)) (length args))
|
||||||
(raise-syntax-error 'syntax-class
|
(raise-syntax-error 'syntax-class
|
||||||
"too few arguments for syntax class"
|
(format "too few arguments for syntax class ~a (expected ~s)"
|
||||||
|
(sc-name stxclass)
|
||||||
|
(length (sc-inputs stxclass)))
|
||||||
id))
|
id))
|
||||||
(values id stxclass args (ssc? stxclass))))]
|
(values id stxclass args (ssc? stxclass))))]
|
||||||
[else (values id #f null #f)]))
|
[else (values id #f null #f)]))
|
||||||
|
|
|
@ -214,6 +214,7 @@
|
||||||
[_
|
[_
|
||||||
(loop (stx-cdr x) (cons ee ex) #t)]))]
|
(loop (stx-cdr x) (cons ee ex) #t)]))]
|
||||||
[(stx-null? x)
|
[(stx-null? x)
|
||||||
|
(internal-definition-context-seal intdef)
|
||||||
(reverse ex)]))))
|
(reverse ex)]))))
|
||||||
|
|
||||||
|
|
||||||
|
|
73
collects/macro-debugger/util/class-ct.ss
Normal file
73
collects/macro-debugger/util/class-ct.ss
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#lang scheme/base
|
||||||
|
(require (for-template scheme/base
|
||||||
|
scheme/class)
|
||||||
|
macro-debugger/stxclass/stxclass)
|
||||||
|
|
||||||
|
(provide static-interface?
|
||||||
|
make-static-interface
|
||||||
|
static-interface-dynamic
|
||||||
|
static-interface-members
|
||||||
|
|
||||||
|
make-checked-binding
|
||||||
|
checked-binding?
|
||||||
|
checked-binding-dynamic
|
||||||
|
checked-binding-iface
|
||||||
|
|
||||||
|
checked-binding
|
||||||
|
static-interface)
|
||||||
|
|
||||||
|
(define-struct static-interface (dynamic members)
|
||||||
|
#:omit-define-syntaxes
|
||||||
|
#:property prop:procedure
|
||||||
|
(lambda (self stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(ifname . args)
|
||||||
|
(datum->syntax stx (cons #'(#%expression ifname) #'args) stx)]
|
||||||
|
[ifname
|
||||||
|
(identifier? #'ifname)
|
||||||
|
(static-interface-dynamic self)])))
|
||||||
|
|
||||||
|
(define-struct raw-checked-binding (dynamic iface)
|
||||||
|
#:omit-define-syntaxes
|
||||||
|
#:property prop:procedure
|
||||||
|
(lambda (self stx)
|
||||||
|
(syntax-case stx (set!)
|
||||||
|
[(set! var expr)
|
||||||
|
#`(let ([newval expr])
|
||||||
|
(unless (is-a? newval #,(static-interface-dynamic
|
||||||
|
(raw-checked-binding-iface self)))
|
||||||
|
(error 'check "interface check failed on: ~e" newval))
|
||||||
|
(set! #,(raw-checked-binding-dynamic self) newval))]
|
||||||
|
[(var . args)
|
||||||
|
(datum->syntax stx (cons #'(#%expression var) #'args) stx)]
|
||||||
|
[var
|
||||||
|
(identifier? #'var)
|
||||||
|
(raw-checked-binding-dynamic self)]
|
||||||
|
[else
|
||||||
|
(raise-syntax-error #f "oops" stx)])))
|
||||||
|
|
||||||
|
(define (make-checked-binding dynamic iface)
|
||||||
|
(make-set!-transformer
|
||||||
|
(make-raw-checked-binding dynamic iface)))
|
||||||
|
|
||||||
|
(define (checked-binding? x)
|
||||||
|
(and (set!-transformer? x)
|
||||||
|
(raw-checked-binding? (set!-transformer-procedure x))))
|
||||||
|
|
||||||
|
(define (checked-binding-dynamic x)
|
||||||
|
(raw-checked-binding-dynamic (set!-transformer-procedure x)))
|
||||||
|
|
||||||
|
(define (checked-binding-iface x)
|
||||||
|
(raw-checked-binding-iface (set!-transformer-procedure x)))
|
||||||
|
|
||||||
|
;; Syntax
|
||||||
|
|
||||||
|
(define-syntax-class static-interface
|
||||||
|
(pattern x
|
||||||
|
#:declare x (static-of 'static-interface static-interface?)
|
||||||
|
#:with value #'x.value))
|
||||||
|
|
||||||
|
(define-syntax-class checked-binding
|
||||||
|
(pattern x
|
||||||
|
#:declare x (static-of 'checked-binding checked-binding?)
|
||||||
|
#:with value #'x.value))
|
224
collects/macro-debugger/util/class-iop.ss
Normal file
224
collects/macro-debugger/util/class-iop.ss
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
#lang scheme/base
|
||||||
|
(require scheme/class
|
||||||
|
(for-syntax scheme/base
|
||||||
|
macro-debugger/stxclass/stxclass
|
||||||
|
;; "stx.ss"
|
||||||
|
"class-ct.ss"))
|
||||||
|
(provide define-interface
|
||||||
|
define-interface/dynamic
|
||||||
|
|
||||||
|
send:
|
||||||
|
send*:
|
||||||
|
send/apply:
|
||||||
|
|
||||||
|
define:
|
||||||
|
lambda:
|
||||||
|
init:
|
||||||
|
init-private:)
|
||||||
|
|
||||||
|
;; Configuration
|
||||||
|
(define-for-syntax warn-on-dynamic-interfaces? #f)
|
||||||
|
(define-for-syntax warn-on-dynamic-object-check-generation? #f)
|
||||||
|
(define-for-syntax warn-on-dynamic-object-check? #f)
|
||||||
|
(define-for-syntax define-dotted-names #f)
|
||||||
|
|
||||||
|
;; define-interface SYNTAX
|
||||||
|
;; (define-interface NAME (IDENTIFIER ...))
|
||||||
|
;; Defines NAME as an interface.
|
||||||
|
(define-syntax (define-interface stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ name:id (mname:id ...))
|
||||||
|
#'(define-interface/dynamic name
|
||||||
|
(let ([name (interface () mname ...)]) name)
|
||||||
|
(mname ...))]))
|
||||||
|
|
||||||
|
;; define-interface/dynamic SYNTAX
|
||||||
|
;; (define-interface/dynamic NAME EXPR (IDENTIFIER ...))
|
||||||
|
;; Defines NAME as a static interface containing the names listed.
|
||||||
|
;; The EXPR is used as the dynamic componenent of the interface, and
|
||||||
|
;; it should contain a superset of the names listed.
|
||||||
|
(define-syntax (define-interface/dynamic stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ name:id dynamic-interface:expr (mname:id ...))
|
||||||
|
(with-syntax ([(dynamic-name) (generate-temporaries #'(name))])
|
||||||
|
#'(begin (define dynamic-name
|
||||||
|
(let ([dynamic-name dynamic-interface])
|
||||||
|
(for-each
|
||||||
|
(lambda (m)
|
||||||
|
(unless (method-in-interface? m dynamic-name)
|
||||||
|
(error 'name "dynamic interface missing method '~s'" m)))
|
||||||
|
'(mname ...))
|
||||||
|
dynamic-name))
|
||||||
|
(define-syntax name
|
||||||
|
(make-static-interface #'dynamic-name '(mname ...)))))]))
|
||||||
|
|
||||||
|
;; Checked send
|
||||||
|
|
||||||
|
(define-syntax (send: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(send: obj:expr iface:static-interface method:id . args)
|
||||||
|
#`(begin (check-method<-interface method iface)
|
||||||
|
#,(syntax/loc stx
|
||||||
|
(send (check-object<:interface send: obj iface)
|
||||||
|
method . args)))]))
|
||||||
|
|
||||||
|
(define-syntax (send*: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(send*: obj:expr iface:static-interface (method:id . args) ...)
|
||||||
|
#`(begin (check-method<-interface method iface) ...
|
||||||
|
#,(syntax/loc stx
|
||||||
|
(send* (check-object<:interface send*: obj iface)
|
||||||
|
(method . args) ...)))]))
|
||||||
|
|
||||||
|
(define-syntax (send/apply: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(send/apply: obj:expr iface:static-interface method:id . args)
|
||||||
|
#`(begin (check-method<-interface method iface)
|
||||||
|
#,(syntax/loc stx
|
||||||
|
(send/apply (check-object<:interface send/apply obj iface)
|
||||||
|
method . args)))]))
|
||||||
|
|
||||||
|
;;
|
||||||
|
|
||||||
|
;; check-method<-interface SYNTAX
|
||||||
|
(define-syntax (check-method<-interface stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(check-method<-interface method:id iface:static-interface)
|
||||||
|
(let ([si #'iface.value])
|
||||||
|
(unless (member (syntax-e #'method) (static-interface-members si))
|
||||||
|
(raise-syntax-error 'checked-send
|
||||||
|
"method not in static interface"
|
||||||
|
#'method))
|
||||||
|
#''okay)]
|
||||||
|
[(check-method<-interface method:id iface:expr)
|
||||||
|
(begin (when warn-on-dynamic-interfaces?
|
||||||
|
(printf "dynamic interface check: ~s,~s: method: ~a~n"
|
||||||
|
(syntax-source #'method)
|
||||||
|
(syntax-line #'method)
|
||||||
|
(syntax-e #'method)))
|
||||||
|
#`(let ([ifc iface])
|
||||||
|
(unless (method-in-interface? 'method ifc)
|
||||||
|
(error 'checked-send
|
||||||
|
"interface does not contain method '~a': ~e"
|
||||||
|
'method
|
||||||
|
ifc))))]))
|
||||||
|
|
||||||
|
;; check-object<:interface SYNTAX
|
||||||
|
(define-syntax (check-object<:interface stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ for-whom obj:checked-binding iface:static-interface)
|
||||||
|
(if (eq? (checked-binding-iface #'obj.value) #'iface.value)
|
||||||
|
#'obj
|
||||||
|
(syntax/loc stx
|
||||||
|
(check-object<:interface for-whom (#%expression obj) (#%expression iface))))]
|
||||||
|
[(_ for-whom obj:expr iface:expr)
|
||||||
|
(begin
|
||||||
|
(when warn-on-dynamic-object-check-generation?
|
||||||
|
(printf "dynamic object check: ~s,~s~n"
|
||||||
|
(syntax-source #'obj)
|
||||||
|
(syntax-line #'obj)))
|
||||||
|
#'(dynamic:check-object<:interface 'for-whom obj iface))]))
|
||||||
|
|
||||||
|
(define (dynamic:check-object<:interface for-whom obj iface)
|
||||||
|
(unless (is-a? obj iface)
|
||||||
|
(error for-whom "interface check failed on: ~e" obj))
|
||||||
|
(let-syntax ([x (lambda (stx)
|
||||||
|
(if warn-on-dynamic-object-check?
|
||||||
|
#'(printf "dynamic: object check passed~n")
|
||||||
|
#'(void)))])
|
||||||
|
x)
|
||||||
|
obj)
|
||||||
|
|
||||||
|
;;
|
||||||
|
|
||||||
|
(define-syntax (define: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ name:id iface:static-interface expr)
|
||||||
|
(let ([si #'iface.value])
|
||||||
|
(with-syntax ([(name-internal) (generate-temporaries #'(name))]
|
||||||
|
[(method ...) (static-interface-members si)]
|
||||||
|
[(name.method ...)
|
||||||
|
(map (lambda (m)
|
||||||
|
(datum->syntax #'name
|
||||||
|
(string->symbol (format "~a.~a" (syntax-e #'name) m))))
|
||||||
|
(static-interface-members si))])
|
||||||
|
#`(begin (define name-internal
|
||||||
|
(check-object<:interface define: expr iface))
|
||||||
|
(define-syntax name
|
||||||
|
(make-checked-binding
|
||||||
|
#'name-internal
|
||||||
|
(syntax-local-value #'iface)))
|
||||||
|
#,(if define-dotted-names
|
||||||
|
#'(begin
|
||||||
|
(define-syntax name.method
|
||||||
|
(syntax-rules ()
|
||||||
|
[(name.method . args)
|
||||||
|
(send: name iface method . args)]))
|
||||||
|
...)
|
||||||
|
#'(begin)))))]
|
||||||
|
[(_ (f:id . args) . body)
|
||||||
|
#'(define f (lambda: args . body))]))
|
||||||
|
|
||||||
|
(define-syntax (lambda: stx)
|
||||||
|
;; FIXME: rewrite as stxclass
|
||||||
|
(define (arg->define stx temp)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(arg : iface)
|
||||||
|
(and (identifier? #'arg)
|
||||||
|
(eq? ': (syntax-e #':)))
|
||||||
|
#`(define: arg iface #,temp)]
|
||||||
|
[arg
|
||||||
|
(identifier? #'arg)
|
||||||
|
#`(define-syntax arg (make-rename-transformer #'#,temp))]))
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ (arg ...) . body)
|
||||||
|
(let ([temporaries (generate-temporaries #'(arg ...))])
|
||||||
|
(with-syntax ([(temp ...) temporaries]
|
||||||
|
[(checked-definition ...)
|
||||||
|
(map arg->define
|
||||||
|
(syntax->list #'(arg ...))
|
||||||
|
temporaries)])
|
||||||
|
#'(lambda (temp ...)
|
||||||
|
(let ()
|
||||||
|
checked-definition ...
|
||||||
|
(let () . body)))))]))
|
||||||
|
|
||||||
|
(define-syntax (init: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ (name:id iface:static-interface) ...)
|
||||||
|
#'(begin (init1: name iface) ...)]))
|
||||||
|
|
||||||
|
(define-syntax (init1: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ name:id iface:static-interface)
|
||||||
|
(with-syntax ([(name-internal) (generate-temporaries #'(name))])
|
||||||
|
#'(begin (init (name name-internal))
|
||||||
|
(void (check-object<:interface init: name-internal iface))
|
||||||
|
(define-syntax name
|
||||||
|
(make-checked-binding
|
||||||
|
#'name-internal
|
||||||
|
(syntax-local-value #'iface)))))]))
|
||||||
|
|
||||||
|
(define-syntax (init-private stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(init-private form ...)
|
||||||
|
#'(begin (init-private1 form) ...)]))
|
||||||
|
|
||||||
|
(define-syntax (init-private1 stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(init-private1 id:id)
|
||||||
|
(with-syntax ([(id-internal) (generate-temporaries #'(id))])
|
||||||
|
#'(begin (init (id-internal id))
|
||||||
|
(define id id-internal)))]))
|
||||||
|
|
||||||
|
(define-syntax (init-private: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ (name:id iface:static-interface) ...)
|
||||||
|
#'(begin (init-private1: name iface) ...)]))
|
||||||
|
|
||||||
|
(define-syntax (init-private1: stx)
|
||||||
|
(syntax-parse stx
|
||||||
|
[(_ name:id iface:static-interface)
|
||||||
|
(with-syntax ([(id-internal) (generate-temporaries #'(id))])
|
||||||
|
#'(begin (init (id-internal name))
|
||||||
|
(define: name iface id-internal)))]))
|
Loading…
Reference in New Issue
Block a user