rename std words to be UPPER CASE (ugh)
add initial unittests for std words (more to do)



git-svn-id: http://skia.googlecode.com/svn/trunk@347 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/forth/ForthTests.cpp b/forth/ForthTests.cpp
new file mode 100644
index 0000000..e918329
--- /dev/null
+++ b/forth/ForthTests.cpp
@@ -0,0 +1,188 @@
+#include "Forth.h"
+#include "SkString.h"
+
+class Reporter {
+public:
+    int fFailureCount;
+
+    Reporter() : fFailureCount(0) {}
+    void reportFailure(const char expression[], const char file[], int line);
+    void reportFailure(const char msg[]);
+};
+    
+typedef void (*ForthWordTestProc)(ForthWord*, ForthEngine*, Reporter*);
+
+#define FORTH_ASSERT(reporter, expression)      \
+    do {                                        \
+        if (!(expression)) {                    \
+            reporter->reportFailure(#expression, __FILE__, __LINE__);   \
+        }                                       \
+    } while (0)
+
+static void drop_test0(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(-17);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 0 == fe->depth());
+}
+
+static void drop_test1(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(-17);
+    fe->push(93);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 1 == fe->depth());
+    FORTH_ASSERT(reporter, -17 == fe->peek(0));
+}
+
+static void dup_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(-17);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 2 == fe->depth());
+    FORTH_ASSERT(reporter, -17 == fe->peek(0));
+    FORTH_ASSERT(reporter, -17 == fe->peek(1));
+}
+
+static void swap_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(-17);
+    fe->push(42);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 2 == fe->depth());
+    FORTH_ASSERT(reporter, -17 == fe->peek(0));
+    FORTH_ASSERT(reporter, 42 == fe->peek(1));
+}
+
+static void over_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 3 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->peek(0));
+    FORTH_ASSERT(reporter, 2 == fe->peek(1));
+    FORTH_ASSERT(reporter, 1 == fe->peek(2));
+}
+
+static void rot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    fe->push(3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 3 == fe->depth());
+    FORTH_ASSERT(reporter, 2 == fe->peek(2));
+    FORTH_ASSERT(reporter, 3 == fe->peek(1));
+    FORTH_ASSERT(reporter, 1 == fe->peek(0));
+}
+
+static void rrot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    fe->push(3);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 3 == fe->depth());
+    FORTH_ASSERT(reporter, 2 == fe->peek(0));
+    FORTH_ASSERT(reporter, 1 == fe->peek(1));
+    FORTH_ASSERT(reporter, 3 == fe->peek(2));
+}
+
+static void swap2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    fe->push(3);
+    fe->push(4);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 4 == fe->depth());
+    FORTH_ASSERT(reporter, 2 == fe->peek(0));
+    FORTH_ASSERT(reporter, 1 == fe->peek(1));
+    FORTH_ASSERT(reporter, 4 == fe->peek(2));
+    FORTH_ASSERT(reporter, 3 == fe->peek(3));
+}
+
+static void dup2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 4 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->peek(3));
+    FORTH_ASSERT(reporter, 2 == fe->peek(2));
+    FORTH_ASSERT(reporter, 1 == fe->peek(1));
+    FORTH_ASSERT(reporter, 2 == fe->peek(0));
+}
+
+static void over2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    fe->push(3);
+    fe->push(4);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 6 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->peek(5));
+    FORTH_ASSERT(reporter, 2 == fe->peek(4));
+    FORTH_ASSERT(reporter, 3 == fe->peek(3));
+    FORTH_ASSERT(reporter, 4 == fe->peek(2));
+    FORTH_ASSERT(reporter, 1 == fe->peek(1));
+    FORTH_ASSERT(reporter, 2 == fe->peek(0));
+}
+
+static void drop2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
+    fe->push(1);
+    fe->push(2);
+    fe->push(3);
+    fe->push(4);
+    word->exec(fe);
+    FORTH_ASSERT(reporter, 2 == fe->depth());
+    FORTH_ASSERT(reporter, 1 == fe->peek(1));
+    FORTH_ASSERT(reporter, 2 == fe->peek(0));
+}
+
+static const struct {
+    const char*         fName;
+    ForthWordTestProc   fProc;
+} gRecs[] = {
+    { "DROP",   drop_test0 },   { "DROP",   drop_test1 },
+    { "DUP",    dup_test },
+    { "SWAP",   swap_test },
+    { "OVER",   over_test },
+    { "ROT",    rot_test },
+    { "-ROT",   rrot_test },
+    { "2SWAP",  swap2_test },
+    { "2DUP",   dup2_test },
+    { "2OVER",  over2_test },
+    { "2DROP",  drop2_test },
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Reporter::reportFailure(const char expression[], const char file[],
+                             int line) {
+    SkDebugf("failed %s:%d: %s\n", file, line, expression);
+    fFailureCount += 1;
+}
+
+void Reporter::reportFailure(const char msg[]) {
+    SkDebugf("%s\n");
+    fFailureCount += 1;
+}
+
+void Forth_test_stdwords();
+void Forth_test_stdwords() {
+    ForthEnv env;
+    Reporter reporter;
+
+    for (size_t i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
+        ForthEngine engine(NULL);
+        
+        ForthWord* word = env.findWord(gRecs[i].fName);
+        if (NULL == word) {
+            SkString str;
+            str.printf("--- can't find stdword %d", gRecs[i].fName);
+            reporter.reportFailure(str.c_str());
+        } else {
+            gRecs[i].fProc(word, &engine, &reporter);
+        }
+    }
+    
+    if (0 == reporter.fFailureCount) {
+        SkDebugf("--- success!\n");
+    } else {
+        SkDebugf("--- %d failures\n", reporter.fFailureCount);
+    }
+}
+