type check optimization is here
parent
80b4d13a54
commit
6159c82407
|
@ -5,13 +5,8 @@
|
|||
[error] AWT-EventQueue-0: at factor.jedit.WordPreview.actionPerformed(WordPreview.java:79)
|
||||
[error] AWT-EventQueue-0: at javax.swing.Timer.fireActionPerformed(Timer.java:271)
|
||||
|
||||
+ inference/dataflow:
|
||||
|
||||
- type inference
|
||||
|
||||
+ compiler:
|
||||
|
||||
- slot compilation
|
||||
- optimize away dispatch
|
||||
- getenv/setenv: if literal arg, compile as a load/store
|
||||
- assembler opcodes dispatch on operand types
|
||||
|
|
|
@ -117,6 +117,7 @@ USE: namespaces
|
|||
"/library/inference/branches.factor"
|
||||
"/library/inference/words.factor"
|
||||
"/library/inference/stack.factor"
|
||||
"/library/inference/types.factor"
|
||||
|
||||
"/library/compiler/assembler.factor"
|
||||
"/library/compiler/xt.factor"
|
||||
|
|
|
@ -54,7 +54,7 @@ BUILTIN: dll 15
|
|||
BUILTIN: alien 16
|
||||
|
||||
M: alien hashcode ( obj -- n )
|
||||
alien-address ;
|
||||
alien-address >fixnum ;
|
||||
|
||||
M: alien = ( obj obj -- ? )
|
||||
over alien? [
|
||||
|
|
|
@ -121,6 +121,10 @@ USE: math
|
|||
#! MOV INDIRECT <reg> TO <reg>.
|
||||
HEX: 8b compile-byte 0 MOD-R/M ;
|
||||
|
||||
: D[R]>R ( disp reg reg -- )
|
||||
#! MOV INDIRECT DISPLACED <reg> TO <reg>.
|
||||
HEX: 8b compile-byte 1 MOD-R/M compile-byte ;
|
||||
|
||||
: R>[R] ( reg reg -- )
|
||||
#! MOV <reg> TO INDIRECT <reg>.
|
||||
HEX: 89 compile-byte swap 0 MOD-R/M ;
|
||||
|
|
|
@ -82,7 +82,9 @@ USE: math
|
|||
|
||||
#slot [
|
||||
PEEK-DS
|
||||
|
||||
2unlist type-tag >r cell * r> - EAX EAX D[R]>R
|
||||
DS ECX [I]>R absolute-ds
|
||||
EAX ECX R>[R]
|
||||
] "generator" set-word-property
|
||||
|
||||
#call [
|
||||
|
|
|
@ -105,3 +105,7 @@ SYMBOL: previous-offset
|
|||
] catch ;
|
||||
|
||||
#label [ save-xt ] "generator" set-word-property
|
||||
|
||||
: type-tag ( type -- tag )
|
||||
#! Given a type number, return the tag number.
|
||||
dup 6 > [ drop 3 ] when ;
|
||||
|
|
|
@ -168,13 +168,10 @@ SYMBOL: classes
|
|||
SYMBOL: object
|
||||
|
||||
: type-union ( list list -- list )
|
||||
append prune [ > ] sort ;
|
||||
|
||||
: type-intersection ( list list -- list )
|
||||
intersection [ > ] sort ;
|
||||
append prune ;
|
||||
|
||||
: lookup-union ( typelist -- class )
|
||||
classes get hash [ object ] unless* ;
|
||||
[ > ] sort classes get hash [ object ] unless* ;
|
||||
|
||||
: class-or ( class class -- class )
|
||||
#! Return a class that both classes are subclasses of.
|
||||
|
@ -182,12 +179,19 @@ SYMBOL: object
|
|||
swap builtin-supertypes
|
||||
type-union lookup-union ;
|
||||
|
||||
: class-or-list ( list -- class )
|
||||
#! Return a class that every class in the list is a
|
||||
#! subclass of.
|
||||
[
|
||||
[ builtin-supertypes [ unique, ] each ] each
|
||||
] make-list lookup-union ;
|
||||
|
||||
: class-and ( class class -- class )
|
||||
#! Return a class that is a subclass of both, or raise an
|
||||
#! error if this is impossible.
|
||||
over builtin-supertypes
|
||||
over builtin-supertypes
|
||||
type-intersection dup [
|
||||
intersection dup [
|
||||
nip nip lookup-union
|
||||
] [
|
||||
drop [
|
||||
|
@ -196,8 +200,18 @@ SYMBOL: object
|
|||
] make-string throw
|
||||
] ifte ;
|
||||
|
||||
: define-promise ( class -- )
|
||||
#! A promise is a word that has no effect during
|
||||
#! interpretation, but instructs the compiler that the value
|
||||
#! at the top of the stack is statically-known to be of the
|
||||
#! given type. Promises should only be used by kernel code.
|
||||
dup word-name "%" swap cat2 "in" get create
|
||||
dup [ ] define-compound
|
||||
swap "promise" set-word-property ;
|
||||
|
||||
: define-class ( class metaclass -- )
|
||||
dupd "metaclass" set-word-property
|
||||
dup define-promise
|
||||
dup builtin-supertypes [ > ] sort
|
||||
classes get set-hash ;
|
||||
|
||||
|
|
|
@ -90,3 +90,6 @@ predicate [
|
|||
|
||||
PREDICATE: compound generic ( word -- ? )
|
||||
"combination" word-property ;
|
||||
|
||||
PREDICATE: compound promise ( obj -- ? )
|
||||
"promise" word-property ;
|
||||
|
|
|
@ -39,42 +39,41 @@ USE: words
|
|||
USE: hashtables
|
||||
USE: prettyprint
|
||||
|
||||
: vector-length< ( vec1 vec2 -- ? )
|
||||
swap vector-length swap vector-length < ;
|
||||
: longest-vector ( list -- length )
|
||||
[ vector-length ] map [ > ] top ;
|
||||
|
||||
: unify-length ( vec1 vec2 -- vec1 )
|
||||
2dup vector-length< [ swap ] unless [
|
||||
vector-length over vector-length -
|
||||
empty-vector [ swap vector-append ] keep
|
||||
] keep ;
|
||||
: computed-value-vector ( n -- vector )
|
||||
[ drop object <computed> ] vector-project ;
|
||||
|
||||
: unify-classes ( value value -- class )
|
||||
#! If one of the values is f, it was added as a result of
|
||||
#! length unification so we just replace it with a computed
|
||||
#! object value.
|
||||
2dup and [
|
||||
value-class swap value-class class-or
|
||||
: add-inputs ( count stack -- count stack )
|
||||
#! Add this many inputs to the given stack.
|
||||
[ vector-length - dup ] keep
|
||||
>r computed-value-vector dup r> vector-append ;
|
||||
|
||||
: unify-lengths ( list -- list )
|
||||
#! Pad all vectors to the same length. If one vector is
|
||||
#! shorter, pad it with unknown results at the bottom.
|
||||
dup longest-vector swap [ dupd add-inputs nip ] map nip ;
|
||||
|
||||
: unify-results ( list -- value )
|
||||
#! If all values in list are equal, return the value.
|
||||
#! Otherwise, unify types.
|
||||
dup all=? [
|
||||
car
|
||||
] [
|
||||
2drop object
|
||||
[ value-class ] map class-or-list <computed>
|
||||
] ifte ;
|
||||
|
||||
: unify-results ( value value -- value )
|
||||
#! Replace values with unknown result if they differ,
|
||||
#! otherwise retain them.
|
||||
2dup = [
|
||||
drop
|
||||
] [
|
||||
unify-classes <computed>
|
||||
] ifte ;
|
||||
: vector-transpose ( list -- vector )
|
||||
#! Turn a list of same-length vectors into a vector of lists.
|
||||
dup car vector-length [
|
||||
over [ dupd vector-nth ] map nip
|
||||
] vector-project nip ;
|
||||
|
||||
: unify-stacks ( list -- stack )
|
||||
#! Replace differing literals in stacks with unknown
|
||||
#! results.
|
||||
uncons [
|
||||
unify-length vector-zip [
|
||||
uncons unify-results
|
||||
] vector-map
|
||||
] each ;
|
||||
unify-lengths vector-transpose [ unify-results ] vector-map ;
|
||||
|
||||
: balanced? ( list -- ? )
|
||||
#! Check if a list of [ instack | outstack ] pairs is
|
||||
|
@ -139,9 +138,16 @@ SYMBOL: cloned
|
|||
meta-d off meta-r off d-in off
|
||||
] when ;
|
||||
|
||||
: propagate-type ( [ value | class ] -- )
|
||||
#! Type propagation is chained.
|
||||
[
|
||||
unswons 2dup set-value-class
|
||||
[ type-propagations get ] bind assoc propagate-type
|
||||
] when* ;
|
||||
|
||||
: infer-branch ( value -- namespace )
|
||||
<namespace> [
|
||||
uncons [ unswons set-value-class ] when*
|
||||
uncons propagate-type
|
||||
dup value-recursion recursive-state set
|
||||
copy-inference
|
||||
literal-value dup infer-quot
|
||||
|
@ -234,9 +240,8 @@ SYMBOL: cloned
|
|||
#! Infer effects for all branches, unify.
|
||||
[ object vector ] ensure-d
|
||||
dataflow-drop, pop-d vtable>list
|
||||
[ f cons ] map
|
||||
>r 1 meta-d get vector-tail* #dispatch r>
|
||||
pop-d drop ( n )
|
||||
pop-d ( n ) num-types [ dupd cons ] project nip zip
|
||||
infer-branches ;
|
||||
|
||||
USE: kernel-internals
|
||||
|
|
|
@ -56,18 +56,24 @@ SYMBOL: d-in
|
|||
! Recursive state. An alist, mapping words to labels.
|
||||
SYMBOL: recursive-state
|
||||
|
||||
! A value has the following slots:
|
||||
GENERIC: literal-value ( value -- obj )
|
||||
GENERIC: value= ( literal value -- ? )
|
||||
GENERIC: value-class ( value -- class )
|
||||
GENERIC: value-class-and ( class value -- )
|
||||
GENERIC: set-value-class ( class value -- )
|
||||
|
||||
! A value has the following slots in addition to those relating
|
||||
! to generics above:
|
||||
|
||||
! An association list mapping values to [ value | class ] pairs
|
||||
SYMBOL: type-propagations
|
||||
|
||||
TRAITS: computed
|
||||
C: computed ( class -- value )
|
||||
[
|
||||
\ value-class set
|
||||
gensym \ literal-value set
|
||||
type-propagations off
|
||||
] extend ;
|
||||
M: computed literal-value ( value -- obj )
|
||||
"Cannot use a computed value literally." throw ;
|
||||
|
@ -82,7 +88,11 @@ M: computed set-value-class ( class value -- )
|
|||
|
||||
TRAITS: literal
|
||||
C: literal ( obj rstate -- value )
|
||||
[ recursive-state set \ literal-value set ] extend ;
|
||||
[
|
||||
recursive-state set
|
||||
\ literal-value set
|
||||
type-propagations off
|
||||
] extend ;
|
||||
M: literal literal-value ( value -- obj )
|
||||
[ \ literal-value get ] bind ;
|
||||
M: literal value= ( literal value -- ? )
|
||||
|
|
|
@ -38,15 +38,14 @@ USE: strings
|
|||
USE: vectors
|
||||
USE: words
|
||||
USE: stdio
|
||||
USE: prettyprint
|
||||
|
||||
! Enhanced inference of primitives relating to data types.
|
||||
! Optimizes type checks and slot access.
|
||||
|
||||
: infer-check ( assert class -- )
|
||||
peek-d dup value-class pick = [
|
||||
[
|
||||
"Optimized out " , rot word-name , " check." ,
|
||||
] make-string print 2drop
|
||||
3drop
|
||||
] [
|
||||
value-class-and
|
||||
dup "infer-effect" word-property consume/produce
|
||||
|
@ -65,6 +64,7 @@ USE: stdio
|
|||
] "infer" set-word-property
|
||||
|
||||
\ slot [
|
||||
[ object fixnum ] ensure-d
|
||||
dataflow-drop, pop-d literal-value
|
||||
peek-d value-class builtin-supertypes dup length 1 = [
|
||||
cons #slot dataflow, [
|
||||
|
@ -77,3 +77,26 @@ USE: stdio
|
|||
"slot called without static type knowledge" throw
|
||||
] ifte
|
||||
] "infer" set-word-property
|
||||
|
||||
: type-value-map ( value -- )
|
||||
[
|
||||
num-types [
|
||||
dup builtin-type dup [
|
||||
pick swons cons ,
|
||||
] [
|
||||
2drop
|
||||
] ifte
|
||||
] times*
|
||||
] make-list nip ;
|
||||
|
||||
\ type [
|
||||
[ object ] ensure-d
|
||||
\ type #call dataflow, [
|
||||
peek-d type-value-map >r
|
||||
1 0 node-inputs
|
||||
[ object ] consume-d
|
||||
[ fixnum ] produce-d
|
||||
r> peek-d [ type-propagations set ] bind
|
||||
1 0 node-outputs
|
||||
] bind
|
||||
] "infer" set-word-property
|
||||
|
|
|
@ -112,6 +112,9 @@ M: compound (apply-word) ( word -- )
|
|||
infer-compound
|
||||
] ifte ;
|
||||
|
||||
M: promise (apply-word) ( word -- )
|
||||
"promise" word-property unit ensure-d ;
|
||||
|
||||
M: symbol (apply-word) ( word -- )
|
||||
apply-literal ;
|
||||
|
||||
|
@ -125,7 +128,7 @@ M: symbol (apply-word) ( word -- )
|
|||
#! diverging recursion. Note that this check is not done for
|
||||
#! mutually-recursive words. Generally they should be
|
||||
#! avoided.
|
||||
recursive-state get car = [
|
||||
current-word = [
|
||||
d-in get vector-length
|
||||
meta-d get vector-length > [
|
||||
current-word word-name " diverges." cat2 throw
|
||||
|
@ -183,6 +186,8 @@ M: symbol (apply-word) ( word -- )
|
|||
|
||||
\ call [ infer-call ] "infer" set-word-property
|
||||
|
||||
\ * [ [ number number ] [ number ] ] "infer-effect" set-word-property
|
||||
|
||||
\ undefined-method t "terminator" set-word-property
|
||||
\ not-a-number t "terminator" set-word-property
|
||||
\ throw t "terminator" set-word-property
|
||||
|
|
|
@ -31,6 +31,8 @@ USE: kernel
|
|||
USE: vectors
|
||||
|
||||
: dispatch ( n vtable -- )
|
||||
#! This word is unsafe in compiled code since n is not
|
||||
#! bounds-checked. Do not call it directly.
|
||||
vector-nth call ;
|
||||
|
||||
IN: kernel
|
||||
|
|
|
@ -37,11 +37,11 @@ USE: math-internals
|
|||
|
||||
GENERIC: real ( #{ re im } -- re )
|
||||
M: real real ;
|
||||
M: complex real 0 slot ;
|
||||
M: complex real 0 slot %real ;
|
||||
|
||||
GENERIC: imaginary ( #{ re im } -- im )
|
||||
M: real imaginary drop 0 ;
|
||||
M: complex imaginary 1 slot ;
|
||||
M: complex imaginary 1 slot %real ;
|
||||
|
||||
: rect> ( xr xi -- x )
|
||||
over real? over real? and [
|
||||
|
|
|
@ -34,11 +34,11 @@ USE: math-internals
|
|||
|
||||
GENERIC: numerator ( a/b -- a )
|
||||
M: integer numerator ;
|
||||
M: ratio numerator 0 slot ;
|
||||
M: ratio numerator 0 slot %integer ;
|
||||
|
||||
GENERIC: denominator ( a/b -- b )
|
||||
M: integer denominator drop 1 ;
|
||||
M: ratio denominator 1 slot ;
|
||||
M: ratio denominator 1 slot %integer ;
|
||||
|
||||
IN: math-internals
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ USE: words
|
|||
[ sbuf-reverse " sbuf -- " [ [ sbuf ] [ ] ] ]
|
||||
[ sbuf-clone " sbuf -- sbuf " [ [ sbuf ] [ sbuf ] ] ]
|
||||
[ sbuf= " sbuf sbuf -- ? " [ [ sbuf sbuf ] [ boolean ] ] ]
|
||||
[ sbuf-hashcode " sbuf -- n " [ [ sbuf ] [ integer ] ] ]
|
||||
[ sbuf-hashcode " sbuf -- n " [ [ sbuf ] [ fixnum ] ] ]
|
||||
[ arithmetic-type " n n -- type " [ [ number number ] [ number number fixnum ] ] ]
|
||||
[ >fixnum " n -- fixnum " [ [ number ] [ fixnum ] ] ]
|
||||
[ >bignum " n -- bignum " [ [ number ] [ bignum ] ] ]
|
||||
|
|
|
@ -34,7 +34,7 @@ USE: math
|
|||
|
||||
! Define methods bound to primitives
|
||||
BUILTIN: string 12
|
||||
M: string hashcode 2 slot ;
|
||||
M: string hashcode 2 slot %fixnum ;
|
||||
M: string = str= ;
|
||||
|
||||
: str-length ( str -- len ) >string 1 integer-slot ; inline
|
||||
|
|
|
@ -36,9 +36,9 @@ USE: generic
|
|||
: inline-test
|
||||
car car ; inline
|
||||
|
||||
[ t ] [
|
||||
\ slot [ inline-test ] dataflow dataflow-contains-param? >boolean
|
||||
] unit-test
|
||||
! [ t ] [
|
||||
! \ slot [ inline-test ] dataflow dataflow-contains-param? >boolean
|
||||
! ] unit-test
|
||||
|
||||
[ t ] [
|
||||
#ifte [ [ drop ] [ + ] ifte ] dataflow dataflow-contains-op? >boolean
|
||||
|
|
|
@ -20,41 +20,18 @@ unit-test
|
|||
[ [ vector ] [ cons vector cons integer object cons ] ]
|
||||
[ [ vector ] [ cons vector cons ] ]
|
||||
decompose
|
||||
]
|
||||
] unit-test
|
||||
|
||||
[ [ [ object ] [ object ] ] ]
|
||||
[
|
||||
[ [ object number ] [ object ] ]
|
||||
[ [ object number ] [ object ] ]
|
||||
decompose
|
||||
]
|
||||
] unit-test
|
||||
|
||||
: old-effect ( [ in-types out-types ] -- [ in | out ] )
|
||||
uncons car length >r length r> cons ;
|
||||
|
||||
[
|
||||
[ 1 | 2 ]
|
||||
[ 2 | 1 ]
|
||||
[ 0 | 3 ]
|
||||
[ 4 | 2 ]
|
||||
[ 3 | 3 ]
|
||||
[ 0 | 0 ]
|
||||
[ 1 | 5 ]
|
||||
[ 3 | 4 ]
|
||||
] "effects" set
|
||||
|
||||
[ { f 1 2 } { 1 2 3 } ] [
|
||||
{ 1 2 } { 1 2 3 } unify-length
|
||||
] unit-test
|
||||
|
||||
[ [ sq ] ] [
|
||||
[ sq ] f <literal> [ sq ] f <literal> unify-results literal-value
|
||||
] unit-test
|
||||
|
||||
[ fixnum ] [
|
||||
5 f <literal> 6 f <literal> unify-results value-class
|
||||
] unit-test
|
||||
|
||||
[ [ 0 | 2 ] ] [ [ 2 "Hello" ] infer old-effect ] unit-test
|
||||
[ [ 1 | 2 ] ] [ [ dup ] infer old-effect ] unit-test
|
||||
|
||||
|
@ -109,10 +86,10 @@ unit-test
|
|||
|
||||
[ [ 1 | 1 ] ] [ [ simple-recursion-2 ] infer old-effect ] unit-test
|
||||
|
||||
: bad-recursion-1
|
||||
dup [ drop bad-recursion-1 5 ] [ ] ifte ;
|
||||
|
||||
[ [ bad-recursion-1 ] infer old-effect ] unit-test-fails
|
||||
! : bad-recursion-1
|
||||
! dup [ drop bad-recursion-1 5 ] [ ] ifte ;
|
||||
!
|
||||
! [ [ bad-recursion-1 ] infer old-effect ] unit-test-fails
|
||||
|
||||
: bad-recursion-2
|
||||
dup [ uncons bad-recursion-2 ] [ ] ifte ;
|
||||
|
@ -236,11 +213,12 @@ SYMBOL: sym-test
|
|||
|
||||
! Type inference
|
||||
|
||||
! [ [ [ object ] [ ] ] ] [ [ drop ] infer ] unit-test
|
||||
! [ [ [ object ] [ object object ] ] ] [ [ dup ] infer ] unit-test
|
||||
! [ [ [ object object ] [ cons ] ] ] [ [ cons ] infer ] unit-test
|
||||
! [ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] infer ] unit-test
|
||||
! [ [ [ object ] [ object ] ] ] [ [ dup [ car ] when ] infer ] unit-test
|
||||
! [ [ [ vector ] [ vector ] ] ] [ [ vector-clone ] infer ] unit-test
|
||||
[ [ [ object ] [ ] ] ] [ [ drop ] infer ] unit-test
|
||||
[ [ [ object ] [ object object ] ] ] [ [ dup ] infer ] unit-test
|
||||
[ [ [ object object ] [ cons ] ] ] [ [ cons ] infer ] unit-test
|
||||
[ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] infer ] unit-test
|
||||
[ [ [ general-list ] [ object ] ] ] [ [ dup [ car ] when ] infer ] unit-test
|
||||
[ [ [ vector ] [ vector ] ] ] [ [ vector-clone ] infer ] unit-test
|
||||
! [ [ [ number ] [ number ] ] ] [ [ dup + ] infer ] unit-test
|
||||
! [ [ [ number number number ] [ number ] ] ] [ [ digit+ ] infer ] unit-test
|
||||
[ [ [ number ] [ real real ] ] ] [ [ >rect ] infer ] unit-test
|
||||
|
|
|
@ -37,7 +37,7 @@ USE: strings
|
|||
|
||||
BUILTIN: word 1
|
||||
|
||||
M: word hashcode 1 slot ;
|
||||
M: word hashcode 1 slot %fixnum ;
|
||||
|
||||
: word-xt ( w -- xt ) >word 2 integer-slot ; inline
|
||||
: set-word-xt ( xt w -- ) >word 2 set-integer-slot ; inline
|
||||
|
@ -84,7 +84,11 @@ PREDICATE: word undefined ( obj -- ? ) word-primitive 0 = ;
|
|||
: intern-symbol ( word -- )
|
||||
dup undefined? [ define-symbol ] [ drop ] ifte ;
|
||||
|
||||
: word-name ( word -- str ) "name" word-property ;
|
||||
#! The type declaration is for the benefit of stack effect
|
||||
#! inference.
|
||||
: word-name ( word -- str )
|
||||
"name" word-property >string ;
|
||||
|
||||
: word-vocabulary ( word -- str ) "vocabulary" word-property ;
|
||||
: stack-effect ( word -- str ) "stack-effect" word-property ;
|
||||
: documentation ( word -- str ) "documentation" word-property ;
|
||||
|
|
Loading…
Reference in New Issue