]> gitweb.factorcode.org Git - factor.git/commitdiff
kernel errors a bit better, inference cleanup
authorSlava Pestov <slava@factorcode.org>
Sun, 26 Dec 2004 06:42:09 +0000 (06:42 +0000)
committerSlava Pestov <slava@factorcode.org>
Sun, 26 Dec 2004 06:42:09 +0000 (06:42 +0000)
16 files changed:
library/assoc.factor
library/compiler/generator-x86.factor
library/inference/branches.factor
library/inference/dataflow.factor
library/inference/inference.factor
library/inference/types.factor [new file with mode: 0644]
library/inference/words.factor
library/primitives.factor
library/test/inference.factor
library/test/lists/assoc.factor
library/test/vectors.factor
library/tools/debugger.factor
library/tools/interpreter.factor
library/vectors.factor
native/error.c
native/run.h

index 2c76f4d90dc3ac474dd4a698414bd3080c0ff0f7..d3d9982507fe6ec48cc92ea211d49b36753fdec9 100644 (file)
@@ -76,3 +76,11 @@ USE: kernel
             2drop
         ] ifte r>
     ] each drop ;
+
+: 2cons ( car1 car2 cdr1 cdr2 -- cons1 cons2 )
+    rot swons >r cons r> ;
+
+: unzip ( assoc -- keys values )
+    #! Split an association list into two lists of keys and
+    #! values.
+    [ uncons >r uncons r> unzip 2cons ] [ [ ] [ ] ] ifte* ;
index 08a5f90f5b86296c2f0c0b8826264b4110fe081d..06cb3f1f4a0733a4c71e6e8814bbfb28fd557126 100644 (file)
@@ -41,10 +41,14 @@ USE: math
     #! immediate just compiled.
     "ds" f f rel-dlsym ;
 
+: PEEK-DS ( -- )
+    #! Peek datastack to EAX.
+    DS ECX [I]>R  absolute-ds
+    ECX EAX [R]>R ;
+
 : POP-DS ( -- )
     #! Pop datastack to EAX.
-    DS ECX [I]>R  absolute-ds
-    ECX EAX [R]>R
+    PEEK-DS
     4 ECX R-I
     ECX DS R>[I]  absolute-ds ;
 
@@ -76,6 +80,11 @@ USE: math
     ECX DS R>[I]  absolute-ds
 ] "generator" set-word-property
 
+#slot [
+    PEEK-DS
+    
+] "generator" set-word-property
+
 #call [
     dup dup postpone-word
     CALL compiled-offset defer-xt
index 51ad120578de2cf170630aa991e99b7ebb7754c4..bdfbb1bf831b7421b549d00d65b3800a5c1a0c56 100644 (file)
@@ -39,75 +39,70 @@ USE: words
 USE: hashtables
 USE: prettyprint
 
-: longest-vector ( list -- length )
-    [ vector-length ] map [ > ] top ;
-
-: computed-value-vector ( n -- vector )
-    [ drop object <computed> ] vector-project ;
-
-: 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-classes ( value value -- value )
-    value-class swap value-class class-or <computed> ;
+: vector-length< ( vec1 vec2 -- ? )
+    swap vector-length swap vector-length < ;
+
+: unify-length ( vec1 vec2 -- vec1 )
+    2dup vector-length< [ swap ] unless [
+        vector-length over vector-length -
+        empty-vector [ swap vector-append ] keep
+    ] keep ;
+
+: 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
+    ] [
+        2drop object
+    ] ifte ;
 
 : unify-results ( value value -- value )
     #! Replace values with unknown result if they differ,
     #! otherwise retain them.
-    2dup = [ drop ] [ unify-classes ] ifte ;
+    2dup = [ drop ] [ unify-classes <computed> ] ifte ;
 
 : unify-stacks ( list -- stack )
     #! Replace differing literals in stacks with unknown
     #! results.
-    uncons [ [ unify-results ] vector-2map ] each ;
-
-: unify-d-in ( list -- d-in )
-    [ [ d-in get ] bind ] map unify-lengths unify-stacks ;
-
-: filter-terminators ( list -- list )
-    [ [ d-in get meta-d get and ] bind ] subset ;
+    uncons [
+        unify-length vector-zip [
+            uncons unify-results
+        ] vector-map
+    ] each ;
 
 : balanced? ( list -- ? )
-    [
-        [
-            d-in get vector-length
-            meta-d get vector-length -
-        ] bind
-    ] map all=? ;
-
-: unify-datastacks ( list -- datastack )
-    [ [ meta-d get ] bind ] map
-    unify-lengths unify-stacks ;
-
-: check-lengths ( list -- )
-    dup [ vector-length ] map all=? [
-        drop
-    ] [
-        "Unbalanced return stack effect:" <multi-error> throw
-    ] ifte ;
-
-: unify-callstacks ( list -- datastack )
-    [ [ meta-r get ] bind ] map
-    dup check-lengths unify-stacks ;
+    #! Check if a list of [ instack | outstack ] pairs is
+    #! balanced.
+    [ uncons vector-length swap vector-length - ] map all=? ;
 
-: unify-effects ( list -- )
-    filter-terminators
-    [ "No branch has a stack effect" throw ] unless*
+: unify-effect ( list -- in out )
+    #! Unify a list of [ instack | outstack ] pairs.
     dup balanced? [
-        dup unify-d-in d-in set
-        dup unify-datastacks meta-d set
-        unify-callstacks meta-r set
+        unzip unify-stacks >r unify-stacks r>
     ] [
         "Unbalanced branches" throw
     ] ifte ;
 
+: datastack-effect ( list -- )
+    [ [ d-in get meta-d get ] bind cons ] map
+    unify-effect
+    meta-d set d-in set ;
+
+: callstack-effect ( list -- )
+    [ [ { } meta-r get ] bind cons ] map
+    unify-effect
+    meta-r set drop ;
+
+: filter-terminators ( list -- list )
+    [ [ d-in get meta-d get and ] bind ] subset [
+        "No branch has a stack effect" throw
+    ] unless* ;
+
+: unify-effects ( list -- )
+    filter-terminators  dup datastack-effect callstack-effect ;
+
 : deep-clone ( vector -- vector )
     #! Clone a vector of vectors.
     [ vector-clone ] vector-map ;
index 3610047cab6afc4ff6dcf7e1a93f7ba77b7188fa..ce083c0485c93b95e5d29b112f103941d4f86d5d 100644 (file)
@@ -68,6 +68,9 @@ SYMBOL: #pick
 SYMBOL: #>r
 SYMBOL: #r>
 
+SYMBOL: #slot
+SYMBOL: #set-slot
+
 SYMBOL: node-consume-d
 SYMBOL: node-produce-d
 SYMBOL: node-consume-r
index 347039ac6fdde431aca404ef26739c3dd8ef9037..9138c4a61d0071e12ce77a980b0d5ed63fccb7de 100644 (file)
@@ -37,6 +37,7 @@ USE: vectors
 USE: words
 USE: hashtables
 USE: generic
+USE: prettyprint
 
 ! Word properties that affect inference:
 ! - infer-effect -- must be set. controls number of inputs
@@ -166,7 +167,11 @@ DEFER: apply-word
 : infer-quot ( quot -- )
     #! Recursive calls to this word are made for nested
     #! quotations.
-    [ apply-object ] each ;
+    [
+        [ apply-object ] each
+    ] [
+        [ swap <chained-error> rethrow ] when*
+    ] catch ;
 
 : raise ( [ in | out ] -- [ in | out ] )
     uncons 2dup min tuck - >r - r> cons ;
@@ -201,7 +206,8 @@ DEFER: apply-word
 : check-return ( -- )
     #! Raise an error if word leaves values on return stack.
     meta-r get vector-length 0 = [
-        "Word leaves elements on return stack" throw
+        "Word leaves elements on return stack"
+        <chained-error> throw
     ] unless ;
 
 : values-node ( op -- )
diff --git a/library/inference/types.factor b/library/inference/types.factor
new file mode 100644 (file)
index 0000000..fefe236
--- /dev/null
@@ -0,0 +1,79 @@
+! :folding=indent:collapseFolds=1:
+
+! $Id$
+!
+! Copyright (C) 2004 Slava Pestov.
+! 
+! Redistribution and use in source and binary forms, with or without
+! modification, are permitted provided that the following conditions are met:
+! 
+! 1. Redistributions of source code must retain the above copyright notice,
+!    this list of conditions and the following disclaimer.
+! 
+! 2. Redistributions in binary form must reproduce the above copyright notice,
+!    this list of conditions and the following disclaimer in the documentation
+!    and/or other materials provided with the distribution.
+! 
+! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+IN: inference
+USE: errors
+USE: generic
+USE: interpreter
+USE: kernel
+USE: kernel-internals
+USE: lists
+USE: math
+USE: namespaces
+USE: strings
+USE: vectors
+USE: words
+USE: stdio
+
+! 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
+    ] [
+        value-class-and
+        dup "infer-effect" word-property consume/produce
+    ] ifte ;
+
+\ >cons [
+    \ >cons \ cons infer-check
+] "infer" set-word-property
+
+\ >vector [
+    \ >vector \ vector infer-check
+] "infer" set-word-property
+
+\ >string [
+    \ >string \ string infer-check
+] "infer" set-word-property
+
+\ slot [
+    dataflow-drop, pop-d literal-value
+    peek-d value-class builtin-supertypes dup length 1 = [
+        cons #slot dataflow, [
+            1 0 node-inputs
+            [ object ] consume-d
+            [ object ] produce-d
+            1 0 node-outputs
+        ] bind
+    ] [
+        "slot called without static type knowledge" throw
+    ] ifte
+] "infer" set-word-property
index 3e5c91b0952b541b9ee22292d8224c4a9c4ccd06..44e5a87b546ddb04284b649699450b995bf7dcae 100644 (file)
@@ -102,7 +102,11 @@ USE: parser
 : inline-compound ( word -- effect )
     #! Infer the stack effect of a compound word in the current
     #! inferencer instance.
-    gensym [ word-parameter infer-quot effect ] with-block ;
+    [
+        gensym [ word-parameter infer-quot effect ] with-block
+    ] [
+        [ swap <chained-error> rethrow ] when*
+    ] catch ;
 
 : (infer-compound) ( word -- effect )
     #! Infer a word's stack effect in a separate inferencer
index 127657fc2f68cbdd4d4391a41369b07d2f862bb9..d522d9e7edbfb53b5a7e02334d6f18ef72dcc078 100644 (file)
@@ -210,9 +210,13 @@ USE: words
     [ memory>string          " address length -- str "            [ [ integer integer ] [ string ] ] ]
     [ local-alien?           " alien -- ? "                       [ [ alien ] [ object ] ] ]
     [ alien-address          " alien -- address "                 [ [ alien ] [ integer ] ] ]
-    [ >cons                  " cons -- cons "                     [ [ cons ] [ cons ] ] ]
-    [ >vector                " vector -- vector "                 [ [ vector ] [ vector ] ] ]
-    [ >string                " string -- string "                 [ [ string ] [ string ] ] ]
+    ! Note: a correct type spec for these would have [ X ] as
+    ! input, not [ object ]. However, we rely on the inferencer
+    ! to handle these specially, since they are also optimized
+    ! out in some cases, etc.
+    [ >cons                  " cons -- cons "                     [ [ object ] [ cons ] ] ]
+    [ >vector                " vector -- vector "                 [ [ object ] [ vector ] ] ]
+    [ >string                " string -- string "                 [ [ object ] [ string ] ] ]
     [ >word                  " word -- word "                     [ [ word ] [ word ] ] ]
     [ slot                   " obj n -- obj "                     [ [ object fixnum ] [ object ] ] ]
     [ set-slot               " obj obj n -- "                     [ [ object object fixnum ] [ ] ] ]
index 5381e28ddf07ebf09f7dd6b210bdaf26540b7752..01af33435d3f26b6208cdc6b7bcd5647415b3cbd 100644 (file)
@@ -22,10 +22,8 @@ USE: generic
     [ 3 | 4 ]
 ] "effects" set
 
-[ 3 ] [ [ { 1 2 } { 1 2 3 } ] longest-vector ] unit-test
-
-[ t ] [
-    [ { 1 2 } { 1 2 3 } ] unify-lengths [ vector-length ] map all=?
+[ { f 1 2 } { 1 2 3 } ] [
+    { 1 2 } { 1 2 3 } unify-lengths
 ] unit-test
 
 [ [ sq ] ] [
@@ -214,6 +212,6 @@ SYMBOL: sym-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
+[ [ [ vector ] [ vector ] ] ] [ [ vector-clone ] infer ] unit-test
 ! [ [ [ number ] [ number ] ] ] [ [ dup + ] infer ] unit-test
 ! [ [ [ number number number ] [ number ] ] ] [ [ digit+ ] 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
index 5c4c2be505ff6c665bc4a861d641ce42adb57a94..4cb177480ecfe1201a45be90c286007367828f83 100644 (file)
@@ -5,6 +5,7 @@ USE: random
 USE: test
 USE: vectors
 USE: strings
+USE: namespaces
 
 [ [ t f t ] vector-length ] unit-test-fails
 [ 3 ] [ { t f t } vector-length ] unit-test
@@ -56,7 +57,7 @@ USE: strings
 unit-test
 
 [ { 6 8 10 12 } ]
-[ { 1 2 3 4 } { 5 6 7 8 } [ + ] vector-2map ]
+[ { 1 2 3 4 } { 5 6 7 8 } vector-zip [ uncons + ] vector-map ]
 unit-test
 
 [ { [ 1 | 5 ] [ 2 | 6 ] [ 3 | 7 ] [ 4 | 8 ] } ]
@@ -69,3 +70,15 @@ unit-test
 [ 2 [ ] vector-tail ] unit-test-fails
 
 [ [ 3 ] ] [ 1 { 1 2 3 } vector-tail* ] unit-test
+
+0 <vector> "funny-stack" set
+
+[ ] [ { 1 5 } "funny-stack" get vector-push ] unit-test
+[ ] [ { 2 3 } "funny-stack" get vector-push ] unit-test
+[ { 2 3 } ] [ "funny-stack" get vector-pop ] unit-test
+[ { 1 5 } ] [ "funny-stack" get vector-peek ] unit-test
+[ { 1 5 } ] [ "funny-stack" get vector-pop ] unit-test
+[ "funny-stack" get vector-pop ] unit-test-fails
+[ "funny-stack" get vector-pop ] unit-test-fails
+[ ] [ "funky" "funny-stack" get vector-push ] unit-test
+[ "funky" ] [ "funny-stack" get vector-pop ] unit-test
index e4d90dfe8a9636e076a00abccf3076733006ca07..e699fd4a76e7dca15624e79f9f34458046771aa3 100644 (file)
@@ -108,10 +108,10 @@ USE: generic
 GENERIC: error. ( error -- )
 
 PREDICATE: cons kernel-error ( obj -- ? )
-    uncons cons? swap fixnum? and ;
+    car kernel-error = ;
 
 M: kernel-error error. ( error -- )
-    uncons car swap {
+    cdr uncons car swap {
         expired-error
         io-task-twice-error
         no-io-tasks-error
@@ -207,7 +207,8 @@ M: object error. ( error -- )
 : init-error-handler ( -- )
     [ 1 exit* ] >c ( last resort )
     [ print-error 1 exit* ] >c
-    [ dup save-error rethrow ] 5 setenv ( kernel calls on error ) ;
+    [ dup save-error rethrow ] 5 setenv ( kernel calls on error )
+    kernel-error 12 setenv ;
 
 ! So that stage 2 boot gives a useful error message if something
 ! fails after this file is loaded.
index dab1671edce60634d10916f5d9e841c8589c52c8..80eadbffb2297de3a8ca35666f34bb55e7ee0834 100644 (file)
@@ -47,6 +47,7 @@ SYMBOL: meta-r
 SYMBOL: meta-d
 : push-d meta-d get vector-push ;
 : pop-d meta-d get vector-pop ;
+: peek-d meta-d get vector-peek ;
 SYMBOL: meta-n
 SYMBOL: meta-c
 
index 7919f0dfa998f6dd707f729a8a0d063cc2e5e916..a30d9ac760c4a7ce07bae8ce895272293caebc2c 100644 (file)
@@ -58,7 +58,7 @@ BUILTIN: vector 11
         "Vector length must be positive" throw 2drop
     ] [
         2dup (set-vector-length) grow-vector-array
-    ] ifte ;
+    ] ifte ; inline
 
 : empty-vector ( len -- vec )
     #! Creates a vector with 'len' elements set to f. Unlike
@@ -73,6 +73,10 @@ BUILTIN: vector 11
     #! Push a value on the end of a vector.
     dup vector-length swap set-vector-nth ;
 
+: vector-peek ( vector -- obj )
+    #! Get value at end of vector.
+    dup vector-length pred swap vector-nth ;
+
 : vector-pop ( vector -- obj )
     #! Get value at end of vector and remove it.
     dup vector-length pred ( vector top )
@@ -122,15 +126,6 @@ BUILTIN: vector 11
         pick pick >r over >r vector-nth r> r> vector-nth cons
     ] vector-project 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 ; inline
-
 : vector-clone ( vector -- vector )
     #! Shallow copy of a vector.
     [ ] vector-map ;
index 17de1d22b14ae832fb1f159da258a53bf95baee7..9e865f9aaceb69e0fd35ead8a53e21d16fbbaffb 100644 (file)
@@ -57,7 +57,7 @@ void primitive_throw(void)
 void general_error(CELL error, CELL tagged)
 {
        early_error(error);
-       throw_error(cons(error,cons(tagged,F)),true);
+       throw_error(cons(userenv[ERROR_ENV],cons(error,cons(tagged,F))),true);
 }
 
 /* It is not safe to access 'ds' from a signal handler, so we just not
@@ -65,7 +65,9 @@ touch it */
 void signal_error(int signal)
 {
        early_error(ERROR_SIGNAL);
-       throw_error(cons(ERROR_SIGNAL,cons(tag_fixnum(signal),F)),false);
+       throw_error(cons(userenv[ERROR_ENV],
+               cons(ERROR_SIGNAL,
+                       cons(tag_fixnum(signal),F))),false);
 }
 
 void type_error(CELL type, CELL tagged)
index 1033f23a0ddf9a21acee39b4824181853353cbcc..97331a143082871dc8e0afa2140c36020e927826 100644 (file)
@@ -12,6 +12,7 @@
 #define RUNQUEUE_ENV   9 /* used by library only */
 #define ARGS_ENV       10
 #define OS_ENV         11
+#define ERROR_ENV      12 /* a marker consed onto kernel errors */
 
 /* Profiling timer */
 #ifndef WIN32