Fix erg's tuple definition bugs

db4
Slava Pestov 2008-07-13 21:06:50 -05:00
parent b887849eb9
commit 817035099c
9 changed files with 110 additions and 49 deletions

View File

@ -1,35 +1,44 @@
IN: classes.tuple.parser.tests
USING: accessors classes.tuple.parser lexer words classes
sequences math kernel slots tools.test parser compiler.units ;
sequences math kernel slots tools.test parser compiler.units
arrays classes.tuple ;
TUPLE: test-1 ;
[ t ] [ test-1 "slot-names" word-prop empty? ] unit-test
[ t ] [ test-1 "slots" word-prop empty? ] unit-test
TUPLE: test-2 < test-1 ;
[ t ] [ test-2 "slot-names" word-prop empty? ] unit-test
[ t ] [ test-2 "slots" word-prop empty? ] unit-test
[ test-1 ] [ test-2 superclass ] unit-test
TUPLE: test-3 a ;
[ { "a" } ] [ test-3 "slot-names" word-prop ] unit-test
[ { "a" } ] [ test-3 "slots" word-prop [ name>> ] map ] unit-test
[ object ] [ "a" test-3 "slots" word-prop slot-named class>> ] unit-test
TUPLE: test-4 < test-3 b ;
[ { "b" } ] [ test-4 "slot-names" word-prop ] unit-test
[ { "b" } ] [ test-4 "slots" word-prop [ name>> ] map ] unit-test
TUPLE: test-5 { a integer } ;
[ { { "a" integer } } ] [ test-5 "slot-names" word-prop ] unit-test
[ { { "a" integer } } ]
[
test-5 "slots" word-prop
[ [ name>> ] [ class>> ] bi 2array ] map
] unit-test
TUPLE: test-6 < test-5 { b integer } ;
[ integer ] [ "b" test-6 "slots" word-prop slot-named class>> ] unit-test
[ { { "b" integer } } ] [ test-6 "slot-names" word-prop ] unit-test
[ { { "b" integer } } ]
[
test-6 "slots" word-prop
[ [ name>> ] [ class>> ] bi 2array ] map
] unit-test
TUPLE: test-7 { b integer initial: 3 } ;
@ -39,6 +48,8 @@ TUPLE: test-8 { b integer read-only } ;
[ t ] [ "b" test-8 "slots" word-prop slot-named read-only>> ] unit-test
DEFER: foo
[ "IN: classes.tuple.parser.tests TUPLE: foo < test-1 < ;" eval ]
[ error>> invalid-slot-name? ]
must-fail-with
@ -51,17 +62,33 @@ must-fail-with
[ error>> unexpected-eof? ]
must-fail-with
[ "IN: classes.tuple.parser.tests USE: alien TUPLE: foo { slot dll } ;" eval ]
[ error>> no-initial-value? ]
2 [
[ "IN: classes.tuple.parser.tests USE: alien TUPLE: foo { slot dll } ;" eval ]
[ error>> no-initial-value? ]
must-fail-with
[ f ] [ \ foo tuple-class? ] unit-test
] times
2 [
[ "IN: classes.tuple.parser.tests USE: arrays TUPLE: foo { slot array initial: 5 } ;" eval ]
[ error>> bad-initial-value? ]
must-fail-with
[ f ] [ \ foo tuple-class? ] unit-test
] times
[ "IN: classes.tuple.parser.tests USE: arrays TUPLE: foo slot { slot array } ;" eval ]
[ error>> duplicate-slot-names? ]
must-fail-with
[ "IN: classes.tuple.parser.tests USE: arrays TUPLE: foo { slot array initial: 5 } ;" eval ]
[ error>> bad-initial-value? ]
must-fail-with
[ f ] [ \ foo tuple-class? ] unit-test
[ ] [
[
{ test-1 test-2 test-3 test-4 test-5 test-6 test-7 test-8 }
{ test-1 test-2 test-3 test-4 test-5 test-6 test-7 test-8 foo }
[ dup class? [ forget-class ] [ drop ] if ] each
] with-compilation-unit
] unit-test

View File

@ -4,10 +4,11 @@ USING: accessors kernel sets namespaces sequences summary parser
lexer combinators words classes.parser classes.tuple arrays ;
IN: classes.tuple.parser
: slot-names ( slots -- seq )
[ dup array? [ first ] when ] map ;
: shadowed-slots ( superclass slots -- shadowed )
[ all-slots [ name>> ] map ]
[ [ dup array? [ first ] when ] map ]
bi* intersect ;
[ all-slots [ name>> ] map ] [ slot-names ] bi* intersect ;
: check-slot-shadowing ( class superclass slots -- )
shadowed-slots [
@ -20,11 +21,19 @@ IN: classes.tuple.parser
] "" make note.
] with each ;
ERROR: duplicate-slot-names names ;
M: duplicate-slot-names summary
drop "Duplicate slot names" ;
: check-duplicate-slots ( slots -- )
slot-names duplicates
dup empty? [ drop ] [ duplicate-slot-names ] if ;
ERROR: invalid-slot-name name ;
M: invalid-slot-name summary
drop
"Invalid slot name" ;
drop "Invalid slot name" ;
: parse-long-slot-name ( -- )
[ scan , \ } parse-until % ] { } make ;
@ -38,7 +47,7 @@ M: invalid-slot-name summary
#! : ...
{
{ [ dup not ] [ unexpected-eof ] }
{ [ dup { ":" "(" "<" "\"" } member? ] [ invalid-slot-name ] }
{ [ dup { ":" "(" "<" "\"" "!" } member? ] [ invalid-slot-name ] }
{ [ dup ";" = ] [ drop f ] }
[ dup "{" = [ drop parse-long-slot-name ] when , t ]
} cond ;
@ -52,4 +61,6 @@ M: invalid-slot-name summary
{ ";" [ tuple f ] }
{ "<" [ scan-word [ parse-tuple-slots ] { } make ] }
[ tuple swap [ parse-slot-name [ parse-tuple-slots ] when ] { } make ]
} case 3dup check-slot-shadowing ;
} case
dup check-duplicate-slots
3dup check-slot-shadowing ;

View File

@ -346,11 +346,9 @@ HELP: tuple
$nl
"Tuple classes have additional word properties:"
{ $list
{ { $snippet "\"constructor\"" } " - a word for creating instances of this tuple class" }
{ { $snippet "\"predicate\"" } " - a quotation which tests if the top of the stack is an instance of this tuple class" }
{ { $snippet "\"slots\"" } " - a sequence of " { $link slot-spec } " instances" }
{ { $snippet "\"slot-names\"" } " - a sequence of strings naming the tuple's slots" }
{ { $snippet "\"tuple-size\"" } " - the number of slots" }
{ { $snippet "\"tuple-layout\"" } " - a " { $link tuple-layout } " instance" }
} } ;
HELP: define-tuple-predicate

View File

@ -443,36 +443,36 @@ TUPLE: redefinition-problem-2 ;
! Hardcore unit tests
USE: threads
\ thread slot-names "slot-names" set
\ thread "slots" word-prop "slots" set
[ ] [
[
\ thread tuple { "xxx" } "slot-names" get append
\ thread tuple { "xxx" } "slots" get append
define-tuple-class
] with-compilation-unit
[ 1337 sleep ] "Test" spawn drop
[
\ thread tuple "slot-names" get
\ thread tuple "slots" get
define-tuple-class
] with-compilation-unit
] unit-test
USE: vocabs
\ vocab slot-names "slot-names" set
\ vocab "slots" word-prop "slots" set
[ ] [
[
\ vocab tuple { "xxx" } "slot-names" get append
\ vocab tuple { "xxx" } "slots" get append
define-tuple-class
] with-compilation-unit
all-words drop
[
\ vocab tuple "slot-names" get
\ vocab tuple "slots" get
define-tuple-class
] with-compilation-unit
] unit-test

View File

@ -74,9 +74,6 @@ M: tuple-class slots>tuple
: >tuple ( seq -- tuple )
unclip slots>tuple ;
: slot-names ( class -- seq )
"slot-names" word-prop ;
ERROR: bad-superclass class ;
<PRIVATE
@ -104,7 +101,7 @@ ERROR: bad-superclass class ;
: superclass-size ( class -- n )
superclasses but-last-slice
[ slot-names length ] sigma ;
[ "slots" word-prop length ] sigma ;
: (instance-check-quot) ( class -- quot )
[
@ -138,19 +135,18 @@ ERROR: bad-superclass class ;
: define-tuple-prototype ( class -- )
dup tuple-prototype "prototype" set-word-prop ;
: generate-tuple-slots ( class slots -- slot-specs )
over superclass-size 2 + make-slots deprecated-slots ;
: finalize-tuple-slots ( class slots -- slots )
over superclass-size 2 + finalize-slots deprecated-slots ;
: define-tuple-slots ( class -- )
dup dup "slot-names" word-prop generate-tuple-slots
[ "slots" set-word-prop ]
dup dup "slots" word-prop finalize-tuple-slots
[ define-accessors ] ! new
[ define-slots ] ! old
2tri ;
2bi ;
: make-tuple-layout ( class -- layout )
[ ]
[ [ superclass-size ] [ slot-names length ] bi + ]
[ [ superclass-size ] [ "slots" word-prop length ] bi + ]
[ superclasses dup length 1- ] tri
<tuple-layout> ;
@ -211,8 +207,9 @@ M: tuple-class update-class
} cleave ;
: define-new-tuple-class ( class superclass slots -- )
make-slots
[ drop f f tuple-class define-class ]
[ nip "slot-names" set-word-prop ]
[ nip "slots" set-word-prop ]
[ 2drop update-classes ]
3tri ;
@ -236,7 +233,7 @@ M: tuple-class update-class
3bi ;
: tuple-class-unchanged? ( class superclass slots -- ? )
rot tuck [ superclass = ] [ slot-names = ] 2bi* and ;
rot tuck [ superclass = ] [ "slots" word-prop = ] 2bi* and ;
: valid-superclass? ( class -- ? )
[ tuple-class? ] [ tuple eq? ] bi or ;
@ -281,7 +278,7 @@ M: tuple-class reset-class
[ call-next-method ]
[
{
"layout" "slots" "slot-names" "boa-check" "prototype"
"layout" "slots" "boa-check" "prototype"
} reset-props
] bi
] bi ;

View File

@ -212,6 +212,12 @@ M: not-a-tuple summary
M: bad-superclass summary
drop "Tuple classes can only inherit from other tuple classes" ;
M: no-initial-value summary
drop "Initial value must be provided for slots specialized to this class" ;
M: bad-initial-value summary
drop "Incompatible initial value" ;
M: no-cond summary
drop "Fall-through in cond" ;

View File

@ -277,13 +277,32 @@ M: array pprint-slot-name
f <inset unclip text pprint-elements block>
\ } pprint-word block> ;
: unparse-slot ( slot-spec -- array )
[
dup name>> ,
dup class>> object eq? [
dup class>> ,
initial: ,
dup initial>> ,
] unless
dup read-only>> [
read-only ,
] when
drop
] { } make ;
: pprint-slot ( slot-spec -- )
unparse-slot
dup length 1 = [ first ] when
pprint-slot-name ;
M: tuple-class see-class*
<colon \ TUPLE: pprint-word
dup pprint-word
dup superclass tuple eq? [
"<" text dup superclass pprint-word
] unless
<block slot-names [ pprint-slot-name ] each block>
<block "slots" word-prop [ pprint-slot ] each block>
pprint-; block> ;
M: word see-class* drop ;

View File

@ -188,9 +188,14 @@ M: array make-slot
[ dup empty? not ] [ peel-off-attributes ] [ ] while drop
check-initial-value ;
: make-slots ( slots base -- specs )
over length [ + ] with map
[ [ make-slot ] dip >>offset ] 2map ;
M: slot-spec make-slot
check-initial-value ;
: make-slots ( slots -- specs )
[ make-slot ] map ;
: finalize-slots ( specs base -- specs )
over length [ + ] with map [ >>offset ] 2map ;
: slot-named ( name specs -- spec/f )
[ slot-spec-name = ] with find nip ;
[ name>> = ] with find nip ;

View File

@ -140,8 +140,6 @@ $nl
{ { $snippet "\"constructor\"" } { $link "tuple-constructors" } }
{ { $snippet "\"slot-names\"" } { $link "tuples" } }
{ { $snippet "\"type\"" } { $link "builtin-classes" } }
{ { { $snippet "\"superclass\"" } ", " { $snippet "\"predicate-definition\"" } } { $link "predicates" } }