]> gitweb.factorcode.org Git - factor.git/commitdiff
Factor 0.71 is ready factor-0-71
authorSlava Pestov <slava@factorcode.org>
Sun, 2 Jan 2005 21:22:11 +0000 (21:22 +0000)
committerSlava Pestov <slava@factorcode.org>
Sun, 2 Jan 2005 21:22:11 +0000 (21:22 +0000)
doc/devel-guide.tex
doc/generic.txt [new file with mode: 0644]
factor/ExternalFactor.java

index 3fc2bcaad813f885471952fc3a2d5ea22606f3d3..c5ae07901dcd0590b12a08427e5ff397e1b45ed4 100644 (file)
@@ -334,12 +334,7 @@ matters (\texttt{-} and \texttt{/}), the operands are taken in the natural order
 \textbf{111}
 \end{alltt}
 
-The \texttt{neg} unary operator negates the number at the top of the stack (that is, multiplies it by -1). Two unary operators \texttt{pred} and \texttt{succ} subtract 1 and add 1, respectively, to the number at the top of the stack.
-
-\begin{alltt}
-\textbf{ok} 5 pred pred succ neg .
-\textbf{-4}
-\end{alltt}
+The \texttt{neg} word negates the number at the top of the stack (that is, multiplies it by -1). 
 
 This type of arithmetic is called \emph{postfix}, because the operator
 follows the operands. Contrast this with \emph{infix} notation used
diff --git a/doc/generic.txt b/doc/generic.txt
new file mode 100644 (file)
index 0000000..224deb1
--- /dev/null
@@ -0,0 +1,272 @@
+THE FACTOR GENERIC WORD SYSTEM
+
+Factor's generic word system is a very abstract generalization of
+"object oriented" features found in other programming languges.
+
+To use the generic word system, you must put the following near the
+beginning of your source file:
+
+USE: generic
+
+The key motivation is that sometimes, you want to write a word that has
+differing behavior depending on the class of its argument. For example,
+in a game, a 'draw' word could take different action if given a ship, a
+weapon, a planet, etc.
+
+Duplicating 'type case' logic is undesirable and also results in
+unnecessary coupling -- adding support for a new type of graphical
+object would require modifying the original definition of 'draw', for
+example.
+
+* Types
+
+In Factor, the idea of a 'type' refers to a very concrete concept. The
+type of an object is its representation in runtime object memory. Types
+include fixnums, bignums, cons cells, vectors, strings, and so on. The
+set of available types is fixed; adding a new type requires modifying
+the runtime source written in C.
+
+* Classes
+
+In Factor, a 'class' is just a predicate that categorizes objects as
+being a member of the class or not. To be useful, it must be consistent
+-- for a given object, it must always return the same truth value.
+
+Examples of classes might include:
+
+- Cons cells where both elements are integers
+
+- Floating point numbers between -1 and 1
+
+- Hash tables holding a certain key
+
+- Any object that occurs as a member of a certain global variable
+holding a list.
+
+- ... and so on.
+
+As you can see, a class of objects does not need to be a subset or a
+superset of a type of objects.
+
+Classes, unlike types, can be defined by the user.
+
+* Generic words
+
+A generic word is a word whose behavior depends on the class of the
+object at the top of the stack.
+
+Generic words are defined using the following syntax:
+
+GENERIC: draw ( actor -- )
+#! Draw the actor.
+
+A stack effect comment, as above, is not required but recommended.
+
+* Methods
+
+A method associates behavior to a generic word. Methods are defined by
+writing M:, followed by a class name, followed by the name of a
+previously-defined generic word.
+
+One of the main benefits of generic words is that each method definition
+can potentially occur in a different source file. Generic word
+definitions also hide conditionals.
+
+Here are two methods for the generic 'draw' word:
+
+M: ship draw ( actor -- )
+    [
+        surface get screen-xy radius get color get
+        filledCircleColor
+    ] bind ;
+
+M: plasma draw ( actor -- )
+    [
+        surface get screen-xy dup len get + color get
+        vlineColor
+    ] bind ;
+
+Here, 'ship' and 'class' are user-defined classes.
+
+* Metaclasses
+
+To understand what classes already exist, and how to define your own
+classes, the concept of a 'metaclass' must be grasped first. Roughly
+speaking, a metaclass is a class of classes.
+
+New metaclasses can be defined by the user, but its an involved process
+that requires a deeper understanding of the generic word systsem than
+can be given here.
+
+** The object class
+
+Every object is a member of the object class. The object class is also a
+metaclass, and it is the one and only instance of itself.
+
+Confusing? The idea is pretty simple. If you define a method on
+'object', it will be called when no more specific method is available:
+
+GENERIC: describe
+M: number describe "The number " write . ;
+M: object describe "I don't know anything about " write . ;
+
+Since the only instance of the object metaclass is itself, you cannot
+define new classes in the object metaclass.
+
+** The builtin metaclass
+
+The builtin metaclass contains precisely the following classes; each
+class corresponds to a runtime type:
+
+alien
+array
+bignum
+complex
+cons
+dll
+f
+fixnum
+float
+port
+ratio
+sbuf
+string
+t
+vector
+word
+
+Each builtin class has a corresponding membership test predicate, named
+after the builtin class suffixed with '?'. For example, cons?, word?,
+etc.
+
+Adding new classes to the builtin metaclass requires modifications to
+the C code comprising Factor's runtime.
+
+** The union metaclass
+
+The union metaclass contains classes whose members are defined to be the
+aggregate of the members of a list of existing classes.
+
+For example, the Factor library defines some unions over numeric types:
+
+UNION: integer fixnum bignum ;
+UNION: rational integer ratio ;
+UNION: real rational float ;
+UNION: number real complex ;
+
+Now, the absolute value function can be defined in an efficient manner
+for real numbers, and in a more general fashion for complex numbers:
+
+GENERIC: abs ( z -- |z| )
+M: real abs dup 0 < [ neg ] when ;
+M: complex abs >rect mag2 ;
+
+New unions can be defined by you, and the numerical types example above
+gives the syntax: you write UNION: followed by the name of the union,
+followed by its members. The list of members is terminated with a
+semi-colon.
+
+A predicate named after the union followed by '?' is
+automatically-defined. For example, the following definition of 'real?'
+was automatically created:
+
+: real?
+    dup rational? [
+        drop t 
+    ] [
+        dup float? [
+            drop t 
+        ] [
+            drop f 
+        ] ifte 
+    ] ifte ;
+
+** The predicate metaclass
+
+The predicate metaclass contains classes whose membership test is an
+arbitrary expression. To speed up dispatch, each predicate must be
+defined as a subclass of some other class. That way predicates
+subclassing from disjoint builtin classes do not need to be
+simultaenously tested.
+
+The library/strings.factor module defines some subclasses of integer,
+classifying the different types of ASCII characters:
+
+PREDICATE: integer blank     " \t\n\r" str-contains? ;
+PREDICATE: integer letter    CHAR: a CHAR: z between? ;
+PREDICATE: integer LETTER    CHAR: A CHAR: Z between? ;
+PREDICATE: integer digit     CHAR: 0 CHAR: 9 between? ;
+PREDICATE: integer printable CHAR: \s CHAR: ~ between? ;
+
+Each predicate defines a corresponding predicate word whose name is
+suffixed with '?'; for example, a 'digit?' word is automatically
+defined:
+
+: digit?
+    dup integer? [
+        CHAR: 0 CHAR: 9 between?
+    ] [
+        drop f
+    ] ifte ;
+
+For obvious reasons, the predicate definition must consume and produce
+exactly one value on the stack.
+
+** The traits metaclass
+
+(The name for this metaclass is wrong and will change eventually. The
+original idea was to allow an object to inherit any number of 'traits',
+thus they would behave like mixins. This never materialized.)
+
+The traits metaclass allows one to associate more fine-grained behavior,
+specifically with hashtables.
+
+New classes can be defined like so:
+
+TRAITS: plasma
+
+In terms of behavior, this is actually identical to the following:
+
+PREDICATE: hashtable plasma \ traits swap hash plasma = ;
+
+However, it is far more efficient (and less verbose).
+
+You can define methods as usual:
+
+GENERIC: collide ( actor1 actor2 -- )
+
+M: plasma collide ( actor1 actor2 -- )
+    #! Remove the other actor.
+    deactivate deactivate ;
+
+How does one actually get an object that plasma? responds with t to? You
+define a constructor word by writing C: followed by the class name:
+
+C: plasma ( actor dy -- plasma )
+    [
+        velocity set
+        actor-xy
+        blue color set
+        10 len set
+        5 radius set
+        active on
+    ] extend ;
+
+The constructor word is named after the class, surrounded in angle
+brackets (< and >). For example, the above actually creates a word named
+<plasma>.
+
+The constructor's definition begins with the parameters given by the
+user, underneath a blank plasma object.
+
+That is, a dummy constructor just returns a blank hashtable that
+responds t to the corresponding membership predicate:
+
+TRAITS: foo
+C: foo ;
+
+<foo> foo? .
+==> t
+
+"hello" foo? .
+==> f
index 69708e5f63266b4514f13c6637fac35bdc2620e6..ec969e9f644a92c225d99a8021fed4a263719559 100644 (file)
@@ -89,7 +89,7 @@ public class ExternalFactor extends DefaultVocabularyLookup
                out.write("USE: jedit wire-server\n".getBytes("ASCII"));
                out.flush();
                waitForAck();
-       }
+       } //}}}
 
        //{{{ waitForAck() method
        private void waitForAck() throws IOException
@@ -104,6 +104,7 @@ public class ExternalFactor extends DefaultVocabularyLookup
                        byte[] discard = new byte[2048];
                        int len = in.read(discard,0,discard.length);
                        discardStr = new String(discard,0,len);
+                       Log.log(Log.DEBUG,this,"Waiting for ACK: " + discardStr);
                }
        } //}}}