]> gitweb.factorcode.org Git - factor.git/commitdiff
working on stack effect inference
authorSlava Pestov <slava@factorcode.org>
Thu, 18 Nov 2004 01:59:28 +0000 (01:59 +0000)
committerSlava Pestov <slava@factorcode.org>
Thu, 18 Nov 2004 01:59:28 +0000 (01:59 +0000)
15 files changed:
TODO.FACTOR.txt
factor/parser/Ine.java
factor/parser/Symbol.java
library/assoc.factor
library/cons.factor
library/lists.factor
library/platform/native/math.factor
library/test/inference.factor
library/test/lists/assoc.factor
library/test/lists/combinators.factor [new file with mode: 0644]
library/test/lists/cons.factor
library/test/lists/lists.factor
library/test/test.factor
library/tools/inference.factor
library/tools/interpreter.factor

index 25b31e895ec48ea8ef9be989340b4b2409bb65b6..a1d7d0c74cb2578b90c507c5781982dab8da9f72 100644 (file)
@@ -1,5 +1,6 @@
 + inference/interpreter:\r
 \r
+- word links in stepper\r
 - : bin 5 [ 5 bin bin 5 ] [ 2drop ] ifte ;\r
 - combinator inference\r
 - generic/2generic inference\r
index cb08072c7c8e77d89a5af0002e5a69b1ff570162..4e2a14288f1413121893b21efb0e51a8274f45a9 100644 (file)
@@ -53,9 +53,6 @@ public class Ine extends FactorParsingDefinition
                if(w == null)
                        return;
 
-               reader.append(w.vocabulary);
-               reader.append(w.name);
                reader.append(new FactorCompoundDefinition(w,state.first));
-               reader.append(reader.intern("define",false));
        }
 }
index f0e7c9b1732f9c6e9262e032d5dcae38523d7494..824869f454110482dceff0c995245a1f087f41eb 100644 (file)
@@ -46,9 +46,6 @@ public class Symbol extends FactorParsingDefinition
                throws Exception
        {
                FactorWord w = reader.nextWord(true);
-               reader.append(w.vocabulary);
-               reader.append(w.name);
                reader.append(new FactorSymbolDefinition(w,w));
-               reader.append(reader.intern("define",false));
        }
 }
index ec89d8165db7fe86db7c7c0175449c561cb1c175..d0a4383b1ebd563070426c017d9bbff595e1c44e 100644 (file)
@@ -79,3 +79,9 @@ USE: stack
             2drop
         ] ifte r>
     ] each drop ;
+
+: unzip ( assoc -- keys values )
+    #! Split an association list into two lists of keys and
+    #! values.
+    [ ] [ ] rot [ uncons 2swons ] each
+    swap reverse swap reverse ;
index 32030f550847e083f4cce15eced80038d7807079..771915475f3f2d71655f54de89282856f34847f6 100644 (file)
@@ -49,3 +49,9 @@ IN: lists USE: kernel USE: stack
 
 : 2cdr ( cons cons -- car car )
     swap cdr swap cdr ;
+
+: 2cons ( cdr1 cdr2 car1 car2 -- cons1 cons2 )
+    rot swons >r cons r> ;
+
+: 2swons ( cdr1 cdr2 car1 car2 -- cons1 cons2 )
+    rot cons >r swons r> ;
index f75f1150a520c80c6b9f8f6b925d61939aa0c395..3ac9fedfc068948a69283172413355280899ac22 100644 (file)
@@ -203,6 +203,24 @@ DEFER: tree-contains?
         2drop t
     ] ifte ;
 
+: all=? ( list -- ? )
+    #! Check if all elements of a list are equal.
+    dup [ uncons [ over = ] all? nip ] [ drop t ] ifte ;
+
+: maximize ( pred o1 o2 -- o1/o2 )
+    #! Return o1 if pred returns true, o2 otherwise.
+    [ rot call ] 2keep ? ;
+
+: (top) ( list maximizer -- elt )
+    #! Return the highest element in the list, where maximizer
+    #! has stack effect ( o1 o2 -- max(o1,o2) ).
+    >r uncons r> each ;
+
+: top ( list pred -- elt )
+    #! Return the highest element in the list, where pred is a
+    #! partial order with stack effect ( o1 o2 -- ? ).
+    swap [ pick >r maximize r> swap ] (top) nip ;
+
 : (count) ( n list -- list )
     >r pred dup 0 < [ drop r> ] [ dup r> cons (count) ] ifte ;
 
index 2ae2b8451ff3f7e09d477493a7efd191f5689343..12f653cc9df9b33763c0bb5a404dc41d161c1bbe 100644 (file)
@@ -33,6 +33,8 @@ USE: stack
 USE: vectors
 USE: words
 
+DEFER: number=
+
 : (gcd) ( x y -- z ) dup 0 = [ drop ] [ tuck mod (gcd) ] ifte ;
 : gcd ( x y -- z ) abs swap abs 2dup < [ swap ] when (gcd) ;
 
@@ -44,7 +46,8 @@ USE: words
     [ swap numerator swap numerator ] 2keep
     swap denominator swap denominator ;
 
-: ratio= ( a/b c/d -- ? ) 2>fraction = [ = ] [ 2drop f ] ifte ;
+: ratio= ( a/b c/d -- ? )
+    2>fraction number= [ number= ] [ 2drop f ] ifte ;
 : ratio-scale ( a/b c/d -- a*d b*c )
     2>fraction >r * swap r> * swap ;
 : ratio+d ( a/b c/d -- b*d ) denominator swap denominator * ;
@@ -64,7 +67,8 @@ USE: words
     [ swap real swap real ] 2keep
     swap imaginary swap imaginary ;
 
-: complex= ( x y -- ? ) 2>rect = [ = ] [ 2drop f ] ifte ;
+: complex= ( x y -- ? )
+    2>rect number= [ number= ] [ 2drop f ] ifte ;
 
 : complex+ ( x y -- x+y ) 2>rect + >r + r> rect> ;
 : complex- ( x y -- x-y ) 2>rect - >r - r> rect> ;
index ca03c95faf5aa937a1a4797b49b40ac7559ff534..c817bb100210673ef057575937d9be6760889763 100644 (file)
@@ -10,9 +10,10 @@ USE: lists
 
 [ 6 ] [ 6 gensym-vector vector-length ] unit-test
 
+[ 3 ] [ [ { 1 2 } { 1 2 3 } ] max-vector-length ] unit-test
+
 [ t ] [
-    { 1 2 } { 1 2 3 } 
-    unify-lengths swap vector-length swap vector-length =
+    [ { 1 2 } { 1 2 3 } ] unify-lengths [ vector-length ] map all=?
 ] unit-test
 
 [ [ sq ] ] [ [ sq ] [ sq ] unify-result ] unit-test
@@ -84,7 +85,31 @@ USE: lists
 [ [ bad-recursion-2 ] infer ] unit-test-fails
 
 ! Simple combinators
-[ [ 1 | 2 ] [ [ car ] keep cdr ] infer ] unit-test
+[ [ 1 | 2 ] ] [ [ [ car ] keep cdr ] infer ] unit-test
+
+! Mutual recursion
+DEFER: foe
+
+: fie ( element obj -- ? )
+    dup cons? [ foe ] [ eq? ] ifte ;
+
+: foe ( element tree -- ? )
+    dup [
+        2dup car fie [
+            nip
+        ] [
+            cdr dup cons? [
+                foe
+            ] [
+                fie
+            ] ifte
+        ] ifte
+    ] [
+        2drop f
+    ] ifte ;
+
+[ [ 2 | 1 ] ] [ [ fie ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ foe ] infer ] unit-test
 
 [ [ 2 | 1 ] ] [ [ 2list ] infer ] unit-test
 [ [ 3 | 1 ] ] [ [ 3list ] infer ] unit-test
@@ -96,3 +121,6 @@ USE: lists
 ! [ [ 1 | 1 ] ] [ [ last* ] infer ] unit-test
 ! [ [ 1 | 1 ] ] [ [ last ] infer ] unit-test
 ! [ [ 1 | 1 ] ] [ [ list? ] infer ] unit-test
+
+[ [ 2 | 1 ] ] [ [ bitand ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ number= ] infer ] unit-test
index 66511cd005103bc7f6736c55796040fd9787db72..386018deec0dfbddf8ff91ca6071dfb7fc2bdf08 100644 (file)
@@ -45,3 +45,6 @@ USE: test
 [ [ [ "one" + ] [ "four" * ] ] ] [
     "three" "quot-alist" get remove-assoc
 ] unit-test
+
+[ [ "one" "three" "four" ] [ [ + ] [ - ] [ * ] ] ]
+[ "quot-alist" get unzip ] unit-test
diff --git a/library/test/lists/combinators.factor b/library/test/lists/combinators.factor
new file mode 100644 (file)
index 0000000..4bd37cd
--- /dev/null
@@ -0,0 +1,34 @@
+IN: scratchpad
+USE: kernel
+USE: lists
+USE: logic
+USE: math
+USE: namespaces
+USE: stack
+USE: test
+USE: strings
+
+[ [ [ 3 2 1 ] [ 5 4 3 ] [ 6 ] ] ]
+[ [ 1 2 3 ] [ 3 4 5 ] [ 6 ] 3list [ reverse ] map ] unit-test
+
+[ f ] [ [ "Hello" { } 4/3 ] [ string? ] all? ] unit-test
+[ t ] [ [ ] [ ] all? ] unit-test
+[ t ] [ [ "hi" t 1/2 ] [ ] all? ] unit-test
+
+[ [ 1 2 3 ] ] [ [ 1 4 2 5 3 6 ] [ 4 < ] subset ] unit-test
+
+[ [ 43 "a" [ ] ] ] [ [ "a" 43 43 43 [ ] 43 "a" [ ] ] prune ] unit-test
+
+[ [ 1 2 3 4 5 6 7 ] ] [ [ 6 4 5 7 2 1 3 ] num-sort ] unit-test
+
+[ f ] [ [ { } { } "Hello" ] all=? ] unit-test
+[ f ] [ [ { 2 } { } { } ] all=? ] unit-test
+[ t ] [ [ ] all=? ] unit-test
+[ t ] [ [ 1/2 ] all=? ] unit-test
+[ t ] [ [ 1.0 10/10 1 ] all=? ] unit-test
+
+[ 5 ] [ [ 5 ] [ < ] top ] unit-test
+[ 5 ] [ [ 5 6 ] [ < ] top ] unit-test
+[ 6 ] [ [ 5 6 ] [ > ] top ] unit-test
+[ 99 ] [ 100 count [ > ] top ] unit-test
+[ 0 ] [ 100 count [ < ] top ] unit-test
index 9d82af3315d883c4234e2224ee5dad886a330b5a..f040f3242084f27f57d62517dc3e7efd64deeb79 100644 (file)
@@ -25,3 +25,11 @@ USE: test
 
 [ [ 1 2 ]   ] [ 1 2   2list  ] unit-test
 [ [ 1 2 3 ] ] [ 1 2 3 3list  ] unit-test
+
+[ [ "car1" | "cdr1" ] [ "car2" | "cdr2" ] ]
+[ "car1" "car2" "cdr1" "cdr2" 2cons ]
+unit-test
+
+[ [ "car1" | "cdr1" ] [ "car2" | "cdr2" ] ]
+[ "cdr1" "cdr2" "car1" "car2" 2swons ]
+unit-test
index bdbcbfa7bcc8d889901df81bddc3d6214af3c5f1..bdfd89b393315eef3322626939427556c8fe27ae 100644 (file)
@@ -60,9 +60,3 @@ USE: strings
 [ [ ]         ] [ 0   count ] unit-test
 [ [ ]         ] [ -10 count ] unit-test
 [ [ 0 1 2 3 ] ] [ 4   count ] unit-test
-
-[ [ 1 2 3 ] ] [ [ 1 4 2 5 3 6 ] [ 4 < ] subset ] unit-test
-
-[ [ 43 "a" [ ] ] ] [ [ "a" 43 43 43 [ ] 43 "a" [ ] ] prune ] unit-test
-
-[ [ 1 2 3 4 5 6 7 ] ] [ [ 6 4 5 7 2 1 3 ] num-sort ] unit-test
index d72133c9ee459416d4baae840eca6c7fcec240ad..dc5ac1083fbfe7dc2bbb10c6d5a204d1dd57bb9a 100644 (file)
@@ -70,6 +70,7 @@ USE: unparser
         "lists/lists"
         "lists/assoc"
         "lists/namespaces"
+        "lists/combinators"
         "combinators"
         "continuations"
         "errors"
@@ -104,12 +105,12 @@ USE: unparser
         "httpd/url-encoding"
         "httpd/html"
         "httpd/httpd"
-        "crashes" test
-        "sbuf" test
-        "threads" test
-        "parsing-word" test
-        "inference" test
-        "interpreter" test
+        "crashes"
+        "sbuf"
+        "threads"
+        "parsing-word"
+        "inference"
+        "interpreter"
     ] [
         test
     ] each
@@ -127,12 +128,16 @@ USE: unparser
         ] each
     ] when
 
-    "benchmark/empty-loop" test
-    "benchmark/fac" test
-    "benchmark/fib" test
-    "benchmark/sort" test 
-    "benchmark/continuations" test
-    "benchmark/ack" test 
-    "benchmark/hashtables" test
-    "benchmark/strings" test
-    "benchmark/vectors" test ;
+    [
+        "benchmark/empty-loop"
+        "benchmark/fac"
+        "benchmark/fib"
+        "benchmark/sort" 
+        "benchmark/continuations"
+        "benchmark/ack" 
+        "benchmark/hashtables"
+        "benchmark/strings"
+        "benchmark/vectors"
+    ] [
+        test
+    ] each ;
index 49d9ac2b27ac1f368aaa3d20f85bf503f9653ed0..0f2ceede74f4a50289e0833102265943f3cc28dd 100644 (file)
@@ -62,7 +62,8 @@ SYMBOL: recursive-state
     >r gensym-vector dup r> vector-append ;
 
 : ensure ( count stack -- count stack )
-    #! Ensure stack has this many elements.
+    #! Ensure stack has this many elements. Return number of
+    #! elements added.
     2dup vector-length > [
         [ vector-length - dup ] keep inputs
     ] [
@@ -170,7 +171,7 @@ DEFER: (infer)
     #! quotations.
     [ apply-object ] each ;
 
-: (infer-branch) ( quot -- [ in-d | datastack ] )
+: infer-branch ( quot -- [ in-d | datastack ] )
     #! Infer the quotation's effect, restoring the meta
     #! interpreter state afterwards.
     [
@@ -178,45 +179,41 @@ DEFER: (infer)
         d-in get  meta-d get cons
     ] with-scope ;
 
-: infer-branch ( quot -- [ in-d | datastack ] )
-    #! Push f if inference failed.
-    [ (infer-branch) ] [ [ drop f ] when ] catch ;
-
 : 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 = ;
+: balanced? ( list -- ? )
+    #! Check if a list of [ in | stack ] pairs has the same
+    #! stack height.
+    [ difference ] map all=? ;
 
-: max-vector-length ( vector vector -- length )
-    swap vector-length swap vector-length max ;
+: max-vector-length ( list -- length )
+    [ vector-length ] map [ > ] top ;
 
-: 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-lengths ( list -- list )
+    #! Pad all vectors to the same length. If one vector is
+    #! shorter, pad it with unknown results at the bottom.
+    dup max-vector-length swap [ dupd ensure nip ] map nip ;
 
 : 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 )
+: unify-stacks ( list -- stack )
     #! Replace differing literals in stacks with unknown
     #! results.
-    unify-lengths [ unify-result ] vector-2map ;
+    uncons [ [ unify-result ] vector-2map ] each ;
 
-: unify ( [ in | stack ] [ in | stack ] -- )
+: unify ( list -- )
     #! Unify meta-interpreter state from two branches.
-    2dup balanced? [
-        2dup
-        2car max d-in set
-        2cdr unify-stacks meta-d set
+    dup balanced? [
+        unzip
+        unify-lengths unify-stacks meta-d set
+        [ > ] top d-in set
     ] [
-        "Unbalanced ifte branches" throw
+        "Unbalanced branches" throw
     ] ifte ;
 
 : set-base ( [ in | stack ] -- )
@@ -225,33 +222,38 @@ DEFER: (infer)
     uncons vector-length cons r>
     recursive-state acons@ ;
 
-: recursive-branches ( false true fe te -- fe te )
-    #! At least one of the branches did not have a computable
-    #! stack effect. Set the base case to the other branch, and
-    #! try again.
-    2dup or [
-        dup [
-            dup set-base >r 2drop infer-branch r>
-        ] [
-            drop dup set-base swap infer-branch rot drop
-        ] ifte
-    ] [
-        no-base-case
-    ] ifte ;
+: recursive-branch ( quot -- )
+    #! Set base case if inference didn't fail.
+    [ infer-branch set-base ] [ [ drop ] when ] catch ;
 
-: infer-branches ( false true -- [ in | stack ] [ in | stack ] )
+: infer-branches ( brachlist -- )
     #! Recursive stack effect inference is done here. If one of
     #! the branches has an undecidable stack effect, we set the
     #! base case to this stack effect and try again.
-    over infer-branch over infer-branch 2dup and [
-        2nip ( all good )
-    ] [
-        recursive-branches
-    ] ifte ;
+    dup [ recursive-branch ] each [ infer-branch ] map unify ;
 
 : infer-ifte ( -- )
     #! Infer effects for both branches, unify.
-    pop-d pop-d pop-d drop ( condition ) infer-branches unify ;
+    pop-d pop-d 2list pop-d drop ( condition ) infer-branches ;
+
+: vtable>list ( vtable -- list )
+    #! generic and 2generic use vectors of words, we need lists
+    #! of quotations. Filter out no-method. Dirty workaround;
+    #! later properly handle throw.
+    vector>list [
+        dup \ no-method = [ drop f ] [ unit ] ifte
+    ] map [ ] subset ;
+
+: infer-generic ( -- )
+    #! Infer effects for all branches, unify.
+    pop-d vtable>list peek-d drop ( dispatch ) infer-branches ;
+
+: infer-2generic ( -- )
+    #! Infer effects for all branches, unify.
+    pop-d vtable>list
+    peek-d drop ( dispatch )
+    peek-d drop ( dispatch )
+    infer-branches ;
 
 : infer ( quot -- [ in | out ] )
     #! Stack effect of a quotation.
@@ -260,6 +262,12 @@ DEFER: (infer)
 \ call [ pop-d (infer) ] "infer" set-word-property
 \ ifte [ infer-ifte ] "infer" set-word-property
 
+\ generic [ infer-generic ] "infer" set-word-property
+\ generic [ 2 | 0 ] "infer-effect" set-word-property
+
+\ 2generic [ infer-2generic ] "infer" set-word-property
+\ 2generic [ 3 | 0 ] "infer-effect" set-word-property
+
 \ >r [ pop-d push-r ] "infer" set-word-property
 \ r> [ pop-r push-d ] "infer" set-word-property
 
index 8823fe206945d816ec5cd24b1b6ea35fc768a412..ca05c6298eb344e7de9ba6f91498f1075c37d030 100644 (file)
@@ -49,6 +49,7 @@ SYMBOL: meta-r
 : pop-r meta-r get vector-pop ;
 SYMBOL: meta-d
 : push-d meta-d get vector-push ;
+: peek-d meta-d get vector-peek ;
 : pop-d meta-d get vector-pop ;
 SYMBOL: meta-n
 SYMBOL: meta-c