work on inferencer, and vector-2map combinator

cvs
Slava Pestov 2004-11-05 22:41:54 +00:00
parent d7db4d1ccd
commit df39f78f6d
7 changed files with 90 additions and 11 deletions

View File

@ -37,6 +37,7 @@ USE: vectors
: dupd ( x y -- x x y ) >r dup r> ;
: swapd ( x y z -- y x z ) >r swap r> ;
: transp ( x y z -- z y x ) swap rot ;
: 2swap ( x y z t -- z t x y ) rot >r rot r> ;
: clear ( -- )
#! Clear the datastack. For interactive use only; invoking

View File

@ -32,9 +32,6 @@ USE: lists
USE: math
USE: stack
: 2vector-nth ( n vec vec -- obj obj )
>r over >r vector-nth r> r> vector-nth ;
: ?vector= ( n vec vec -- ? )
#! Reached end?
drop vector-length = ;

View File

@ -5,9 +5,17 @@ USE: math
USE: stack
USE: combinators
USE: vectors
USE: kernel
[ 6 ] [ 6 gensym-vector vector-length ] unit-test
[ t ] [
{ 1 2 } { 1 2 3 }
unify-lengths swap vector-length swap vector-length =
] unit-test
[ [ sq ] ] [ [ sq ] [ sq ] unify-result ] unit-test
[ [ 0 | 2 ] ] [ [ 2 "Hello" ] infer ] unit-test
[ [ 1 | 2 ] ] [ [ dup ] infer ] unit-test
@ -41,3 +49,11 @@ USE: vectors
[ [ 1 | 0 ] ] [ [ [ drop ] when* ] infer ] unit-test
[ [ 1 | 1 ] ] [ [ [ { { [ ] } } ] unless* ] infer ] unit-test
[ [ 0 | 1 ] ] [
[ [ 2 2 fixnum+ ] dup [ ] when call ] infer
] unit-test
[
[ [ 2 2 fixnum+ ] ] [ [ 2 2 fixnum* ] ] ifte call
] unit-test-fails

View File

@ -35,3 +35,11 @@ USE: vectors
[ { 1 2 3 4 5 6 } ]
[ { 1 2 3 } vector-clone dup { 4 5 6 } vector-append ] unit-test
[ { 6 8 10 12 } ]
[ { 1 2 3 4 } { 5 6 7 8 } [ + ] vector-2map ]
unit-test
[ { [ 1 | 5 ] [ 2 | 6 ] [ 3 | 7 ] [ 4 | 8 ] } ]
[ { 1 2 3 4 } { 5 6 7 8 } vector-zip ]
unit-test

View File

@ -53,19 +53,19 @@ SYMBOL: r-in
: inputs ( count stack -- stack )
#! Add this many inputs to the given stack.
>r dup d-in +@ gensym-vector dup r> vector-append ;
>r gensym-vector dup r> vector-append ;
: ensure ( count stack -- stack )
: ensure ( count stack -- count stack )
#! Ensure stack has this many elements.
2dup vector-length > [
[ vector-length - ] keep inputs
[ vector-length - dup ] keep inputs
] [
nip
>r drop 0 r>
] ifte ;
: ensure-d ( count -- )
#! Ensure count of unknown results are on the stack.
meta-d get ensure meta-d set ;
meta-d get ensure meta-d set d-in +@ ;
: consume-d ( count -- )
#! Remove count of elements.
@ -76,6 +76,10 @@ SYMBOL: r-in
[ gensym push-d ] times ;
: standard-effect ( word [ in | out ] -- )
#! If a word does not have special inference behavior, we
#! either execute the word in the meta interpreter (if it is
#! side-effect-free and all parameters are literal), or
#! simply apply its stack effect to the meta-interpreter.
over "meta-infer" word-property [
drop host-word
] [
@ -118,35 +122,61 @@ DEFER: (infer)
d-in get meta-d get vector-length cons ;
: (infer) ( quot -- )
#! Recursive calls to this word are made for nested
#! quotations.
[ dup word? [ apply-word ] [ push-d ] ifte ] each ;
: infer ( quot -- [ in | out ] )
#! Stack effect of a quotation.
[ init-inference (infer) effect ] with-scope ;
: infer-branch ( quot -- [ in-d | datastack ] )
: infer-branch ( quot -- [ in-d | datastack ] )
#! Infer the quotation's effect, restoring the meta
#! interpreter state afterwards.
[
copy-interpreter (infer)
d-in get meta-d get cons
] with-scope ;
: difference ( [ in | stack ] -- diff )
#! Stack height difference of infer-branch return value.
uncons vector-length - ;
: balanced? ( [ in | stack ] [ in | stack ] -- ? )
#! Check if two stack effects preserve stack height.
difference swap difference = ;
: max-vector-length ( vector vector -- length )
swap vector-length swap vector-length max ;
: unify-lengths ( stack stack -- stack stack )
#! If one vector is shorter, pad it with unknown results at
#! the bottom.
2dup max-vector-length
tuck swap ensure nip >r swap ensure nip r> ;
: unify-result ( obj obj -- obj )
#! Replace values with unknown result if they differ,
#! otherwise retain them.
2dup = [ drop ] [ 2drop gensym ] ifte ;
: unify-stacks ( stack stack -- stack )
swap vector-length swap vector-length max gensym-vector ;
#! Replace differing literals in stacks with unknown
#! results.
unify-lengths [ unify-result ] vector-2map ;
: unify ( [ in | stack ] [ in | stack ] -- )
#! Unify meta-interpreter state from two branches.
2dup balanced? [
2dup 2car max d-in set 2cdr unify-stacks meta-d set
2dup
2car max d-in set
2cdr unify-stacks meta-d set
] [
"Unbalanced ifte branches" throw
] ifte ;
: infer-ifte ( -- )
#! Infer effects for both branches, unify.
pop-d pop-d pop-d drop ( condition )
>r infer-branch r> infer-branch unify ;

View File

@ -28,6 +28,7 @@
IN: vectors
USE: combinators
USE: kernel
USE: lists
USE: logic
USE: math
USE: stack
@ -57,3 +58,26 @@ USE: stack
: vector-append ( v1 v2 -- )
#! Destructively append v2 to v1.
[ over vector-push ] vector-each drop ;
: vector-collect ( n quot -- accum )
#! Execute the quotation n times, passing the loop counter
#! the quotation, and collect results in a new vector.
over <vector> rot [
-rot 2dup >r >r slip vector-push r> r>
] times* nip ;
: vector-zip ( v1 v2 -- v )
#! Make a new vector with each pair of elements from the
#! first two in a pair.
over vector-length [
pick pick 2vector-nth cons
] vector-collect nip nip ;
: vector-2map ( v1 v2 quot -- v )
#! Apply a quotation with stack effect ( obj obj -- obj ) to
#! each pair of elements from v1 and v2, collecting them
#! into a new list. Behavior is undefined if vector lengths
#! differ.
-rot vector-zip [
swap dup >r >r uncons r> call r> swap
] vector-map nip ;

View File

@ -31,6 +31,9 @@ USE: lists
USE: math
USE: stack
: 2vector-nth ( n vec vec -- obj obj )
>r over >r vector-nth r> r> vector-nth ;
: empty-vector ( len -- vec )
#! Creates a vector with 'len' elements set to f. Unlike
#! <vector>, which gives an empty vector with a certain