Working on call-next-method, and identity-tuple

db4
Slava Pestov 2008-04-02 21:27:49 -05:00
parent 93ebbfb7e4
commit 5346e1899f
43 changed files with 279 additions and 195 deletions

View File

@ -16,12 +16,6 @@ IN: bootstrap.compiler
"cpu." cpu append require "cpu." cpu append require
: enable-compiler ( -- )
[ optimized-recompile-hook ] recompile-hook set-global ;
: disable-compiler ( -- )
[ default-recompile-hook ] recompile-hook set-global ;
enable-compiler enable-compiler
nl nl

View File

@ -444,7 +444,6 @@ PRIVATE>
"resource:/core/bootstrap/stage1.factor" run-file "resource:/core/bootstrap/stage1.factor" run-file
build-image build-image
write-image write-image
\ word-props target-word
] with-scope ; ] with-scope ;
: make-images ( -- ) : make-images ( -- )

View File

@ -159,17 +159,24 @@ num-types get f <array> builtins set
"tuple-layout" "classes.tuple.private" create register-builtin "tuple-layout" "classes.tuple.private" create register-builtin
! Catch-all class for providing a default method. ! Catch-all class for providing a default method.
"object" "kernel" create [ drop t ] "predicate" set-word-prop
"object" "kernel" create "object" "kernel" create
f builtins get [ ] subset union-class define-class [ f builtins get [ ] subset union-class define-class ]
[ [ drop t ] "predicate" set-word-prop ]
bi
"object?" "kernel" vocab-words delete-at
! Class of objects with object tag ! Class of objects with object tag
"hi-tag" "kernel.private" create "hi-tag" "kernel.private" create
f builtins get num-tags get tail union-class define-class builtins get num-tags get tail define-union-class
! Empty class with no instances ! Empty class with no instances
"null" "kernel" create [ drop f ] "predicate" set-word-prop "null" "kernel" create
"null" "kernel" create f { } union-class define-class [ f { } union-class define-class ]
[ [ drop f ] "predicate" set-word-prop ]
bi
"null?" "kernel" vocab-words delete-at
"fixnum" "math" create { } define-builtin "fixnum" "math" create { } define-builtin
"fixnum" "math" create ">fixnum" "math" create 1quotation "coercer" set-word-prop "fixnum" "math" create ">fixnum" "math" create 1quotation "coercer" set-word-prop
@ -378,17 +385,9 @@ define-builtin
] ]
} cleave } cleave
! Define general-t type, which is any object that is not f.
"general-t" "kernel" create
f "f" "syntax" lookup builtins get remove [ ] subset union-class
define-class
"f" "syntax" create [ not ] "predicate" set-word-prop "f" "syntax" create [ not ] "predicate" set-word-prop
"f?" "syntax" vocab-words delete-at "f?" "syntax" vocab-words delete-at
"general-t" "kernel" create [ ] "predicate" set-word-prop
"general-t?" "kernel" vocab-words delete-at
! Create special tombstone values ! Create special tombstone values
"tombstone" "hashtables.private" create "tombstone" "hashtables.private" create
"tuple" "kernel" lookup "tuple" "kernel" lookup

View File

@ -66,6 +66,7 @@ IN: bootstrap.syntax
"CS{" "CS{"
"<<" "<<"
">>" ">>"
"call-next-method"
} [ "syntax" create drop ] each } [ "syntax" create drop ] each
"t" "syntax" lookup define-symbol "t" "syntax" lookup define-symbol

View File

@ -23,8 +23,8 @@ random inference effects kernel.private ;
[ t ] [ number object number class-and* ] unit-test [ t ] [ number object number class-and* ] unit-test
[ t ] [ object number number class-and* ] unit-test [ t ] [ object number number class-and* ] unit-test
[ t ] [ slice reversed null class-and* ] unit-test [ t ] [ slice reversed null class-and* ] unit-test
[ t ] [ general-t \ f null class-and* ] unit-test [ t ] [ \ f class-not \ f null class-and* ] unit-test
[ t ] [ general-t \ f object class-or* ] unit-test [ t ] [ \ f class-not \ f object class-or* ] unit-test
TUPLE: first-one ; TUPLE: first-one ;
TUPLE: second-one ; TUPLE: second-one ;

View File

@ -21,7 +21,6 @@ $nl
{ { $link f } { $snippet "[ not ]" } { "The conventional name for a word which outputs true when given false is " { $link not } "; " { $snippet "f?" } " would be confusing." } } { { $link f } { $snippet "[ not ]" } { "The conventional name for a word which outputs true when given false is " { $link not } "; " { $snippet "f?" } " would be confusing." } }
{ { $link object } { $snippet "[ drop t ]" } { "All objects are instances of " { $link object } } } { { $link object } { $snippet "[ drop t ]" } { "All objects are instances of " { $link object } } }
{ { $link null } { $snippet "[ drop f ]" } { "No object is an instance of " { $link null } } } { { $link null } { $snippet "[ drop f ]" } { "No object is an instance of " { $link null } } }
{ { $link general-t } { $snippet "[ ]" } { "All objects with a true value are instances of " { $link general-t } } }
} }
"The set of class predicate words is a class:" "The set of class predicate words is a class:"
{ $subsection predicate } { $subsection predicate }

View File

@ -3,7 +3,7 @@ kernel math namespaces parser prettyprint sequences strings
tools.test vectors words quotations classes tools.test vectors words quotations classes
classes.private classes.union classes.mixin classes.predicate classes.private classes.union classes.mixin classes.predicate
classes.algebra vectors definitions source-files classes.algebra vectors definitions source-files
compiler.units ; compiler.units kernel.private ;
IN: classes.tests IN: classes.tests
! DEFER: bah ! DEFER: bah
@ -153,3 +153,10 @@ TUPLE: flat-mx-2-1 ; INSTANCE: flat-mx-2-1 flat-mx-2
! Test generic see and parsing ! Test generic see and parsing
[ "USING: alien math ;\nIN: classes.tests\nUNION: bah fixnum alien ;\n" ] [ "USING: alien math ;\nIN: classes.tests\nUNION: bah fixnum alien ;\n" ]
[ [ \ bah see ] with-string-writer ] unit-test [ [ \ bah see ] with-string-writer ] unit-test
[ t ] [ 3 object instance? ] unit-test
[ t ] [ 3 fixnum instance? ] unit-test
[ f ] [ 3 float instance? ] unit-test
[ t ] [ 3 number instance? ] unit-test
[ f ] [ 3 null instance? ] unit-test
[ t ] [ "hi" \ hi-tag instance? ] unit-test

View File

@ -60,7 +60,7 @@ PREDICATE: predicate < word "predicating" word-prop >boolean ;
dup class? [ "superclass" word-prop ] [ drop f ] if ; dup class? [ "superclass" word-prop ] [ drop f ] if ;
: superclasses ( class -- supers ) : superclasses ( class -- supers )
[ dup ] [ [ superclass ] keep ] [ ] unfold nip reverse ; [ superclass ] follow reverse ;
: members ( class -- seq ) : members ( class -- seq )
#! Output f for non-classes to work with algebra code #! Output f for non-classes to work with algebra code
@ -133,3 +133,6 @@ GENERIC: class ( object -- class )
M: hi-tag class hi-tag type>class ; M: hi-tag class hi-tag type>class ;
M: object class tag type>class ; M: object class tag type>class ;
: instance? ( obj class -- ? )
"predicate" word-prop call ;

View File

@ -153,14 +153,6 @@ HELP: tuple=
{ $description "Low-level tuple equality test. User code should use " { $link = } " instead." } { $description "Low-level tuple equality test. User code should use " { $link = } " instead." }
{ $warning "This word is in the " { $vocab-link "classes.tuple.private" } " vocabulary because it does not do any type checking. Passing values which are not tuples can result in memory corruption." } ; { $warning "This word is in the " { $vocab-link "classes.tuple.private" } " vocabulary because it does not do any type checking. Passing values which are not tuples can result in memory corruption." } ;
HELP: removed-slots
{ $values { "class" tuple-class } { "newslots" "a sequence of strings" } { "seq" "a sequence of strings" } }
{ $description "Outputs the sequence of existing tuple slot names not in " { $snippet "newslots" } "." } ;
HELP: forget-removed-slots
{ $values { "class" tuple-class } { "slots" "a sequence of strings" } }
{ $description "Forgets accessor words for existing tuple slots which are not in " { $snippet "newslots" } "." } ;
HELP: tuple HELP: tuple
{ $class-description "The class of tuples. This class is further partitioned into disjoint subclasses; each tuple shape defined by " { $link POSTPONE: TUPLE: } " is a new class." { $class-description "The class of tuples. This class is further partitioned into disjoint subclasses; each tuple shape defined by " { $link POSTPONE: TUPLE: } " is a new class."
$nl $nl

View File

@ -511,3 +511,34 @@ USE: vocabs
define-tuple-class define-tuple-class
] with-compilation-unit ] with-compilation-unit
] unit-test ] unit-test
[ "USE: words T{ word }" eval ] [ [ no-method? ] is? ] must-fail-with
! Accessors not being forgotten...
[ [ ] ] [
"IN: classes.tuple.tests TUPLE: forget-accessors-test x y z ;"
<string-reader>
"forget-accessors-test" parse-stream
] unit-test
[ t ] [ "forget-accessors-test" "classes.tuple.tests" lookup class? ] unit-test
: accessor-exists? ( class name -- ? )
>r "forget-accessors-test" "classes.tuple.tests" lookup r>
">>" append "accessors" lookup method >boolean ;
[ t ] [ "x" accessor-exists? ] unit-test
[ t ] [ "y" accessor-exists? ] unit-test
[ t ] [ "z" accessor-exists? ] unit-test
[ [ ] ] [
"IN: classes.tuple.tests GENERIC: forget-accessors-test"
<string-reader>
"forget-accessors-test" parse-stream
] unit-test
[ f ] [ "forget-accessors-test" "classes.tuple.tests" lookup class? ] unit-test
[ f ] [ "x" accessor-exists? ] unit-test
[ f ] [ "y" accessor-exists? ] unit-test
[ f ] [ "z" accessor-exists? ] unit-test

View File

@ -19,7 +19,7 @@ ERROR: no-tuple-class class ;
GENERIC: tuple-layout ( object -- layout ) GENERIC: tuple-layout ( object -- layout )
M: class tuple-layout "layout" word-prop ; M: tuple-class tuple-layout "layout" word-prop ;
M: tuple tuple-layout 1 slot ; M: tuple tuple-layout 1 slot ;
@ -40,7 +40,9 @@ PRIVATE>
[ drop ] [ no-tuple-class ] if ; [ drop ] [ no-tuple-class ] if ;
: tuple>array ( tuple -- array ) : tuple>array ( tuple -- array )
prepare-tuple>array >r copy-tuple-slots r> layout-class prefix ; prepare-tuple>array
>r copy-tuple-slots r>
layout-class prefix ;
: tuple-slots ( tuple -- array ) : tuple-slots ( tuple -- array )
prepare-tuple>array drop copy-tuple-slots ; prepare-tuple>array drop copy-tuple-slots ;
@ -120,15 +122,6 @@ PRIVATE>
: define-tuple-layout ( class -- ) : define-tuple-layout ( class -- )
dup make-tuple-layout "layout" set-word-prop ; dup make-tuple-layout "layout" set-word-prop ;
: removed-slots ( class newslots -- seq )
swap slot-names seq-diff ;
: forget-removed-slots ( class slots -- )
dupd removed-slots [
[ reader-word forget-method ]
[ writer-word forget-method ] 2bi
] with each ;
: all-slot-names ( class -- slots ) : all-slot-names ( class -- slots )
superclasses [ slot-names ] map concat \ class prefix ; superclasses [ slot-names ] map concat \ class prefix ;
@ -189,9 +182,8 @@ M: tuple-class update-class
tri tri
] each-subclass ] each-subclass
] ]
[ nip forget-removed-slots ]
[ define-new-tuple-class ] [ define-new-tuple-class ]
3tri ; 3bi ;
: tuple-class-unchanged? ( class superclass slots -- ? ) : tuple-class-unchanged? ( class superclass slots -- ? )
rot tuck [ superclass = ] [ slot-names = ] 2bi* and ; rot tuck [ superclass = ] [ slot-names = ] 2bi* and ;
@ -213,7 +205,19 @@ M: tuple-class define-tuple-class
dup [ construct-boa throw ] curry define ; dup [ construct-boa throw ] curry define ;
M: tuple-class reset-class M: tuple-class reset-class
{ "metaclass" "superclass" "slots" "layout" } reset-props ; [
dup "slot-names" word-prop [
[ reader-word forget-method ]
[ writer-word forget-method ] 2bi
] with each
] [
{
"metaclass"
"superclass"
"layout"
"slots"
} reset-props
] bi ;
M: tuple clone M: tuple clone
(clone) dup delegate clone over set-delegate ; (clone) dup delegate clone over set-delegate ;
@ -228,12 +232,6 @@ M: tuple hashcode*
] 2curry reduce ] 2curry reduce
] recursive-hashcode ; ] recursive-hashcode ;
M: object construct-empty ( class -- tuple )
tuple-layout <tuple> ;
M: object construct-boa ( ... class -- tuple )
tuple-layout <tuple-boa> ;
! Deprecated ! Deprecated
M: object get-slots ( obj slots -- ... ) M: object get-slots ( obj slots -- ... )
[ execute ] with each ; [ execute ] with each ;
@ -241,10 +239,6 @@ M: object get-slots ( obj slots -- ... )
M: object set-slots ( ... obj slots -- ) M: object set-slots ( ... obj slots -- )
<reversed> get-slots ; <reversed> get-slots ;
M: object construct ( ... slots class -- tuple ) : delegates ( obj -- seq ) [ delegate ] follow ;
construct-empty [ swap set-slots ] keep ;
: delegates ( obj -- seq )
[ dup ] [ [ delegate ] keep ] [ ] unfold nip ;
: is? ( obj quot -- ? ) >r delegates r> contains? ; inline : is? ( obj quot -- ? ) >r delegates r> contains? ; inline

View File

@ -2,14 +2,21 @@ USING: generator help.markup help.syntax words io parser
assocs words.private sequences compiler.units ; assocs words.private sequences compiler.units ;
IN: compiler IN: compiler
HELP: enable-compiler
{ $description "Enables the optimizing compiler." } ;
HELP: disable-compiler
{ $description "Enables the optimizing compiler." } ;
ARTICLE: "compiler-usage" "Calling the optimizing compiler" ARTICLE: "compiler-usage" "Calling the optimizing compiler"
"Normally, new word definitions are recompiled automatically, however in some circumstances the optimizing compiler may need to be called directly." "Normally, new word definitions are recompiled automatically. This can be changed:"
$nl { $subsection disable-compiler }
"The main entry point to the optimizing compiler:" { $subsection enable-compiler }
"The optimizing compiler can be called directly, although this should not be necessary under normal circumstances:"
{ $subsection optimized-recompile-hook } { $subsection optimized-recompile-hook }
"Removing a word's optimized definition:" "Removing a word's optimized definition:"
{ $subsection decompile } { $subsection decompile }
"These words are not usually used directly. Instead, use " { $link "compilation-units" } "." ; "Higher-level words can be found in " { $link "compilation-units" } "." ;
ARTICLE: "compiler" "Optimizing compiler" ARTICLE: "compiler" "Optimizing compiler"
"Factor is a fully compiled language implementation with two distinct compilers:" "Factor is a fully compiled language implementation with two distinct compilers:"

View File

@ -56,5 +56,11 @@ IN: compiler
compiled get >alist compiled get >alist
] with-scope ; ] with-scope ;
: enable-compiler ( -- )
[ optimized-recompile-hook ] recompile-hook set-global ;
: disable-compiler ( -- )
[ default-recompile-hook ] recompile-hook set-global ;
: recompile-all ( -- ) : recompile-all ( -- )
forget-errors all-words compile ; forget-errors all-words compile ;

View File

@ -4,7 +4,7 @@ compiler.units words ;
TUPLE: combination-1 ; TUPLE: combination-1 ;
M: combination-1 perform-combination 2drop [ ] ; M: combination-1 perform-combination drop [ ] define ;
M: combination-1 make-default-method 2drop [ "No method" throw ] ; M: combination-1 make-default-method 2drop [ "No method" throw ] ;

View File

@ -21,19 +21,6 @@ M: word class-of drop "word" ;
[ "Hello world" ] [ 4 foobar foobar ] unit-test [ "Hello world" ] [ 4 foobar foobar ] unit-test
[ "Goodbye cruel world" ] [ 4 foobar ] unit-test [ "Goodbye cruel world" ] [ 4 foobar ] unit-test
GENERIC: bool>str ( x -- y )
M: general-t bool>str drop "true" ;
M: f bool>str drop "false" ;
: str>bool
H{
{ "true" t }
{ "false" f }
} at ;
[ t ] [ t bool>str str>bool ] unit-test
[ f ] [ f bool>str str>bool ] unit-test
! Testing unions ! Testing unions
UNION: funnies quotation float complex ; UNION: funnies quotation float complex ;
@ -51,16 +38,6 @@ M: very-funny gooey sq ;
[ 0.25 ] [ 0.5 gooey ] unit-test [ 0.25 ] [ 0.5 gooey ] unit-test
DEFER: complement-test
FORGET: complement-test
GENERIC: complement-test ( x -- y )
M: f complement-test drop "f" ;
M: general-t complement-test drop "general-t" ;
[ "general-t" ] [ 5 complement-test ] unit-test
[ "f" ] [ f complement-test ] unit-test
GENERIC: empty-method-test ( x -- y ) GENERIC: empty-method-test ( x -- y )
M: object empty-method-test ; M: object empty-method-test ;
TUPLE: for-arguments-sake ; TUPLE: for-arguments-sake ;

View File

@ -6,16 +6,7 @@ classes.algebra quotations arrays vocabs effects ;
IN: generic IN: generic
! Method combination protocol ! Method combination protocol
GENERIC: perform-combination ( word combination -- quot ) GENERIC: perform-combination ( word combination -- )
M: object perform-combination
#! We delay the invalid method combination error for a
#! reason. If we call forget-vocab on a vocabulary which
#! defines a method combination, a generic using this
#! method combination, and a method on the generic, and the
#! method combination is forgotten first, then forgetting
#! the method will throw an error. We don't want that.
nip [ "Invalid method combination" throw ] curry [ ] like ;
GENERIC: make-default-method ( generic combination -- method ) GENERIC: make-default-method ( generic combination -- method )
@ -38,6 +29,18 @@ PREDICATE: method-spec < pair
: order ( generic -- seq ) : order ( generic -- seq )
"methods" word-prop keys sort-classes ; "methods" word-prop keys sort-classes ;
: next-method-class ( class generic -- class/f )
order [ class< ] with subset reverse dup length 1 =
[ drop f ] [ second ] if ;
: next-method ( class generic -- class/f )
[ next-method-class ] keep method ;
GENERIC: next-method-quot ( class generic -- quot )
: (call-next-method) ( class generic -- )
next-method-quot call ;
TUPLE: check-method class generic ; TUPLE: check-method class generic ;
: check-method ( class generic -- class generic ) : check-method ( class generic -- class generic )

View File

@ -12,9 +12,9 @@ PREDICATE: math-class < class
number bootstrap-word class< number bootstrap-word class<
] if ; ] if ;
: last/first ( seq -- pair ) dup peek swap first 2array ; : last/first ( seq -- pair ) [ peek ] [ first ] bi 2array ;
: math-precedence ( class -- n ) : math-precedence ( class -- pair )
{ {
{ [ dup null class< ] [ drop { -1 -1 } ] } { [ dup null class< ] [ drop { -1 -1 } ] }
{ [ dup math-class? ] [ class-types last/first ] } { [ dup math-class? ] [ class-types last/first ] }

View File

@ -15,7 +15,7 @@ C: <trivial-tuple-dispatch-engine> trivial-tuple-dispatch-engine
TUPLE: tuple-dispatch-engine echelons ; TUPLE: tuple-dispatch-engine echelons ;
: push-echelon ( class method assoc -- ) : push-echelon ( class method assoc -- )
>r swap dup tuple-layout layout-echelon r> >r swap dup "layout" word-prop layout-echelon r>
[ ?set-at ] change-at ; [ ?set-at ] change-at ;
: echelon-sort ( assoc -- assoc' ) : echelon-sort ( assoc -- assoc' )

View File

@ -8,6 +8,10 @@ generic.standard.engines.tag generic.standard.engines.predicate
generic.standard.engines.tuple accessors ; generic.standard.engines.tuple accessors ;
IN: generic.standard IN: generic.standard
GENERIC: dispatch# ( word -- n )
M: word dispatch# "combination" word-prop dispatch# ;
: unpickers : unpickers
{ {
[ nip ] [ nip ]
@ -101,7 +105,7 @@ PREDICATE: simple-generic < standard-generic
T{ standard-combination f 0 } define-generic ; T{ standard-combination f 0 } define-generic ;
: with-standard ( combination quot -- quot' ) : with-standard ( combination quot -- quot' )
>r #>> (dispatch#) r> with-variable ; >r #>> (dispatch#) r> with-variable ; inline
M: standard-generic mangle-method M: standard-generic mangle-method
drop 1quotation ; drop 1quotation ;
@ -112,6 +116,27 @@ M: standard-combination make-default-method
M: standard-combination perform-combination M: standard-combination perform-combination
[ drop ] [ [ single-combination ] with-standard ] 2bi define ; [ drop ] [ [ single-combination ] with-standard ] 2bi define ;
M: standard-combination dispatch# #>> ;
ERROR: inconsistent-next-method object class generic ;
ERROR: no-next-method class generic ;
M: standard-generic next-method-quot
[
[
[ [ instance? ] curry ]
[ dispatch# (picker) ] bi* prepend %
]
[
2dup next-method
[ 2nip 1quotation ]
[ [ no-next-method ] 2curry ] if* ,
]
[ [ inconsistent-next-method ] 2curry , ]
2tri
] [ ] make ;
TUPLE: hook-combination var ; TUPLE: hook-combination var ;
C: <hook-combination> hook-combination C: <hook-combination> hook-combination
@ -124,6 +149,8 @@ PREDICATE: hook-generic < generic
dip var>> [ get ] curry prepend dip var>> [ get ] curry prepend
] with-variable ; inline ] with-variable ; inline
M: hook-combination dispatch# drop 0 ;
M: hook-generic mangle-method M: hook-generic mangle-method
drop 1quotation [ drop ] prepend ; drop 1quotation [ drop ] prepend ;
@ -133,14 +160,6 @@ M: hook-combination make-default-method
M: hook-combination perform-combination M: hook-combination perform-combination
[ drop ] [ [ single-combination ] with-hook ] 2bi define ; [ drop ] [ [ single-combination ] with-hook ] 2bi define ;
GENERIC: dispatch# ( word -- n )
M: word dispatch# "combination" word-prop dispatch# ;
M: standard-combination dispatch# #>> ;
M: hook-combination dispatch# drop 0 ;
M: simple-generic definer drop \ GENERIC: f ; M: simple-generic definer drop \ GENERIC: f ;
M: standard-generic definer drop \ GENERIC# f ; M: standard-generic definer drop \ GENERIC# f ;

View File

@ -21,7 +21,7 @@ GENERIC: mynot ( x -- y )
M: f mynot drop t ; M: f mynot drop t ;
M: general-t mynot drop f ; M: object mynot drop f ;
GENERIC: detect-f ( x -- y ) GENERIC: detect-f ( x -- y )
@ -297,3 +297,15 @@ cell-bits 32 = [
[ t ] [ [ t ] [
[ { vector } declare nth-unsafe ] \ nth-unsafe inlined? [ { vector } declare nth-unsafe ] \ nth-unsafe inlined?
] unit-test ] unit-test
[ t ] [
[
dup integer? [
dup fixnum? [
1 +
] [
2 +
] if
] when
] \ + inlined?
] unit-test

View File

@ -176,9 +176,18 @@ M: pair constraint-satisfied?
: predicate-constraints ( class #call -- ) : predicate-constraints ( class #call -- )
[ [
0 `input class, ! If word outputs true, input is an instance of class
general-t 0 `output class, [
] set-constraints ; 0 `input class,
\ f class-not 0 `output class,
] set-constraints
] [
! If word outputs false, input is not an instance of class
[
class-not 0 `input class,
\ f 0 `output class,
] set-constraints
] 2bi ;
: compute-constraints ( #call -- ) : compute-constraints ( #call -- )
dup node-param "constraints" word-prop [ dup node-param "constraints" word-prop [
@ -209,7 +218,7 @@ M: #push infer-classes-before
M: #if child-constraints M: #if child-constraints
[ [
general-t 0 `input class, \ f class-not 0 `input class,
f 0 `input literal, f 0 `input literal,
] make-constraints ; ] make-constraints ;

View File

@ -9,15 +9,13 @@ IN: inference.dataflow
: <computed> \ <computed> counter ; : <computed> \ <computed> counter ;
! Literal value ! Literal value
TUPLE: value literal uid recursion ; TUPLE: value < identity-tuple literal uid recursion ;
: <value> ( obj -- value ) : <value> ( obj -- value )
<computed> recursive-state get value construct-boa ; <computed> recursive-state get value construct-boa ;
M: value hashcode* nip value-uid ; M: value hashcode* nip value-uid ;
M: value equal? 2drop f ;
! Result of curry ! Result of curry
TUPLE: curried obj quot ; TUPLE: curried obj quot ;
@ -30,13 +28,12 @@ C: <composed> composed
UNION: special curried composed ; UNION: special curried composed ;
TUPLE: node param TUPLE: node < identity-tuple
param
in-d out-d in-r out-r in-d out-d in-r out-r
classes literals intervals classes literals intervals
history successor children ; history successor children ;
M: node equal? 2drop f ;
M: node hashcode* drop node hashcode* ; M: node hashcode* drop node hashcode* ;
GENERIC: flatten-curry ( value -- ) GENERIC: flatten-curry ( value -- )

View File

@ -1,6 +1,7 @@
IN: inference.transforms.tests IN: inference.transforms.tests
USING: sequences inference.transforms tools.test math kernel USING: sequences inference.transforms tools.test math kernel
quotations inference accessors combinators words arrays ; quotations inference accessors combinators words arrays
classes ;
: compose-n-quot <repetition> >quotation ; : compose-n-quot <repetition> >quotation ;
: compose-n compose-n-quot call ; : compose-n compose-n-quot call ;
@ -56,3 +57,5 @@ C: <color> color
[ 16 -3 1/6 ] [ 4 3 6 spread-test ] unit-test [ 16 -3 1/6 ] [ 4 3 6 spread-test ] unit-test
[ 16 -3 1/6 ] [ 4 3 6 \ spread-test word-def call ] unit-test [ 16 -3 1/6 ] [ 4 3 6 \ spread-test word-def call ] unit-test
[ fixnum instance? ] must-infer

View File

@ -3,7 +3,7 @@
USING: arrays kernel words sequences generic math namespaces USING: arrays kernel words sequences generic math namespaces
quotations assocs combinators math.bitfields inference.backend quotations assocs combinators math.bitfields inference.backend
inference.dataflow inference.state classes.tuple.private effects inference.dataflow inference.state classes.tuple.private effects
inspector hashtables ; inspector hashtables classes generic ;
IN: inference.transforms IN: inference.transforms
: pop-literals ( n -- rstate seq ) : pop-literals ( n -- rstate seq )
@ -98,3 +98,11 @@ M: duplicated-slots-error summary
\ construct-empty 1 1 <effect> make-call-node \ construct-empty 1 1 <effect> make-call-node
] if ] if
] "infer" set-word-prop ] "infer" set-word-prop
\ instance? [
[ +inlined+ depends-on ] [ "predicate" word-prop ] bi
] 1 define-transform
\ (call-next-method) [
[ [ +inlined+ depends-on ] bi@ ] [ next-method-quot ] 2bi
] 2 define-transform

View File

@ -250,8 +250,9 @@ $nl
{ $subsection eq? } { $subsection eq? }
"Value comparison:" "Value comparison:"
{ $subsection = } { $subsection = }
"Generic words for custom value comparison methods:" "Custom value comparison methods:"
{ $subsection equal? } { $subsection equal? }
{ $subsection identity-tuple }
"Some types of objects also have an intrinsic order allowing sorting using " { $link natural-sort } ":" "Some types of objects also have an intrinsic order allowing sorting using " { $link natural-sort } ":"
{ $subsection <=> } { $subsection <=> }
{ $subsection compare } { $subsection compare }
@ -377,10 +378,13 @@ HELP: equal?
} }
$nl $nl
"If a class defines a custom equality comparison test, it should also define a compatible method for the " { $link hashcode* } " generic word." "If a class defines a custom equality comparison test, it should also define a compatible method for the " { $link hashcode* } " generic word."
} } ;
HELP: identity-tuple
{ $class-description "A class defining an " { $link equal? } " method which always returns f." }
{ $examples { $examples
"To define a tuple class such that two instances are only equal if they are both the same instance, we can add a method to " { $link equal? } " which always returns " { $link f } ". Since " { $link = } " handles the case where the two objects are " { $link eq? } ", this method will never be called with two " { $link eq? } " objects, so such a definition is valid:" "To define a tuple class such that two instances are only equal if they are both the same instance, inherit from the " { $link identity-tuple } " class. This class defines a method on " { $link equal? } " which always returns " { $link f } ". Since " { $link = } " handles the case where the two objects are " { $link eq? } ", this method will never be called with two " { $link eq? } " objects, so such a definition is valid:"
{ $code "TUPLE: foo ;" "M: foo equal? 2drop f ;" } { $code "TUPLE: foo < identity-tuple ;" }
"By calling " { $link = } " on instances of " { $snippet "foo" } " we get the results we expect:" "By calling " { $link = } " on instances of " { $snippet "foo" } " we get the results we expect:"
{ $unchecked-example "T{ foo } dup = ." "t" } { $unchecked-example "T{ foo } dup = ." "t" }
{ $unchecked-example "T{ foo } dup clone = ." "f" } { $unchecked-example "T{ foo } dup clone = ." "f" }
@ -665,6 +669,11 @@ HELP: bi@
"[ p ] bi@" "[ p ] bi@"
">r p r> p" ">r p r> p"
} }
"The following two lines are also equivalent:"
{ $code
"[ p ] bi@"
"[ p ] [ p ] bi*"
}
} ; } ;
HELP: 2bi@ HELP: 2bi@
@ -676,6 +685,11 @@ HELP: 2bi@
"[ p ] 2bi@" "[ p ] 2bi@"
">r >r p r> r> p" ">r >r p r> r> p"
} }
"The following two lines are also equivalent:"
{ $code
"[ p ] 2bi@"
"[ p ] [ p ] 2bi*"
}
} ; } ;
HELP: tri@ HELP: tri@
@ -687,6 +701,11 @@ HELP: tri@
"[ p ] tri@" "[ p ] tri@"
">r >r p r> p r> p" ">r >r p r> p r> p"
} }
"The following two lines are also equivalent:"
{ $code
"[ p ] tri@"
"[ p ] [ p ] [ p ] tri*"
}
} ; } ;
HELP: if ( cond true false -- ) HELP: if ( cond true false -- )
@ -785,19 +804,6 @@ HELP: null
"The canonical empty class with no instances." "The canonical empty class with no instances."
} ; } ;
HELP: general-t
{ $class-description
"The class of all objects not equal to " { $link f } "."
}
{ $examples
"Here is an implementation of " { $link if } " using generic words:"
{ $code
"GENERIC# my-if 2 ( ? true false -- )"
"M: f my-if 2nip call ;"
"M: general-t my-if drop nip call ;"
}
} ;
HELP: most HELP: most
{ $values { "x" object } { "y" object } { "quot" "a quotation with stack effect " { $snippet "( x y -- ? )" } } { "z" "either " { $snippet "x" } " or " { $snippet "y" } } } { $values { "x" object } { "y" object } { "quot" "a quotation with stack effect " { $snippet "( x y -- ? )" } } { "z" "either " { $snippet "x" } " or " { $snippet "y" } } }
{ $description "If the quotation yields a true value when applied to " { $snippet "x" } " and " { $snippet "y" } ", outputs " { $snippet "x" } ", otherwise outputs " { $snippet "y" } "." } ; { $description "If the quotation yields a true value when applied to " { $snippet "x" } " and " { $snippet "y" } ", outputs " { $snippet "x" } ", otherwise outputs " { $snippet "y" } "." } ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2004, 2008 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel.private slots.private ; USING: kernel.private slots.private classes.tuple.private ;
IN: kernel IN: kernel
! Stack stuff ! Stack stuff
@ -114,12 +114,6 @@ DEFER: if
[ 2nip call ] if ; inline [ 2nip call ] if ; inline
! Object protocol ! Object protocol
GENERIC: delegate ( obj -- delegate )
M: object delegate drop f ;
GENERIC: set-delegate ( delegate tuple -- )
GENERIC: hashcode* ( depth obj -- code ) GENERIC: hashcode* ( depth obj -- code )
M: object hashcode* 2drop 0 ; M: object hashcode* 2drop 0 ;
@ -130,6 +124,10 @@ GENERIC: equal? ( obj1 obj2 -- ? )
M: object equal? 2drop f ; M: object equal? 2drop f ;
TUPLE: identity-tuple ;
M: identity-tuple equal? 2drop f ;
: = ( obj1 obj2 -- ? ) : = ( obj1 obj2 -- ? )
2dup eq? [ 2drop t ] [ equal? ] if ; inline 2dup eq? [ 2drop t ] [ equal? ] if ; inline
@ -142,18 +140,11 @@ M: object clone ;
M: callstack clone (clone) ; M: callstack clone (clone) ;
! Tuple construction ! Tuple construction
GENERIC# get-slots 1 ( tuple slots -- ... ) : construct-empty ( class -- tuple )
tuple-layout <tuple> ;
GENERIC# set-slots 1 ( ... tuple slots -- ) : construct-boa ( ... class -- tuple )
tuple-layout <tuple-boa> ;
GENERIC: construct-empty ( class -- tuple )
GENERIC: construct ( ... slots class -- tuple ) inline
GENERIC: construct-boa ( ... class -- tuple )
: construct-delegate ( delegate class -- tuple )
>r { set-delegate } r> construct ; inline
! Quotation building ! Quotation building
: 2curry ( obj1 obj2 quot -- curry ) : 2curry ( obj1 obj2 quot -- curry )
@ -201,3 +192,20 @@ GENERIC: construct-boa ( ... class -- tuple )
: do-primitive ( number -- ) "Improper primitive call" throw ; : do-primitive ( number -- ) "Improper primitive call" throw ;
PRIVATE> PRIVATE>
! Deprecated
GENERIC: delegate ( obj -- delegate )
M: object delegate drop f ;
GENERIC: set-delegate ( delegate tuple -- )
GENERIC# get-slots 1 ( tuple slots -- ... )
GENERIC# set-slots 1 ( ... tuple slots -- )
: construct ( ... slots class -- tuple )
construct-empty [ swap set-slots ] keep ; inline
: construct-delegate ( delegate class -- tuple )
>r { set-delegate } r> construct ; inline

View File

@ -154,7 +154,7 @@ SYMBOL: potential-loops
] [ ] [
node-class { node-class {
{ [ dup null class< ] [ drop f f ] } { [ dup null class< ] [ drop f f ] }
{ [ dup general-t class< ] [ drop t t ] } { [ dup \ f class-not class< ] [ drop t t ] }
{ [ dup \ f class< ] [ drop f t ] } { [ dup \ f class< ] [ drop f t ] }
{ [ t ] [ drop f f ] } { [ t ] [ drop f f ] }
} cond } cond

View File

@ -70,12 +70,20 @@ DEFER: (flat-length)
] if ; ] if ;
! Partial dispatch of math-generic words ! Partial dispatch of math-generic words
: normalize-math-class ( class -- class' )
{ fixnum bignum ratio float complex }
[ class< ] with find nip object or ;
: math-both-known? ( word left right -- ? ) : math-both-known? ( word left right -- ? )
math-class-max swap specific-method ; math-class-max swap specific-method ;
: inline-math-method ( #call word -- node ) : inline-math-method ( #call word -- node )
over node-input-classes first2 3dup math-both-known? over node-input-classes
[ math-method f splice-quot ] [ 2drop 2drop t ] if ; [ first normalize-math-class ]
[ second normalize-math-class ] bi
3dup math-both-known?
[ math-method f splice-quot ]
[ 2drop 2drop t ] if ;
: inline-method ( #call -- node ) : inline-method ( #call -- node )
dup node-param { dup node-param {

View File

@ -75,7 +75,7 @@ sequences.private combinators ;
dup node-in-d second dup value? [ dup node-in-d second dup value? [
swap [ swap [
value-literal 0 `input literal, value-literal 0 `input literal,
general-t 0 `output class, \ f class-not 0 `output class,
] set-constraints ] set-constraints
] [ ] [
2drop 2drop

View File

@ -269,7 +269,7 @@ generic.standard system ;
: comparison-constraints ( node true false -- ) : comparison-constraints ( node true false -- )
>r >r dup node set intervals dup [ >r >r dup node set intervals dup [
2dup 2dup
r> general-t (comparison-constraints) r> \ f class-not (comparison-constraints)
r> \ f (comparison-constraints) r> \ f (comparison-constraints)
] [ ] [
r> r> 2drop 2drop r> r> 2drop 2drop

View File

@ -365,7 +365,17 @@ ERROR: bad-number ;
: (:) CREATE-WORD parse-definition ; : (:) CREATE-WORD parse-definition ;
: (M:) CREATE-METHOD parse-definition ; SYMBOL: current-class
SYMBOL: current-generic
: (M:)
CREATE-METHOD
[
[ "method-class" word-prop current-class set ]
[ "method-generic" word-prop current-generic set ]
[ ] tri
parse-definition
] with-scope ;
: scan-object ( -- object ) : scan-object ( -- object )
scan-word dup parsing? scan-word dup parsing?

View File

@ -57,8 +57,6 @@ unit-test
[ ] [ \ integer see ] unit-test [ ] [ \ integer see ] unit-test
[ ] [ \ general-t see ] unit-test
[ ] [ \ generic see ] unit-test [ ] [ \ generic see ] unit-test
[ ] [ \ duplex-stream see ] unit-test [ ] [ \ duplex-stream see ] unit-test

View File

@ -416,6 +416,9 @@ PRIVATE>
swap >r [ push ] curry compose r> while swap >r [ push ] curry compose r> while
] keep { } like ; inline ] keep { } like ; inline
: follow ( obj quot -- seq )
>r [ dup ] r> [ keep ] curry [ ] unfold nip ; inline
: index ( obj seq -- n ) : index ( obj seq -- n )
[ = ] with find drop ; [ = ] with find drop ;

View File

@ -243,7 +243,7 @@ HELP: flushable
HELP: t HELP: t
{ $syntax "t" } { $syntax "t" }
{ $values { "t" "the canonical truth value" } } { $values { "t" "the canonical truth value" } }
{ $description "The canonical instance of " { $link general-t } ". It is just a symbol." } ; { $class-description "The canonical truth value, which is an instance of itself." } ;
HELP: f HELP: f
{ $syntax "f" } { $syntax "f" }

View File

@ -185,4 +185,10 @@ IN: bootstrap.syntax
[ \ >> parse-until >quotation ] with-compilation-unit [ \ >> parse-until >quotation ] with-compilation-unit
call call
] define-syntax ] define-syntax
"call-next-method" [
current-class get literalize parsed
current-generic get literalize parsed
\ (call-next-method) parsed
] define-syntax
] with-compilation-unit ] with-compilation-unit

View File

@ -6,13 +6,11 @@ IN: vocabs
SYMBOL: dictionary SYMBOL: dictionary
TUPLE: vocab TUPLE: vocab < identity-tuple
name words name words
main help main help
source-loaded? docs-loaded? ; source-loaded? docs-loaded? ;
M: vocab equal? 2drop f ;
: <vocab> ( name -- vocab ) : <vocab> ( name -- vocab )
H{ } clone H{ } clone
{ set-vocab-name set-vocab-words } { set-vocab-name set-vocab-words }
@ -92,10 +90,6 @@ TUPLE: vocab-link name ;
: <vocab-link> ( name -- vocab-link ) : <vocab-link> ( name -- vocab-link )
vocab-link construct-boa ; vocab-link construct-boa ;
M: vocab-link equal?
over vocab-link?
[ [ vocab-link-name ] bi@ = ] [ 2drop f ] if ;
M: vocab-link hashcode* M: vocab-link hashcode*
vocab-link-name hashcode* ; vocab-link-name hashcode* ;

View File

@ -173,7 +173,7 @@ GENERIC: subwords ( word -- seq )
M: word subwords drop f ; M: word subwords drop f ;
: reset-generic ( word -- ) : reset-generic ( word -- )
dup subwords [ forget ] each dup subwords forget-all
dup reset-word dup reset-word
{ "methods" "combination" "default-method" } reset-props ; { "methods" "combination" "default-method" } reset-props ;

View File

@ -6,7 +6,7 @@ init threads continuations math io.encodings io.streams.duplex
io.nonblocking accessors ; io.nonblocking accessors ;
IN: io.launcher IN: io.launcher
TUPLE: process TUPLE: process < identity-tuple
command command
detached detached
@ -65,8 +65,6 @@ M: object register-process drop ;
V{ } clone over processes get set-at V{ } clone over processes get set-at
register-process ; register-process ;
M: process equal? 2drop f ;
M: process hashcode* process-handle hashcode* ; M: process hashcode* process-handle hashcode* ;
: pass-environment? ( process -- ? ) : pass-environment? ( process -- ? )

View File

@ -96,14 +96,13 @@ M: inet6 parse-sockaddr
M: f parse-sockaddr nip ; M: f parse-sockaddr nip ;
: addrinfo>addrspec ( addrinfo -- addrspec ) : addrinfo>addrspec ( addrinfo -- addrspec )
dup addrinfo-addr [ addrinfo-addr ] [ addrinfo-family addrspec-of-family ] bi
swap addrinfo-family addrspec-of-family
parse-sockaddr ; parse-sockaddr ;
: parse-addrinfo-list ( addrinfo -- seq ) : parse-addrinfo-list ( addrinfo -- seq )
[ dup ] [ addrinfo-next ] follow
[ dup addrinfo-next swap addrinfo>addrspec ] [ addrinfo>addrspec ] map
[ ] unfold nip [ ] subset ; [ ] subset ;
: prepare-resolve-host ( host serv passive? -- host' serv' flags ) : prepare-resolve-host ( host serv passive? -- host' serv' flags )
#! If the port is a number, we resolve for 'http' then #! If the port is a number, we resolve for 'http' then

View File

@ -4,13 +4,12 @@ USING: generic kernel math sequences arrays assocs alarms
calendar ; calendar ;
IN: models IN: models
TUPLE: model value connections dependencies ref locked? ; TUPLE: model < identity-tuple
value connections dependencies ref locked? ;
: <model> ( value -- model ) : <model> ( value -- model )
V{ } clone V{ } clone 0 f model construct-boa ; V{ } clone V{ } clone 0 f model construct-boa ;
M: model equal? 2drop f ;
M: model hashcode* drop model hashcode* ; M: model hashcode* drop model hashcode* ;
: add-dependency ( dep model -- ) : add-dependency ( dep model -- )

View File

@ -27,9 +27,8 @@ DEFER: freetype
\ freetype get-global expired? [ init-freetype ] when \ freetype get-global expired? [ init-freetype ] when
\ freetype get-global ; \ freetype get-global ;
TUPLE: font ascent descent height handle widths ; TUPLE: font < identity-tuple
ascent descent height handle widths ;
M: font equal? 2drop f ;
M: font hashcode* drop font hashcode* ; M: font hashcode* drop font hashcode* ;

View File

@ -44,14 +44,12 @@ M: array rect-dim drop { 0 0 } ;
: rect-union ( rect1 rect2 -- newrect ) : rect-union ( rect1 rect2 -- newrect )
(rect-union) <extent-rect> ; (rect-union) <extent-rect> ;
TUPLE: gadget TUPLE: gadget < identity-tuple
pref-dim parent children orientation focus pref-dim parent children orientation focus
visible? root? clipped? layout-state graft-state graft-node visible? root? clipped? layout-state graft-state graft-node
interior boundary interior boundary
model ; model ;
M: gadget equal? 2drop f ;
M: gadget hashcode* drop gadget hashcode* ; M: gadget hashcode* drop gadget hashcode* ;
M: gadget model-changed 2drop ; M: gadget model-changed 2drop ;
@ -354,7 +352,7 @@ SYMBOL: in-layout?
swap [ over (add-gadget) ] each relayout ; swap [ over (add-gadget) ] each relayout ;
: parents ( gadget -- seq ) : parents ( gadget -- seq )
[ dup ] [ [ gadget-parent ] keep ] [ ] unfold nip ; [ gadget-parent ] follow ;
: each-parent ( gadget quot -- ? ) : each-parent ( gadget quot -- ? )
>r parents r> all? ; inline >r parents r> all? ; inline
@ -401,7 +399,7 @@ M: f request-focus-on 2drop ;
dup focusable-child swap request-focus-on ; dup focusable-child swap request-focus-on ;
: focus-path ( world -- seq ) : focus-path ( world -- seq )
[ dup ] [ [ gadget-focus ] keep ] [ ] unfold nip ; [ gadget-parent ] follow ;
: make-gadget ( quot gadget -- gadget ) : make-gadget ( quot gadget -- gadget )
[ \ make-gadget rot with-variable ] keep ; inline [ \ make-gadget rot with-variable ] keep ; inline

View File

@ -5,7 +5,7 @@ namespaces opengl sequences io combinators math.vectors
ui.gadgets ui.gestures ui.render ui.backend inspector ; ui.gadgets ui.gestures ui.render ui.backend inspector ;
IN: ui.gadgets.worlds IN: ui.gadgets.worlds
TUPLE: world TUPLE: world < identity-tuple
active? focused? active? focused?
glass glass
title status title status
@ -46,8 +46,6 @@ M: world request-focus-on ( child gadget -- )
t over set-gadget-root? t over set-gadget-root?
dup request-focus ; dup request-focus ;
M: world equal? 2drop f ;
M: world hashcode* drop world hashcode* ; M: world hashcode* drop world hashcode* ;
M: world pref-dim* M: world pref-dim*