]> gitweb.factorcode.org Git - factor.git/commitdiff
more progress on generic words
authorSlava Pestov <slava@factorcode.org>
Sun, 12 Dec 2004 21:32:47 +0000 (21:32 +0000)
committerSlava Pestov <slava@factorcode.org>
Sun, 12 Dec 2004 21:32:47 +0000 (21:32 +0000)
factor/DefaultVocabularyLookup.java
factor/FactorReader.java
factor/jedit/RestartableFactorScanner.java
factor/parser/BeginConstructor.java [new file with mode: 0644]
factor/parser/BeginMethod.java
factor/parser/EndMethod.java [deleted file]
factor/parser/In.java
factor/parser/Traits.java
library/generic.factor
library/test/generic.factor

index 988a624df9bd62466513636756f26d6c827b103c..98386a7d485b0cba0f007ab6d9af839e81ceae62 100644 (file)
@@ -120,9 +120,9 @@ public class DefaultVocabularyLookup implements VocabularyLookup
                FactorWord traits = define("generic","TRAITS:");
                traits.parsing = new Traits(traits);
                FactorWord beginMethod = define("generic","M:");
-               beginMethod.parsing = new BeginMethod(beginMethod);
-               FactorWord endMethod = define("generic",";M");
-               endMethod.parsing = new EndMethod(beginMethod,endMethod);
+               beginMethod.parsing = new BeginMethod(beginMethod,def);
+               FactorWord beginConstructor = define("generic","C:");
+               beginConstructor.parsing = new BeginConstructor(beginConstructor,def);
        } //}}}
 
        //{{{ getVocabulary() method
index 3f4a16298d51fd547a5b083dbfc986669c886034..d2cc137f2637c6a556d379ad9458c9c4b225a58a 100644 (file)
@@ -346,7 +346,7 @@ public class FactorReader
        public void pushExclusiveState(FactorWord start, FactorWord defining)
                throws FactorParseException
        {
-               if(states != null && getCurrentState().start != toplevel)
+               if(getCurrentState().start != toplevel)
                        scanner.error(start + " cannot be nested");
                pushState(start,defining);
        } //}}}
@@ -371,7 +371,8 @@ public class FactorReader
                ParseState state = getCurrentState();
                if(state.start != start)
                        scanner.error(end + " does not close " + state.start);
-               states = states.next();
+               if(states.next() != null)
+                       states = states.next();
                return state;
        } //}}}
 
index 67d5e511f32e9949576922b9ba1d83d3f59a9db4..0779edc523666552fbee10aa89cd9c06f12a938f 100644 (file)
@@ -50,7 +50,8 @@ public class RestartableFactorScanner extends FactorScanner
        {
                String line = getLine();
                int col = getColumnNumber();
-               if(getReadTable().getCharacterType(line.charAt(col - 1))
+               if(line != null &&
+                       getReadTable().getCharacterType(line.charAt(col - 1))
                        == ReadTable.WHITESPACE)
                {
                        col--;
diff --git a/factor/parser/BeginConstructor.java b/factor/parser/BeginConstructor.java
new file mode 100644 (file)
index 0000000..5390d79
--- /dev/null
@@ -0,0 +1,53 @@
+/* :folding=explicit: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.
+ */
+
+package factor.parser;
+
+import factor.*;
+
+public class BeginConstructor extends FactorParsingDefinition
+{
+       private FactorWord colon;
+
+       public BeginConstructor(FactorWord word, FactorWord colon)
+       {
+               super(word);
+               this.colon = colon;
+       }
+
+       public void eval(FactorReader reader)
+               throws Exception
+       {
+               FactorWord type = reader.nextWord(false);
+               if(type == null)
+                       return;
+
+               reader.pushExclusiveState(colon,type);
+       }
+}
index 9271e913b85decc3c2d2686138481e11831375b8..24a54aeab7bf73a77c6b97d0d660419153029465 100644 (file)
@@ -33,15 +33,18 @@ import factor.*;
 
 public class BeginMethod extends FactorParsingDefinition
 {
-       public BeginMethod(FactorWord word)
+       private FactorWord colon;
+
+       public BeginMethod(FactorWord word, FactorWord colon)
        {
                super(word);
+               this.colon = colon;
        }
 
        public void eval(FactorReader reader)
                throws Exception
        {
-               FactorWord type = reader.nextWord(true);
+               FactorWord type = reader.nextWord(false);
                if(type == null)
                        return;
 
@@ -49,6 +52,6 @@ public class BeginMethod extends FactorParsingDefinition
                if(generic == null)
                        return;
 
-               reader.pushExclusiveState(word,generic);
+               reader.pushExclusiveState(colon,generic);
        }
 }
diff --git a/factor/parser/EndMethod.java b/factor/parser/EndMethod.java
deleted file mode 100644 (file)
index 763db97..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* :folding=explicit: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.
- */
-
-package factor.parser;
-
-import factor.*;
-
-public class EndMethod extends FactorParsingDefinition
-{
-       public FactorWord start;
-
-       public EndMethod(FactorWord start, FactorWord end)
-       {
-               super(end);
-               this.start = start;
-       }
-
-       public void eval(FactorReader reader)
-               throws Exception
-       {
-               FactorReader.ParseState state = reader.popState(start,word);
-               FactorWord w = state.defining;
-               /* Only ever null with restartable scanner;
-               error already logged, so give up */
-               if(w == null)
-                       return;
-
-               w.def = new FactorMethodDefinition(null,w,state.first);
-               reader.append(w.def);
-       }
-}
index c092c2216c097741e6af0e6b5926d9ea635cc9d7..e41de2a7a5be79d8a8918661444ae7bef933552e 100644 (file)
@@ -33,16 +33,11 @@ import factor.*;
 
 public class In extends FactorParsingDefinition
 {
-       //{{{ In constructor
-       /**
-        * A new definition.
-        */
        public In(FactorWord word)
        {
                super(word);
-       } //}}}
+       }
 
-       //{{{ eval() method
        public void eval(FactorReader reader)
                throws Exception
        {
@@ -50,5 +45,5 @@ public class In extends FactorParsingDefinition
 
                reader.setIn(next);
                reader.addUse(next);
-       } //}}}
+       }
 }
index 2bb7286cd34cf1d3845a07773a1f5f7374d7a9f6..ae9aa7ea007a78ed9b7e785723a1ca1802242fa1 100644 (file)
@@ -43,6 +43,8 @@ public class Traits extends FactorParsingDefinition
        {
                FactorWord w = reader.nextWord(true);
                w.def = new FactorTraitsDefinition(w);
+               reader.intern("<" + w.name + ">",true);
+               reader.intern(w.name + "?",true);
                reader.append(w.def);
        }
 }
index 3c625e705c4275032f49fb908640e3b88de261aa..fd4c7d8a84388a6f9ef145d3389b9309b6abd6c9 100644 (file)
@@ -26,7 +26,6 @@
 ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 IN: generic
-
 USE: errors
 USE: hashtables
 USE: kernel
@@ -39,18 +38,43 @@ USE: vectors
 
 ! A simple single-dispatch generic word system.
 
+! Catch-all metaclass for providing a default method.
+SYMBOL: object
+
+: define-generic ( word vtable -- )
+    2dup "vtable" set-word-property
+    [ generic ] cons define-compound ;
+
+: <vtable> ( default -- vtable )
+    num-types [ drop dup ] vector-project nip ;
+
+: define-object ( generic definition -- )
+    <vtable> define-generic drop ;
+
+object [ define-object ] "define-method" set-word-property
+
 : predicate-word ( word -- word )
     word-name "?" cat2 "in" get create ;
 
-: builtin-predicate ( symbol type# -- )
-    [ swap type eq? ] cons >r predicate-word r> define-compound ;
+: builtin-predicate ( type# symbol -- )
+    predicate-word swap [ swap type eq? ] cons define-compound ;
+
+: add-method ( definition type vtable -- )
+    >r "builtin-type" word-property r> set-vector-nth ;
+
+: define-builtin ( type generic definition -- )
+    -rot "vtable" word-property add-method ;
+
+: builtin-class ( number type -- )
+    dup undefined? [ dup define-symbol ] when
+    2dup builtin-predicate
+    dup [ define-builtin ] "define-method" set-word-property
+    swap "builtin-type" set-word-property ;
 
 : BUILTIN:
     #! Followed by type name and type number. Define a built-in
     #! type predicate with this number.
-    CREATE dup undefined? [ dup define-symbol ] when scan-word
-    2dup builtin-predicate
-    "builtin-type" set-word-property ; parsing
+    CREATE scan-word swap builtin-class ; parsing
 
 : builtin-type ( symbol -- n )
     "builtin-type" word-property ;
@@ -100,22 +124,18 @@ SYMBOL: delegate
     traits-map [ swap object-map eq? ] cons
     define-compound ;
 
+: define-traits ( type generic definition -- )
+    swap rot traits-map set-hash ;
+
 : TRAITS:
     #! TRAITS: foo creates a new traits type. Instances can be
     #! created with <foo>, and tested with foo?.
     CREATE
     dup define-symbol
     dup init-traits-map
+    dup [ define-traits ] "define-method" set-word-property
     traits-predicate ; parsing
 
-: add-method ( quot class vtable -- )
-    >r "builtin-type" word-property r>
-    set-vector-nth ;
-
-: <vtable> ( word -- vtable )
-    num-types [ drop [ undefined-method ] ] vector-project
-    [ "vtable" set-word-property ] keep ;
-
 : add-traits-dispatch ( word vtable -- )
     >r unit [ car swap traits-method call ] cons \ vector r>
     add-method ;
@@ -124,18 +144,14 @@ SYMBOL: delegate
     #! GENERIC: bar creates a generic word bar that calls the
     #! bar method on the traits object, with the traits object
     #! on the stack.
-    CREATE dup <vtable> 2dup add-traits-dispatch
-    [ generic ] cons define-compound ; parsing
+    CREATE [ undefined-method ] <vtable>
+    2dup add-traits-dispatch
+    define-generic ; parsing
 
 : constructor-word ( word -- word )
     word-name "<" swap ">" cat3 "in" get create ;
 
-: define-constructor ( word -- )
-    [ constructor-word [ <namespace> ] ] keep
-    traits-map [ traits pick set-hash ] cons append
-    define-compound ;
-
-: (;C) ( constructor traits definition -- )
+: define-constructor ( constructor traits definition -- )
     >r
     traits-map [ traits pick set-hash ] cons \ <namespace> swons
     r> append define-compound ;
@@ -143,19 +159,17 @@ SYMBOL: delegate
 : C: ( -- constructor traits [ ] )
     #! C: foo ... begins definition for <foo> where foo is a
     #! traits type.
-    scan-word [ constructor-word ] keep [ (;C) ] [ ] ; parsing
+    scan-word [ constructor-word ] keep
+    [ define-constructor ] [ ] ; parsing
 
-: (;M) ( type generic definition -- )
-    pick builtin-type [
-        rot "builtin-type" word-property
-        rot "vtable" word-property
-        set-vector-nth
-    ] [
-        rot traits-map [ put ] bind
-    ] ifte ;
+: define-method ( type -- quotation )
+    #! In a vain attempt at something resembling a "meta object
+    #! protocol", we call the "define-method" word property with
+    #! stack ( type generic definition -- ).
+    "define-method" word-property
+    [ [ undefined-method ] ] unless* ;
 
 : M: ( -- type generic [ ] )
     #! M: foo bar begins a definition of the bar generic word
     #! specialized to the foo type.
-    scan-word scan-word [ (;M) ] [ ] ;
-    parsing
+    scan-word  dup define-method  scan-word swap [ ] ; parsing
index c642aca08245be9155de6c79678c6b8f4285c67f..62f8f14b5d3731b1dffd2c48444729b2b255766a 100644 (file)
@@ -4,6 +4,9 @@ USE: namespaces
 USE: generic
 USE: test
 USE: kernel
+USE: math
+USE: words
+USE: lists
 
 TRAITS: test-traits
 C: test-traits ;
@@ -56,3 +59,21 @@ TRAITS: del2
 C: del2 ( delegate -- del2 ) [ delegate set ] extend ;
 
 [ 5 ] [ <del1> <del2> super ] unit-test
+
+GENERIC: class-of
+
+M: fixnum class-of drop "fixnum" ;
+M: word   class-of drop "word"   ;
+M: cons   class-of drop "cons"   ;
+
+[ "fixnum" ] [ 5 class-of ] unit-test
+[ "cons" ] [ [ 1 2 3 ] class-of ] unit-test
+[ "word" ] [ \ class-of class-of ] unit-test
+[ 3.4 class-of ] unit-test-fails
+
+GENERIC: foobar
+M: object foobar drop "Hello world" ;
+M: fixnum foobar drop "Goodbye cruel world" ;
+
+[ "Hello world" ] [ 4 foobar foobar ] unit-test
+[ "Goodbye cruel world" ] [ 4 foobar ] unit-test