more unittests (already found/fixed some bugs)



git-svn-id: http://skia.googlecode.com/svn/trunk@348 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/forth/ForthParser.h b/forth/ForthParser.h
index 9c939f8..65a39a1 100644
--- a/forth/ForthParser.h
+++ b/forth/ForthParser.h
@@ -2,6 +2,7 @@
 #define ForthParser_DEFINED
 
 #include "SkTDict.h"
+//#include "SkString.h"
 
 class ForthWord;
 class FCode;
@@ -18,6 +19,8 @@
     }
 
     void add(const char name[], size_t len, ForthWord* word) {
+    //    SkString str(name, len);
+    //    SkDebugf("add %s %p\n", str.c_str(), word);
         (void)fDict.set(name, len, word);
     }
 
diff --git a/forth/ForthTests.cpp b/forth/ForthTests.cpp
index e918329..91ffaec 100644
--- a/forth/ForthTests.cpp
+++ b/forth/ForthTests.cpp
@@ -132,6 +132,198 @@
     FORTH_ASSERT(reporter, 2 == fe->peek(0));
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
+static void iadd_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(35);
+    fe->push(99);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 134 == fe->top());
+    fe->push(-135);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, -1 == fe->top());
+}
+
+static void isub_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(35);
+    fe->push(99);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 35-99 == fe->top());
+}
+
+static void imul_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(15);
+    fe->push(-20);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, -300 == fe->top());
+    fe->push(0);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 0 == fe->top());
+}
+
+static void idiv_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(100);
+    fe->push(25);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 4 == fe->top());
+    fe->setTop(10);
+    fe->push(-3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, -3 == fe->top());
+    fe->setTop(-1);
+    fe->push(-1);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->top());
+}
+
+static void imod_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    fe->push(3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->top());
+    fe->push(5);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->top());
+}
+
+static void idivmod_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    fe->push(3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 2 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->peek(1));
+    FORTH_ASSERT(reporter, 3 == fe->peek(0));
+}
+
+static void idot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->top());
+}
+
+static void iabs_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 10 == fe->top());
+    fe->setTop(-10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 10 == fe->top());
+}
+
+static void inegate_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, -10 == fe->top());
+    fe->setTop(-10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 10 == fe->top());
+}
+
+static void imin_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    fe->push(3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 3 == fe->top());
+    fe->push(-10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, -10 == fe->top());
+}
+
+static void imax_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    fe->push(3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 10 == fe->top());
+    fe->push(-10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 10 == fe->top());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void logical_and_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    const static int data[] = {
+        0, 0, 0,
+        2, 0, 0,
+        0, -1, 0,
+        1, 5, -1
+    };
+    for (size_t i = 0; i < SK_ARRAY_COUNT(data)/3; i++) {
+        fe->push(data[i*3 + 0]);
+        fe->push(data[i*3 + 1]);
+        word->exec(fe);
+        FORTH_ASSERT(reporter, 1 == fe->depth());
+        FORTH_ASSERT(reporter, data[i*3 + 2] == fe->top());
+        fe->pop();
+    }
+}
+
+static void logical_or_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    const static int data[] = {
+        0, 0, 0,
+        2, 0, -1,
+        0, -1, -1,
+        1, 5, -1
+    };
+    for (size_t i = 0; i < SK_ARRAY_COUNT(data)/3; i++) {
+        fe->push(data[i*3 + 0]);
+        fe->push(data[i*3 + 1]);
+        word->exec(fe);
+        FORTH_ASSERT(reporter, 1 == fe->depth());
+        FORTH_ASSERT(reporter, data[i*3 + 2] == fe->top());
+        fe->pop();
+    }
+}
+
+static void logical_not_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    const static int data[] = {
+        0, -1,
+        5, 0,
+        -1, 0
+    };
+    for (size_t i = 0; i < SK_ARRAY_COUNT(data)/2; i++) {
+        fe->push(data[i*2 + 0]);
+        word->exec(fe);
+        FORTH_ASSERT(reporter, 1 == fe->depth());
+        FORTH_ASSERT(reporter, data[i*2 + 1] == fe->top());
+        fe->pop();
+    }
+}
+
+static void if_dup_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(10);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 2 == fe->depth());
+    FORTH_ASSERT(reporter, 10 == fe->peek(1));
+    FORTH_ASSERT(reporter, 10 == fe->peek(0));
+    fe->pop();
+    fe->pop();
+    fe->push(0);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, 0 == fe->top());
+}
+
 static const struct {
     const char*         fName;
     ForthWordTestProc   fProc;
@@ -146,6 +338,24 @@
     { "2DUP",   dup2_test },
     { "2OVER",  over2_test },
     { "2DROP",  drop2_test },
+
+    { "+",      iadd_test },
+    { "-",      isub_test },
+    { "*",      imul_test },
+    { "/",      idiv_test },
+    { "MOD",    imod_test },
+    { "/MOD",   idivmod_test },
+
+//    { ".",      idot_test },
+    { "ABS",    iabs_test },
+    { "NEGATE", inegate_test },
+    { "MIN",    imin_test },
+    { "MAX",    imax_test },
+
+    { "AND",    logical_and_test },
+    { "OR",     logical_or_test },
+    { "0=",     logical_not_test },
+    { "?DUP",   if_dup_test },
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -161,8 +371,8 @@
     fFailureCount += 1;
 }
 
-void Forth_test_stdwords();
-void Forth_test_stdwords() {
+void Forth_test_stdwords(bool verbose);
+void Forth_test_stdwords(bool verbose) {
     ForthEnv env;
     Reporter reporter;
 
@@ -175,6 +385,9 @@
             str.printf("--- can't find stdword %d", gRecs[i].fName);
             reporter.reportFailure(str.c_str());
         } else {
+            if (verbose) {
+                SkDebugf("--- testing %s %p\n", gRecs[i].fName, word);
+            }
             gRecs[i].fProc(word, &engine, &reporter);
         }
     }
diff --git a/forth/SampleForth.cpp b/forth/SampleForth.cpp
index 2877fb6..cfd1172 100644
--- a/forth/SampleForth.cpp
+++ b/forth/SampleForth.cpp
@@ -150,7 +150,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void Forth_test_stdwords();
+void Forth_test_stdwords(bool verbose);
 
 class ForthView : public SkView {
     ForthEnv    fEnv;
@@ -160,7 +160,7 @@
     SkForthCtx  fContext;
 public:
 	ForthView() {
-        Forth_test_stdwords();
+        Forth_test_stdwords(false);
 
         load_words(&fEnv, &fContext);
 
@@ -186,9 +186,6 @@
                   "draw1 "
                   );
 #endif
-        ForthEnv env;
-        env.parse("3 5 = IF 42 . ELSE -42 . THEN 99 .");
-        env.run();
     }
     
 protected:
diff --git a/forth/StdWords.cpp b/forth/StdWords.cpp
index 98e39c0..177dabd 100644
--- a/forth/StdWords.cpp
+++ b/forth/StdWords.cpp
@@ -77,11 +77,13 @@
 ///////////////// logicals
 
 BEGIN_WORD(logical_and) {
-    fe->push(-(fe->pop() && fe->pop()));
+    intptr_t tmp = fe->pop();
+    fe->setTop(-(tmp && fe->top()));
 } END_WORD
 
 BEGIN_WORD(logical_or) {
-    fe->push(-(fe->pop() || fe->pop()));
+    intptr_t tmp = fe->pop();
+    fe->setTop(-(tmp || fe->top()));
 } END_WORD
 
 BEGIN_WORD(logical_not) {
@@ -400,18 +402,18 @@
     ADD_LITERAL_WORD("2OVER", over2);
     ADD_LITERAL_WORD("2DROP", drop2);
     
-    this->add("+", 1, new add_ForthWord);
-    this->add("-", 1, new sub_ForthWord);
-    this->add("*", 1, new mul_ForthWord);
-    this->add("/", 1, new div_ForthWord);
-    this->add("MOD", 1, new mod_ForthWord);
-    this->add("/MOD", 1, new divmod_ForthWord);
+    ADD_LITERAL_WORD("+", add);
+    ADD_LITERAL_WORD("-", sub);
+    ADD_LITERAL_WORD("*", mul);
+    ADD_LITERAL_WORD("/", div);
+    ADD_LITERAL_WORD("MOD", mod);
+    ADD_LITERAL_WORD("/MOD", divmod);
 
-    this->add(".", 1, new dot_ForthWord);
-    this->add("ABS", 3, new abs_ForthWord);
-    this->add("NEGATE", 3, new negate_ForthWord);
-    this->add("MIN", 3, new min_ForthWord);
-    this->add("MAX", 3, new max_ForthWord);
+    ADD_LITERAL_WORD(".", dot);
+    ADD_LITERAL_WORD("ABS", abs);
+    ADD_LITERAL_WORD("NEGATE", negate);
+    ADD_LITERAL_WORD("MIN", min);
+    ADD_LITERAL_WORD("MAX", max);
 
     ADD_LITERAL_WORD("AND", logical_and);
     ADD_LITERAL_WORD("OR", logical_or);