Better support for class top-level behavior
This commit is contained in:
parent
b9a175eed2
commit
0d5a775a62
|
@ -71,41 +71,42 @@
|
||||||
|
|
||||||
(define-syntax-class initializer-class
|
(define-syntax-class initializer-class
|
||||||
#:literals (#%plain-lambda)
|
#:literals (#%plain-lambda)
|
||||||
#:attributes (val)
|
#:attributes (initializer-body initializer-self-id
|
||||||
|
initializer-args-id)
|
||||||
(pattern (#%plain-lambda
|
(pattern (#%plain-lambda
|
||||||
(self:id super-go:id si_c:id si_inited?:id
|
(self:id super-go:id si_c:id si_inited?:id
|
||||||
si_leftovers:id init-args:id)
|
si_leftovers:id init-args:id)
|
||||||
body:initializer-body)
|
body:initializer-body)
|
||||||
#:with val #'body.val))
|
#:with initializer-body #'body.val
|
||||||
|
#:with initializer-self-id #'self
|
||||||
|
#:with initializer-args-id #'init-args))
|
||||||
|
|
||||||
(define-syntax-class make-methods-body
|
(define-syntax-class make-methods-body
|
||||||
#:literals (let-values letrec-syntaxes+values #%plain-app values)
|
#:literals (let-values letrec-syntaxes+values #%plain-app values)
|
||||||
#:attributes (initializer-body)
|
#:attributes (initializer-body initializer-self-id
|
||||||
|
initializer-args-id)
|
||||||
(pattern (letrec-values _
|
(pattern (letrec-values _
|
||||||
(#%plain-app
|
(#%plain-app
|
||||||
values
|
values
|
||||||
public:expr
|
public:expr
|
||||||
override:expr
|
override:expr
|
||||||
augride:expr
|
augride:expr
|
||||||
initializer:initializer-class))
|
:initializer-class)))
|
||||||
#:with initializer-body #'initializer.val)
|
(pattern (let-values () :make-methods-body))
|
||||||
(pattern (let-values () body:make-methods-body)
|
(pattern (letrec-syntaxes+values _ _ :make-methods-body)))
|
||||||
#:with initializer-body #'body.initializer-body)
|
|
||||||
(pattern (letrec-syntaxes+values _ _ body:make-methods-body)
|
|
||||||
#:with initializer-body #'body.initializer-body))
|
|
||||||
|
|
||||||
(define-syntax-class make-methods-class
|
(define-syntax-class make-methods-class
|
||||||
#:literals (let-values #%plain-lambda)
|
#:literals (let-values #%plain-lambda)
|
||||||
#:attributes (initializer-body)
|
#:attributes (initializer-body initializer-self-id
|
||||||
|
initializer-args-id)
|
||||||
(pattern (#%plain-lambda
|
(pattern (#%plain-lambda
|
||||||
(local-accessor:id local-mutator:id local-method-or-field:id ...)
|
(local-accessor:id local-mutator:id local-method-or-field:id ...)
|
||||||
(let-values ([(field-name:id) accessor-or-mutator] ...)
|
(let-values ([(field-name:id) accessor-or-mutator] ...)
|
||||||
body:make-methods-body))
|
:make-methods-body))))
|
||||||
#:with initializer-body #'body.initializer-body))
|
|
||||||
|
|
||||||
(define-syntax-class class-expansion
|
(define-syntax-class class-expansion
|
||||||
#:literals (let-values letrec-syntaxes+values #%plain-app)
|
#:literals (let-values letrec-syntaxes+values #%plain-app)
|
||||||
#:attributes (superclass-expr initializer-body
|
#:attributes (superclass-expr
|
||||||
init-internals init-externals
|
init-internals init-externals
|
||||||
init-field-internals init-field-externals
|
init-field-internals init-field-externals
|
||||||
optional-inits
|
optional-inits
|
||||||
|
@ -113,7 +114,10 @@
|
||||||
public-internals public-externals
|
public-internals public-externals
|
||||||
override-internals override-externals
|
override-internals override-externals
|
||||||
private-names
|
private-names
|
||||||
make-methods)
|
make-methods
|
||||||
|
initializer-body
|
||||||
|
initializer-self-id
|
||||||
|
initializer-args-id)
|
||||||
(pattern (let-values ()
|
(pattern (let-values ()
|
||||||
(letrec-syntaxes+values
|
(letrec-syntaxes+values
|
||||||
()
|
()
|
||||||
|
@ -124,9 +128,8 @@
|
||||||
(#%plain-app
|
(#%plain-app
|
||||||
compose-class:id
|
compose-class:id
|
||||||
internal:expr ...
|
internal:expr ...
|
||||||
make-methods:make-methods-class
|
(~and make-methods :make-methods-class)
|
||||||
(quote #f)))))
|
(quote #f)))))))
|
||||||
#:with initializer-body #'make-methods.initializer-body))
|
|
||||||
|
|
||||||
;; Syntax TCResults -> Type
|
;; Syntax TCResults -> Type
|
||||||
;; Type-check a class form by trawling its innards
|
;; Type-check a class form by trawling its innards
|
||||||
|
@ -282,6 +285,8 @@
|
||||||
(list->set (syntax->datum #'cls.init-internals))
|
(list->set (syntax->datum #'cls.init-internals))
|
||||||
local-private-table private-method-types
|
local-private-table private-method-types
|
||||||
this%-private-names
|
this%-private-names
|
||||||
|
#'cls.initializer-self-id
|
||||||
|
#'cls.initializer-args-id
|
||||||
self-type))
|
self-type))
|
||||||
(with-lexical-env/extend lexical-names/top-level lexical-types/top-level
|
(with-lexical-env/extend lexical-names/top-level lexical-types/top-level
|
||||||
(check-super-new provided-super-inits super-inits))
|
(check-super-new provided-super-inits super-inits))
|
||||||
|
@ -363,7 +368,7 @@
|
||||||
;; local-tables->lexical-env : Dict<Symbol, Symbol>
|
;; local-tables->lexical-env : Dict<Symbol, Symbol>
|
||||||
;; Dict<Symbol, Id> Dict List<Symbol>
|
;; Dict<Symbol, Id> Dict List<Symbol>
|
||||||
;; Dict<Symbol, (List Id Id)> Dict List<Symbol>
|
;; Dict<Symbol, (List Id Id)> Dict List<Symbol>
|
||||||
;; Type
|
;; Id Id Type
|
||||||
;; -> List<Id> List<Type> List<Id> List<Type>
|
;; -> List<Id> List<Type> List<Id> List<Type>
|
||||||
;; Construct mappings to put into the lexical type-checking environment
|
;; Construct mappings to put into the lexical type-checking environment
|
||||||
;; from the class local accessor mappings
|
;; from the class local accessor mappings
|
||||||
|
@ -373,6 +378,7 @@
|
||||||
local-init-table inits init-names
|
local-init-table inits init-names
|
||||||
local-private-table
|
local-private-table
|
||||||
private-types private-methods
|
private-types private-methods
|
||||||
|
self-id init-args-id
|
||||||
self-type)
|
self-type)
|
||||||
;; localize to accessor names via the provided tables
|
;; localize to accessor names via the provided tables
|
||||||
(define (localize local-table names)
|
(define (localize local-table names)
|
||||||
|
@ -430,10 +436,16 @@
|
||||||
localized-private-methods
|
localized-private-methods
|
||||||
localized-field-get-names
|
localized-field-get-names
|
||||||
localized-field-set-names
|
localized-field-set-names
|
||||||
localized-init-names)
|
localized-init-names
|
||||||
|
;; Set `self` to the self-type and `init-args`
|
||||||
|
;; to Any, so that accessors can use them without
|
||||||
|
;; problems.
|
||||||
|
;; Be careful though!
|
||||||
|
(list self-id init-args-id))
|
||||||
(append method-types private-method-types
|
(append method-types private-method-types
|
||||||
field-get-types field-set-types
|
field-get-types field-set-types
|
||||||
init-types)))
|
init-types
|
||||||
|
(list self-type (make-Univ)))))
|
||||||
|
|
||||||
;; check-methods : Listof<Syntax> Dict<Symbol, Symbol> Dict Type
|
;; check-methods : Listof<Syntax> Dict<Symbol, Symbol> Dict Type
|
||||||
;; -> Dict<Symbol, Type>
|
;; -> Dict<Symbol, Type>
|
||||||
|
|
|
@ -347,6 +347,20 @@
|
||||||
(define/public (m y) 0)
|
(define/public (m y) 0)
|
||||||
(+ 3 5))))
|
(+ 3 5))))
|
||||||
|
|
||||||
|
;; test top-level method call
|
||||||
|
(check-ok
|
||||||
|
(: c% (Class [m (Integer -> Integer)]))
|
||||||
|
(define c% (class: object% (super-new)
|
||||||
|
(define/public (m y) 0)
|
||||||
|
(m 3))))
|
||||||
|
|
||||||
|
;; test top-level field access
|
||||||
|
(check-ok
|
||||||
|
(: c% (Class (field [f String])))
|
||||||
|
(define c% (class: object% (super-new)
|
||||||
|
(field [f "foo"])
|
||||||
|
(string-append f "z"))))
|
||||||
|
|
||||||
;; fails, bad top-level expression
|
;; fails, bad top-level expression
|
||||||
(check-err
|
(check-err
|
||||||
(: c% (Class [m (Integer -> Integer)]))
|
(: c% (Class [m (Integer -> Integer)]))
|
||||||
|
@ -354,6 +368,20 @@
|
||||||
(define/public (m y) 0)
|
(define/public (m y) 0)
|
||||||
(+ "foo" 5))))
|
(+ "foo" 5))))
|
||||||
|
|
||||||
|
;; fails, ill-typed method call
|
||||||
|
(check-err
|
||||||
|
(: c% (Class [m (Integer -> Integer)]))
|
||||||
|
(define c% (class: object% (super-new)
|
||||||
|
(define/public (m y) 0)
|
||||||
|
(m "foo"))))
|
||||||
|
|
||||||
|
;; fails, ill-typed field access
|
||||||
|
(check-err
|
||||||
|
(: c% (Class [f String]))
|
||||||
|
(define c% (class: object% (super-new)
|
||||||
|
(field [f "foo"])
|
||||||
|
(set! f 5))))
|
||||||
|
|
||||||
;; test private method
|
;; test private method
|
||||||
(check-ok
|
(check-ok
|
||||||
(class: object% (super-new)
|
(class: object% (super-new)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user