]> gitweb.factorcode.org Git - factor.git/commitdiff
cleanup quicksort, thread safety fix
authorSlava Pestov <slava@factorcode.org>
Sun, 21 Nov 2004 08:29:18 +0000 (08:29 +0000)
committerSlava Pestov <slava@factorcode.org>
Sun, 21 Nov 2004 08:29:18 +0000 (08:29 +0000)
TODO.FACTOR.txt
doc/new-guide.tex
factor/ExternalFactor.java
factor/jedit/FactorPlugin.java
library/lists.factor
library/math/arithmetic.factor
library/test/inference.factor
library/test/lists/combinators.factor
library/tools/inference.factor

index 501f057df82e3df41f3f82891b1420f6daa71456..3d972a7acb9091760507b5573d179e7ff5920bc7 100644 (file)
@@ -1,6 +1,5 @@
 + 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
@@ -31,6 +30,7 @@
 \r
 + listener/plugin:\r
 \r
+- gracefully handle non-working cfactor\r
 - accept multi-line input in listener\r
 - don't show listener on certain commands\r
 - NPE in ErrorHighlight\r
 - jedit ==> jedit-word, jedit takes a file name\r
 - command line parsing cleanup\r
 - nicer way to combine two paths\r
-- :get &get\r
-- namestack, catchstack lists\r
+- catchstack lists\r
 - OOP\r
-- room. prints code heap size\r
 - refactor sort\r
 - ditch object paths\r
 - browser responder for word links in HTTPd; inspect responder for\r
index c5265fa4681ab37105093c77802cdb054596b5e3..883cc843594431b0a5618d2b4202b6fbc15dbdef 100644 (file)
@@ -899,17 +899,18 @@ Test if a value is a proper list.\\
 
 \section{The interpreter}
 
+\chapkeywords{acons >r r>}
 \index{\texttt{acons}}
 \index{\texttt{>r}}
 \index{\texttt{r>}}
 
 So far, we have seen what we called ``the stack'' store intermediate values between computations. In fact Factor maintains a number of other stacks, and the formal name for the stack we've been dealing with so far is the \emph{data stack}.
 
-Another fundamental stack is the \emph{call stack}. It is used to save interpreter state for nested calls.
+Another fundamental stack is the \emph{return stack}. It is used to save interpreter state for nested calls.
 
-You have probably noticed that code quotations are just lists. At a low level, each colon definition is also just a quotation. The interpreter consists of a loop that iterates a quotation, pushing each literal, and executing each word. If the word is a colon definition, the interpreter saves its state on the call stack, executes the definition of that word, then restores the execution state from the call stack and continues.
+You have probably noticed that code quotations are just lists. At a low level, each colon definition is also just a quotation. The interpreter consists of a loop that iterates a quotation, pushing each literal, and executing each word. If the word is a colon definition, the interpreter saves its state on the return stack, executes the definition of that word, then restores the execution state from the return stack and continues.
 
-The call stack also serves a dual purpose as a temporary storage area. Sometimes, juggling values on the data stack becomes ackward, and in that case \texttt{>r} and \texttt{r>} can be used to move a value from the data stack to the call stack, and vice versa, respectively.
+The return stack also serves a dual purpose as a temporary storage area. Sometimes, juggling values on the data stack becomes ackward, and in that case \texttt{>r} and \texttt{r>} can be used to move a value from the data stack to the return stack, and vice versa, respectively.
 
 A simple example can be found in the definition of the \texttt{acons} word:
 
@@ -929,9 +930,28 @@ Note that usages of \texttt{>r} and \texttt{r>} must be balanced within a single
 : the-ugly r> ;
 \end{verbatim}
 
-Basically, the rule is you must leave the call stack in the same state as you found it so that when the current quotation finishes executing, the interpreter can continue executing without seeing your data on the call stack.
+Basically, the rule is you must leave the return stack in the same state as you found it so that when the current quotation finishes executing, the interpreter can return to the calling word.
+
+One exception is that when \texttt{ifte} occurs as the last word in a definition, values may be pushed on the return stack before the condition value is computed, as long as both branches of the \texttt{ifte} pop the values off the return stack before returning.
+
+Lets review the words we saw in this chapter:
+
+\wordtable{
+\tabvocab{lists}
+\texttt{acons}&
+\texttt{( value key alist -{}- alist )}&
+Add a key/value pair to the association list.\\
+\tabvocab{stack}
+\texttt{>r}&
+\texttt{( obj -{}- r:obj )}&
+Move value to return stack..\\
+\texttt{r>}&
+\texttt{( r:obj -{}- obj )}&
+Move value from return stack..\\
+}
+
+\section{Word definitions}
 
-One exception is that when \texttt{ifte} occurs as the last word in a definition, values may be pushed on the call stack before the condition value is computed, as long as both branches of the \texttt{ifte} pop the values off the callstack before returning.
 
 \section{Recursive combinators}
 
@@ -1232,6 +1252,16 @@ BIN: 11111 -2 shift .b
 
 The attentive reader will notice that shifting to the left is equivalent to multiplying by a power of two, and shifting to the right is equivalent to performing a truncating division by a power of two.
 
+\chapter{Working with state}
+
+\section{Building lists and strings}
+
+\chapkeywords{make-string make-list ,}
+\index{\texttt{make-string}}
+\index{\texttt{make-list}}
+\index{\texttt{make-,}}
+
+
 \input{new-guide.ind}
 
 \end{document}
index c6022061d0c8028424b8287416b52bac1ee9e8a1..683ae9304d0165e340bf56eedb37068e3f896b45 100644 (file)
@@ -158,6 +158,15 @@ public class ExternalFactor extends DefaultVocabularyLookup
                {
                        /* don't care about response */
                        sendEval("0 exit*");
+               }
+               catch(Exception e)
+               {
+                       // We don't care...
+                       Log.log(Log.DEBUG,this,e);
+               }
+               
+               try
+               {
                        in.close();
                        out.close();
                }
index 4c75498215f30a0d90911617a6aa06815b2a6c7e..28a0d415ff6353192b2e01f0ddd6a5613ee275bd 100644 (file)
@@ -79,7 +79,7 @@ public class FactorPlugin extends EditPlugin
         * Returns the object representing a connection to an external Factor instance.
         * It will start the interpreter if it's not already running.
         */
-       public static ExternalFactor getExternalInstance()
+       public synchronized static ExternalFactor getExternalInstance()
                throws IOException, UnsupportedEncodingException
        {
                if(external == null)
index 3ac9fedfc068948a69283172413355280899ac22..c02013cf14d45e91fe3fc18f7411025670e4a298 100644 (file)
@@ -43,6 +43,8 @@ USE: vectors
     over [ >r uncons r> append cons ] [ nip ] ifte ;
 
 : contains? ( element list -- remainder )
+    #! Push remainder of list from first occurrence of element,
+    #! or f.
     dup [
         2dup car = [ nip ] [ cdr contains? ] ifte
     ] [
@@ -50,67 +52,54 @@ USE: vectors
     ] ifte ;
 
 : nth ( n list -- list[n] )
-    #! Push the nth element of a proper list.
+    #! nth element of a proper list.
     #! Supplying n <= 0 pushes the first element of the list.
     #! Supplying an argument beyond the end of the list raises
     #! an error.
     swap [ cdr ] times car ;
 
 : last* ( list -- last )
-    #! Pushes last cons of a list.
+    #! Last cons of a list.
     dup cdr cons? [ cdr last* ] when ;
 
 : last ( list -- last )
+    #! Last element of a list.
     last* car ;
 
+: tail ( list -- tail )
+    #! Return the cdr of the last cons cell, or f.
+    dup [ last* cdr ] when ;
+
 : list? ( list -- ? )
     #! Proper list test. A proper list is either f, or a cons
     #! cell whose cdr is a proper list.
-    dup [
-        dup cons? [ cdr list? ] [ drop f ] ifte
-    ] [
-        drop t
-    ] ifte ;
+    dup cons? [ tail ] when not ;
 
 : partition-add ( obj ? ret1 ret2 -- ret1 ret2 )
-    >r >r [ r> cons r> ] [ r> swap r> cons ] ifte ; inline
+    rot [ >r cons r> ] [ swapd cons ] ifte ; inline
 
-: partition-step ( ret1 ret2 ref combinator car -- ret1 ret2 )
-    >r rot >r rot r> r> -rot >r >r dup >r swap call r> swap r> r>
-    partition-add ; inline
+: partition-step ( list combinator -- cdr combinator car ? )
+    over car over call >r >r unswons r> swap r> ; inline
 
-: partition-iter ( ret1 ret2 ref combinator list -- ret1 ret2 )
-    dup [
-        3dup cdr >r >r >r
-        car partition-step
-        r> r> r> partition-iter
+: (partition) ( list combinator ret1 ret2 -- ret1 ret2 )
+    >r >r  over [
+        partition-step  r> r> partition-add  (partition)
     ] [
-        3drop
+        2drop  r> r>
     ] ifte ; inline
 
-: partition ( ref list combinator -- list1 list2 )
-    #! Compare each element in a proper list against a
-    #! reference element using a combinator. The combinator's
-    #! return value determines if the element is prepended to
-    #! the first or second list.
+: partition ( list ref combinator -- list1 list2 )
     #! The combinator must have stack effect:
     #! ( ref element -- ? )
-    swap >r >r >r [ ] [ ] r> r> r> partition-iter ;
-    inline
+    cons [ ] [ ] (partition) ; inline
 
 : sort ( list comparator -- sorted )
-    #! Sort the elements in a proper list using a comparator.
-    #! The comparator must have stack effect:
-    #! ( x y -- ? )
-    #! To sort elements in descending order, return t if x < y.
-    #! To sort elements in ascending order, return t if x > y.
+    #! To sort in ascending order, comparator must have stack
+    #! effect ( x y -- x>y ).
     over [
-        ! Partition
-        dup >r >r uncons dupd r> partition r>
-        ! Recurse
-        tuck sort >r sort swap r>
-        ! Combine
-        cons append
+        ( Partition ) [ >r uncons over r> partition ] keep
+        ( Recurse ) [ sort swap ] keep sort
+        ( Combine ) swapd cons append
     ] [
         drop
     ] ifte ; inline
index 57d7feaa5264b92d99acb352c3f689f6c8f22eaf..ead58048c8cfaf8697552597537b080e0c1964ac 100644 (file)
@@ -57,7 +57,7 @@ USE: stack
     #! by swapping them.
     2dup > [ swap ] when  >r dupd max r> min = ;
 
-: sq dup * ; inline recursive-infer
+: sq dup * ; inline
 
 : pred 1 - ; inline
 : succ 1 + ; inline
index 47c968c1cb5fd655a2c5a4aeec75beb5e8c60a41..c18df6452194d974a046d24dbbc2fb85e4d4f070 100644 (file)
@@ -146,5 +146,17 @@ DEFER: foe
 [ [ 2 | 1 ] ] [ [ /i ] infer ] unit-test
 [ [ 2 | 1 ] ] [ [ /f ] infer ] unit-test
 [ [ 2 | 2 ] ] [ [ /mod ] infer ] unit-test
-
+[ [ 2 | 1 ] ] [ [ + ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ - ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ * ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ / ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ < ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ <= ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ > ] infer ] unit-test
+[ [ 2 | 1 ] ] [ [ >= ] infer ] unit-test
 [ [ 2 | 1 ] ] [ [ number= ] infer ] unit-test
+
+[ [ 2 | 1 ] ] [ [ = ] infer ] unit-test
+
+[ [ 1 | 0 ] ] [ [ >n ] infer ] unit-test
+[ [ 0 | 1 ] ] [ [ n> ] infer ] unit-test
index 4bd37cdac8ae0ab0301d6fd0d0c9bf272fdbe680..d2545f446feb48ab5d769cbd9563c647b603e430 100644 (file)
@@ -19,6 +19,9 @@ USE: strings
 
 [ [ 43 "a" [ ] ] ] [ [ "a" 43 43 43 [ ] 43 "a" [ ] ] prune ] unit-test
 
+[ "fdsfs" num-sort ] unit-test-fails
+[ [ ] ] [ [ ] num-sort ] unit-test
+[ [ "2 + 2" ] ] [ [ "2 + 2" ] [ str-lexi> ] sort ] 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
index 0a11f77d7376012c7accca8f801018df7eb3077b..011ce1dab2ece386cc83fbe051ce29f329be58db 100644 (file)
@@ -43,7 +43,6 @@ USE: hashtables
 ! Word properties that affect inference:
 ! - infer-effect -- must be set. controls number of inputs
 ! expected, and number of outputs produced.
-! - meta-infer -- evaluate word in meta-interpreter if set.
 ! - infer - quotation with custom inference behavior; ifte uses
 ! this. Word is passed on the stack.
 ! - recursive-infer - if true, inferencer will always invoke
@@ -92,24 +91,16 @@ SYMBOL: entry-effect
 : consume/produce ( [ in | out ] -- )
     unswons dup ensure-d consume-d produce-d ;
 
-: standard-effect ( word [ in | out ] -- )
+: apply-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
-    ] [
-        nip consume/produce
-    ] ifte ;
-
-: apply-effect ( word [ in | out ] -- )
-    #! Helper word for apply-word.
     dup car ensure-d
-    over "infer" word-property dup [
-        nip nip call
+    swap "infer" word-property dup [
+        nip call
     ] [
-        drop standard-effect
+        drop consume/produce
     ] ifte ;
 
 : no-effect ( word -- )
@@ -301,6 +292,10 @@ DEFER: (infer)
     #! Stack effect of a quotation.
     [ init-inference (infer)  effect ] with-scope ;
 
+: meta-infer ( word -- )
+    #! Mark a word as being partially evaluated.
+    dup unit [ car meta-word ] cons  "infer" set-word-property ;
+
 \ call [ pop-d (infer) ] "infer" set-word-property
 \ ifte [ infer-ifte ] "infer" set-word-property
 
@@ -313,11 +308,16 @@ DEFER: (infer)
 \ >r [ pop-d push-r ] "infer" set-word-property
 \ r> [ pop-r push-d ] "infer" set-word-property
 
-\ drop  t "meta-infer" set-word-property
-\ dup  t "meta-infer" set-word-property
-\ swap t "meta-infer" set-word-property
-\ over t "meta-infer" set-word-property
-\ pick t "meta-infer" set-word-property
-\ nip t "meta-infer" set-word-property
-\ tuck t "meta-infer" set-word-property
-\ rot t "meta-infer" set-word-property
+\ drop meta-infer
+\ dup meta-infer
+\ swap meta-infer
+\ over meta-infer
+\ pick meta-infer
+\ nip meta-infer
+\ tuck meta-infer
+\ rot meta-infer
+
+\ + [ 2 | 1 ] "infer-effect" set-word-property
+\ - [ 2 | 1 ] "infer-effect" set-word-property
+\ * [ 2 | 1 ] "infer-effect" set-word-property
+\ / [ 2 | 1 ] "infer-effect" set-word-property