]> git.mdlowis.com Git - projs/onward.git/commitdiff
Started testing built-in words
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 25 Nov 2014 00:26:50 +0000 (19:26 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 25 Nov 2014 00:26:50 +0000 (19:26 -0500)
build.rb
source/main.c
source/onward/onward.c
source/onward/onward.ft [new file with mode: 0644]
source/onward/onward.fth [deleted file]
source/onward/onward.h
tests/main.c
tests/test_compiler.c [deleted file]
tests/test_interpreter.c [new file with mode: 0644]
tests/test_vars.c [new file with mode: 0755]

index 802db8d0f15b25f7b6ffe22aa2b87c3fce05578d..eafcafce05e46939963caba66b454250ad46b293 100755 (executable)
--- a/build.rb
+++ b/build.rb
@@ -37,7 +37,7 @@ unless Opts[:profile].include? "no-tests"
       'source/onward/onward.c',
       'modules/atf/source/atf.c'] +
       Dir['tests/**/*.c'])
-  test_env.Command('TESTS', [], 'CMD' => ['./onward-tests'])
+  test_env.Command('Unit Tests', ['./onward-tests'], 'CMD' => ['./onward-tests'])
 end
 
 #------------------------------------------------------------------------------
index a95ebe06aab812dc278fa3ae91c38c2450bfd2e2..98ab5c64b14be60f123bd813c94019548861058b 100755 (executable)
@@ -4,7 +4,7 @@
 #define STACK_SZ (64u)
 value_t Arg_Stack_Buf[STACK_SZ];
 value_t Ret_Stack_Buf[STACK_SZ];
-char     Input_Line[1024];
+char    Input_Line[1024];
 value_t Ram_Data_Buf[8192/sizeof(value_t)];
 
 defcode("dumpw", dumpw, LATEST_BUILTIN, 0u) {
@@ -42,6 +42,7 @@ void print_stack(void) {
             printf("%zd ", *curr);
     }
     puts(")");
+    printf("errno: %zd\n", errno);
     puts(!errno ? "OK." : "?");
 }
 
@@ -61,8 +62,10 @@ void parse(FILE* file) {
 
 void parse_file(char* fname) {
     FILE* file = fopen(fname, "r");
-    parse(file);
-    fclose(file);
+    if (file) {
+        parse(file);
+        fclose(file);
+    }
 }
 
 int main(int argc, char** argv) {
index 13f192d8da64caf720dec6ebb25deaeeeb8e44a0..a1427f259f5bc51cf2f9a3218fdd4b6ae8ee7167 100755 (executable)
@@ -102,6 +102,9 @@ defcode("num", num, &dropline, 0u) {
             case 'o': base = 8;  break;
             case 'd': base = 10; break;
             case 'x': base = 16; break;
+            case '\0':
+                success = 1;
+                value = 0;
             default:  base = -1; break;
         }
     }
diff --git a/source/onward/onward.ft b/source/onward/onward.ft
new file mode 100644 (file)
index 0000000..c6e12b0
--- /dev/null
@@ -0,0 +1,31 @@
+
+: immediate
+    latest @        \ Get the latest word
+    CELLSZ +        \ Add offset to get to the flags field
+    dup @           \ Fetch the current value
+    F_IMMEDIATE | ! \ Set the immediate bit
+; immediate
+
+\ : if immediate
+\     ' 0br , \ compile 0branch
+\     here @  \ save location of the offset on the stack
+\     0 ,     \ compile a dummy offset
+\ ;
+\
+\ : then immediate
+\     dup
+\     here @ swap -   \ calculate the offset from the address saved on the stack
+\     swap !          \ store the offset in the back-filled location
+\ ;
+\
+\ : else immediate
+\     ' br ,          \ definite branch to just over the false-part
+\     here @          \ save location of the offset on the stack
+\     0 ,             \ compile a dummy offset
+\     swap            \ now back-fill the original (if) offset
+\     dup             \ same as for then word above
+\     here @ swap -
+\     swap !
+\ ;
+
+
diff --git a/source/onward/onward.fth b/source/onward/onward.fth
deleted file mode 100644 (file)
index cd8bcc5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-: foo + ;
index a1dd75499d5d25412ddaba91243bd414ef58f341..9f5a8447486599c6318b147b32693c6dbd4bcac4 100755 (executable)
@@ -148,6 +148,7 @@ decvar(latest);
 decvar(state);
 decvar(here);
 deccode(word);
+deccode(dropline);
 deccode(num);
 deccode(lit);
 deccode(find);
index bbda21934c8ef30c9de09bd002050702c4a902d9..b77f02a2a9f6ea36c8b6586014f63e9bea5ee842 100755 (executable)
@@ -1,9 +1,31 @@
 #include "atf.h"
+#include "onward.h"
+
+static value_t Arg_Stack_Buf[32u];
+static value_t Ret_Stack_Buf[32u];
+static value_t Ram_Data_Buf[8192/sizeof(value_t)];
+
+void state_reset(void) {
+    /* Initialize the system */
+    onward_init_t init_data = {
+        Arg_Stack_Buf,
+        32u,
+        Ret_Stack_Buf,
+        32u,
+        Ram_Data_Buf,
+        8192/sizeof(value_t),
+        (word_t*)LATEST_BUILTIN
+    };
+    onward_init(&init_data);
+    errno = 0;
+}
 
 int main(int argc, char** argv)
 {
     (void)argc;
     (void)argv;
-    RUN_EXTERN_TEST_SUITE(Variables);
+    /* Run the tests and report the results */
+    RUN_EXTERN_TEST_SUITE(Constants_And_Variables);
+    RUN_EXTERN_TEST_SUITE(Interpreter);
     return PRINT_TEST_RESULTS();
 }
diff --git a/tests/test_compiler.c b/tests/test_compiler.c
deleted file mode 100755 (executable)
index 89d672c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Unit Test Framework Includes
-#include "atf.h"
-
-// File To Test
-#include "onward.h"
-
-void test_setup(void) {}
-
-//-----------------------------------------------------------------------------
-// Begin Unit Tests
-//-----------------------------------------------------------------------------
-TEST_SUITE(Variables) {
-    //-------------------------------------------------------------------------
-    // Test
-    //-------------------------------------------------------------------------
-    TEST(Verify_)
-    {
-    }
-}
diff --git a/tests/test_interpreter.c b/tests/test_interpreter.c
new file mode 100644 (file)
index 0000000..40f3cd6
--- /dev/null
@@ -0,0 +1,335 @@
+// Unit Test Framework Includes
+#include "atf.h"
+#include <string.h>
+
+// File To Test
+#include "onward.h"
+
+void state_reset(void);
+
+//-----------------------------------------------------------------------------
+// Begin Unit Tests
+//-----------------------------------------------------------------------------
+TEST_SUITE(Interpreter) {
+    //-------------------------------------------------------------------------
+    // Testing: word
+    //-------------------------------------------------------------------------
+    TEST(Verify_word_reads_the_next_word_and_places_it_on_the_stack)
+    {
+        state_reset();
+        input = (intptr_t)" foo ";
+        ((primitive_t)word.code)();
+        char* result = (char*)onward_aspop();
+        CHECK(0 == strcmp(result, "foo"));
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: \
+    //-------------------------------------------------------------------------
+    TEST(Verify_dropline_drops_the_rest_of_the_given_input)
+    {
+        state_reset();
+        input = (intptr_t)" foo ";
+        ((primitive_t)dropline.code)();
+        CHECK(0 == strcmp((char*)input, ""));
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: num
+    //-------------------------------------------------------------------------
+    TEST(Verify_num_parses_a_decimal_zero)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(0 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_negative_decimal_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"-42");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(-42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_positive_decimal_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"42");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_binary_radix_zero)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0b0");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(0 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_negative_binary_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"-0b101010");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(-42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_positive_binary_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0b101010");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_octal_radix_zero)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0o0");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(0 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_negative_octal_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"-0o52");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(-42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_positive_octal_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0o52");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_decimal_radix_zero)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0d0");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(0 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_negative_decimal_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"-0d42");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(-42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_positive_decimal_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0d42");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_hexadecimal_radix_zero)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0x0");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(0 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_negative_hexadecimal_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"-0x2A");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(-42 == onward_aspop());
+    }
+
+    TEST(Verify_num_parses_a_positive_hexadecimal_radix_number)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0x2a");
+        ((primitive_t)num.code)();
+        CHECK(1 == onward_aspop());
+        CHECK(42 == onward_aspop());
+    }
+
+    TEST(Verify_num_fails_to_parse_a_string_containing_chars_of_the_wrong_base)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0b2");
+        ((primitive_t)num.code)();
+        CHECK(0 == onward_aspop());
+        CHECK(0 == strcmp("0b2", (char*)onward_aspop()));
+    }
+
+    TEST(Verify_num_fails_to_parse_a_string_containing_chars_of_the_wrong_base)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0b02");
+        ((primitive_t)num.code)();
+        CHECK(0 == onward_aspop());
+        CHECK(0 == strcmp("0b02", (char*)onward_aspop()));
+    }
+
+    TEST(Verify_num_fails_to_parse_a_string_containing_chars_of_the_wrong_base)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0b20");
+        ((primitive_t)num.code)();
+        CHECK(0 == onward_aspop());
+        CHECK(0 == strcmp("0b20", (char*)onward_aspop()));
+    }
+
+    TEST(Verify_num_fails_to_parse_a_string_containing_chars_of_the_wrong_base)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"0b0Z");
+        ((primitive_t)num.code)();
+        CHECK(0 == onward_aspop());
+        CHECK(0 == strcmp("0b0Z", (char*)onward_aspop()));
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: lit
+    //-------------------------------------------------------------------------
+    TEST(Verify_lit_grabs_the_next_instruction_and_pushes_it_on_the_stack_as_a_literal)
+    {
+        state_reset();
+        intptr_t code[] = { 42 };
+        pc = (intptr_t)code;
+        ((primitive_t)lit.code)();
+        CHECK(42 == onward_aspop());
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: find
+    //-------------------------------------------------------------------------
+    TEST(Verify_find_pushes_the_word_address_on_the_stack_if_found)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"+");
+        ((primitive_t)find.code)();
+        CHECK((intptr_t)&add == onward_aspop());
+    }
+
+    TEST(Verify_find_pushes_null_on_the_stack_if_not_found)
+    {
+        state_reset();
+        onward_aspush((intptr_t)"foo");
+        ((primitive_t)find.code)();
+        CHECK((intptr_t)NULL == onward_aspop());
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: exec
+    //-------------------------------------------------------------------------
+    TEST(Verify_exec_should_execute_the_word_on_the_top_of_the_stack)
+    {
+        state_reset();
+        onward_aspush(1);
+        onward_aspush(1);
+        onward_aspush((intptr_t)&add);
+        ((primitive_t)exec.code)();
+        CHECK(2 == onward_aspop());
+        CHECK(asb == asp);
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: create
+    //-------------------------------------------------------------------------
+    TEST(Verify_create_a_new_word_definition)
+    {
+        state_reset();
+        word_t* old_word = (word_t*)latest;
+        onward_aspush((intptr_t)"foo");
+        ((primitive_t)create.code)();
+        word_t* new_word = (word_t*)latest;
+        CHECK(F_HIDDEN_MSK == new_word->flags);
+        CHECK((intptr_t*)here == new_word->code);
+        CHECK(old_word == new_word->link);
+        CHECK(0 == *(intptr_t*)here);
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: ,
+    //-------------------------------------------------------------------------
+    TEST(Verify_comma_appends_a_word_to_the_latest_word)
+    {
+        state_reset();
+        intptr_t code[] = { 0, 0 };
+        here = (intptr_t)code;
+        onward_aspush((intptr_t)&add);
+        ((primitive_t)comma.code)();
+        CHECK((intptr_t)&add == code[0]);
+        CHECK(here == (intptr_t)&code[1]);
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: [
+    //-------------------------------------------------------------------------
+    TEST(Verify_lbrack_switches_to_immediate_mode)
+    {
+        state_reset();
+        state = 1;
+        ((primitive_t)lbrack.code)();
+        CHECK(0 == state);
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: ]
+    //-------------------------------------------------------------------------
+    TEST(Verify_rbrack_switches_to_compile_mode)
+    {
+        state_reset();
+        state = 0;
+        ((primitive_t)rbrack.code)();
+        CHECK(1 == state);
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: :
+    //-------------------------------------------------------------------------
+
+    //-------------------------------------------------------------------------
+    // Testing: '
+    //-------------------------------------------------------------------------
+    TEST(Verify_tick_fetches_next_instruction_and_places_it_on_the_stack)
+    {
+        state_reset();
+        intptr_t code[] = { (intptr_t)&add, 0 };
+        pc = (intptr_t)code;
+        ((primitive_t)tick.code)();
+        CHECK((intptr_t)&add == onward_aspop());
+    }
+
+    //-------------------------------------------------------------------------
+    // Testing: br
+    //-------------------------------------------------------------------------
+
+    //-------------------------------------------------------------------------
+    // Testing: 0br
+    //-------------------------------------------------------------------------
+
+    //-------------------------------------------------------------------------
+    // Testing: interp
+    //-------------------------------------------------------------------------
+}
diff --git a/tests/test_vars.c b/tests/test_vars.c
new file mode 100755 (executable)
index 0000000..312e06e
--- /dev/null
@@ -0,0 +1,48 @@
+// Unit Test Framework Includes
+#include "atf.h"
+
+// File To Test
+#include "onward.h"
+
+void state_reset(void);
+
+static intptr_t get_const(const word_t* word) {
+    ((primitive_t)word->code)();
+   return onward_aspop();
+}
+
+static bool is_var(intptr_t* data, const word_t* word) {
+    ((primitive_t)word->code)();
+    return ((intptr_t)data == onward_aspop());
+}
+
+//-----------------------------------------------------------------------------
+// Begin Unit Tests
+//-----------------------------------------------------------------------------
+TEST_SUITE(Constants_And_Variables) {
+    TEST(Verify_constants_are_the_expected_values)
+    {
+        state_reset();
+        CHECK(0               == get_const(&VERSION_word));
+        CHECK(CELLSZ          == get_const(&CELLSZ_word));
+        CHECK(SYS_BITCOUNT    == get_const(&BITCOUNT_word));
+        CHECK(F_PRIMITIVE_MSK == get_const(&F_PRIMITIVE_word));
+        CHECK(F_HIDDEN_MSK    == get_const(&F_HIDDEN_word));
+        CHECK(F_IMMEDIATE_MSK == get_const(&F_IMMEDIATE_word));
+    }
+
+    TEST(Verify_variables_behave_as_expected)
+    {
+        state_reset();
+        CHECK(is_var(&pc, &pc_word));
+        CHECK(is_var(&asb, &asb_word));
+        CHECK(is_var(&asp, &asp_word));
+        CHECK(is_var(&rsb, &rsb_word));
+        CHECK(is_var(&rsp, &rsp_word));
+        CHECK(is_var(&input, &input_word));
+        CHECK(is_var(&errno, &errno_word));
+        CHECK(is_var(&latest, &latest_word));
+        CHECK(is_var(&state, &state_word));
+        CHECK(is_var(&here, &here_word));
+    }
+}