Add support for final tuple classes which cannot be subclassed: TUPLE: foo ... ; final

db4
Slava Pestov 2010-02-18 02:19:57 +13:00
parent 41433da61b
commit 01824d41be
10 changed files with 77 additions and 12 deletions

View File

@ -1,11 +1,11 @@
! (c)Joe Groff bsd license ! (c)Joe Groff bsd license
USING: accessors alien alien.c-types alien.data ascii USING: accessors alien alien.c-types alien.data ascii
assocs byte-arrays classes.struct classes.tuple.private assocs byte-arrays classes.struct classes.tuple.private classes.tuple
combinators compiler.tree.debugger compiler.units destructors combinators compiler.tree.debugger compiler.units destructors
io.encodings.utf8 io.pathnames io.streams.string kernel libc io.encodings.utf8 io.pathnames io.streams.string kernel libc
literals math mirrors namespaces prettyprint literals math mirrors namespaces prettyprint
prettyprint.config see sequences specialized-arrays system prettyprint.config see sequences specialized-arrays system
tools.test parser lexer eval layouts ; tools.test parser lexer eval layouts generic.single classes ;
FROM: math => float ; FROM: math => float ;
QUALIFIED-WITH: alien.c-types c QUALIFIED-WITH: alien.c-types c
SPECIALIZED-ARRAY: char SPECIALIZED-ARRAY: char
@ -338,13 +338,28 @@ STRUCT: struct-that's-a-word { x int } ;
[ [
"USE: classes.struct IN: classes.struct.tests TUPLE: not-a-struct ; S{ not-a-struct }" "USE: classes.struct IN: classes.struct.tests TUPLE: not-a-struct ; S{ not-a-struct }"
eval( -- value ) eval( -- value )
] must-fail ] [ error>> no-method? ] must-fail-with
! Subclassing a struct class should not be allowed ! Subclassing a struct class should not be allowed
[ [
"USE: classes.struct IN: classes.struct.tests STRUCT: a-struct { x int } ; TUPLE: not-a-struct < a-struct ;" "USING: alien.c-types classes.struct ; IN: classes.struct.tests STRUCT: a-struct { x int } ; TUPLE: not-a-struct < a-struct ;"
eval( -- ) eval( -- )
] must-fail ] [ error>> bad-superclass? ] must-fail-with
! Changing a superclass into a struct should reset the subclass
TUPLE: will-become-struct ;
TUPLE: a-subclass < will-become-struct ;
[ f ] [ will-become-struct struct-class? ] unit-test
[ will-become-struct ] [ a-subclass superclass ] unit-test
[ ] [ "IN: classes.struct.tests USING: classes.struct alien.c-types ; STRUCT: will-become-struct { x int } ;" eval( -- ) ] unit-test
[ t ] [ will-become-struct struct-class? ] unit-test
[ tuple ] [ a-subclass superclass ] unit-test
! Remove c-type when struct class is forgotten ! Remove c-type when struct class is forgotten
[ ] [ [ ] [

View File

@ -32,8 +32,6 @@ TUPLE: struct-bit-slot-spec < struct-slot-spec
PREDICATE: struct-class < tuple-class PREDICATE: struct-class < tuple-class
superclass \ struct eq? ; superclass \ struct eq? ;
M: struct-class valid-superclass? drop f ;
SLOT: fields SLOT: fields
: struct-slots ( struct-class -- slots ) : struct-slots ( struct-class -- slots )
@ -273,7 +271,7 @@ M: struct binary-zero? >c-ptr [ 0 = ] all? ;
[ type>> c-type drop ] each ; [ type>> c-type drop ] each ;
: redefine-struct-tuple-class ( class -- ) : redefine-struct-tuple-class ( class -- )
[ dup class? [ forget-class ] [ drop ] if ] [ struct f define-tuple-class ] bi ; [ struct f define-tuple-class ] [ make-final ] bi ;
:: (define-struct-class) ( class slots offsets-quot -- ) :: (define-struct-class) ( class slots offsets-quot -- )
slots empty? [ struct-must-have-slots ] when slots empty? [ struct-must-have-slots ] when

View File

@ -194,7 +194,7 @@ M: not-a-tuple summary
drop "Not a tuple" ; drop "Not a tuple" ;
M: bad-superclass summary M: bad-superclass summary
drop "Tuple classes can only inherit from other tuple classes" ; drop "Tuple classes can only inherit from non-final tuple classes" ;
M: no-initial-value summary M: no-initial-value summary
drop "Initial value must be provided for slots specialized to this class" ; drop "Initial value must be provided for slots specialized to this class" ;

View File

@ -63,6 +63,9 @@ FUNCTOR-SYNTAX: TUPLE:
} case } case
\ define-tuple-class suffix! ; \ define-tuple-class suffix! ;
FUNCTOR-SYNTAX: final
[ word make-final ] append! ;
FUNCTOR-SYNTAX: SINGLETON: FUNCTOR-SYNTAX: SINGLETON:
scan-param suffix! scan-param suffix!
\ define-singleton-class suffix! ; \ define-singleton-class suffix! ;

View File

@ -97,3 +97,11 @@ TYPED: no-outputs-unboxable-input ( x: unboxable3 -- )
buh set ; buh set ;
[ T{ unboxable3 } ] [ T{ unboxable3 } no-outputs-unboxable-input buh get ] unit-test [ T{ unboxable3 } ] [ T{ unboxable3 } no-outputs-unboxable-input buh get ] unit-test
! Reported by littledan
TUPLE: superclass x ;
TUPLE: subclass < superclass y ;
TYPED: unbox-fail ( superclass: a -- ? ) subclass? ;
[ t ] [ subclass new unbox-fail ] unit-test

View File

@ -49,6 +49,7 @@ IN: bootstrap.syntax
"SYMBOLS:" "SYMBOLS:"
"CONSTANT:" "CONSTANT:"
"TUPLE:" "TUPLE:"
"final"
"SLOT:" "SLOT:"
"T{" "T{"
"UNION:" "UNION:"

View File

@ -8,8 +8,9 @@ IN: classes.parser
: create-class-in ( string -- word ) : create-class-in ( string -- word )
current-vocab create current-vocab create
dup set-word
dup save-class-location dup save-class-location
dup create-predicate-word dup set-word save-location ; dup create-predicate-word save-location ;
: CREATE-CLASS ( -- word ) : CREATE-CLASS ( -- word )
scan create-class-in ; scan create-class-in ;

View File

@ -770,3 +770,30 @@ TUPLE: tuple-predicate-redefine-test ;
[ ] [ "IN: classes.tuple.tests TUPLE: tuple-predicate-redefine-test ;" eval( -- ) ] unit-test [ ] [ "IN: classes.tuple.tests TUPLE: tuple-predicate-redefine-test ;" eval( -- ) ] unit-test
[ t ] [ \ tuple-predicate-redefine-test? predicate? ] unit-test [ t ] [ \ tuple-predicate-redefine-test? predicate? ] unit-test
! Final classes
TUPLE: final-superclass ;
TUPLE: final-subclass < final-superclass ;
[ final-superclass ] [ final-subclass superclass ] unit-test
! Making the superclass final should change the superclass of the subclass
[ ] [ "IN: classes.tuple.tests TUPLE: final-superclass ; final" eval( -- ) ] unit-test
[ tuple ] [ final-subclass superclass ] unit-test
[ t ] [ \ final-subclass valid-superclass? ] unit-test
! Subclassing a final class should fail
[ "IN: classes.tuple.tests TUPLE: final-subclass < final-superclass ;" eval( -- ) ]
[ error>> bad-superclass? ] must-fail-with
! Making a final class non-final should work
[ ] [ "IN: classes.tuple.tests TUPLE: final-superclass ;" eval( -- ) ] unit-test
[ ] [ "IN: classes.tuple.tests TUPLE: final-subclass < final-superclass ; final" eval( -- ) ] unit-test
! Changing a superclass should not change the final status of a subclass
[ ] [ "IN: classes.tuple.tests TUPLE: final-superclass x ;" eval( -- ) ] unit-test
[ f ] [ \ final-subclass valid-superclass? ] unit-test

View File

@ -240,7 +240,7 @@ M: tuple-class update-class
GENERIC: valid-superclass? ( class -- ? ) GENERIC: valid-superclass? ( class -- ? )
M: tuple-class valid-superclass? drop t ; M: tuple-class valid-superclass? "final" word-prop not ;
M: builtin-class valid-superclass? tuple eq? ; M: builtin-class valid-superclass? tuple eq? ;
@ -266,8 +266,16 @@ PRIVATE>
: define-tuple-class ( class superclass slots -- ) : define-tuple-class ( class superclass slots -- )
over check-superclass over check-superclass
over prepare-slots over prepare-slots
pick f "final" set-word-prop
(define-tuple-class) ; (define-tuple-class) ;
GENERIC: make-final ( class -- )
M: tuple-class make-final
[ dup class-usage keys ?metaclass-changed ]
[ t "final" set-word-prop ]
bi ;
M: word (define-tuple-class) M: word (define-tuple-class)
define-new-tuple-class ; define-new-tuple-class ;
@ -301,7 +309,7 @@ M: tuple-class reset-class
] with each ] with each
] [ ] [
[ call-next-method ] [ call-next-method ]
[ { "layout" "slots" "boa-check" "prototype" } reset-props ] [ { "layout" "slots" "boa-check" "prototype" "final" } reset-props ]
bi bi
] bi ; ] bi ;

View File

@ -204,6 +204,10 @@ IN: bootstrap.syntax
parse-tuple-definition define-tuple-class parse-tuple-definition define-tuple-class
] define-core-syntax ] define-core-syntax
"final" [
word make-final
] define-core-syntax
"SLOT:" [ "SLOT:" [
scan define-protocol-slot scan define-protocol-slot
] define-core-syntax ] define-core-syntax