From: Michael D. Lowis Date: Tue, 25 Nov 2014 00:26:50 +0000 (-0500) Subject: Started testing built-in words X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=fb8da27e703f0891171d1325e500eb42538b76ba;p=projs%2Fonward.git Started testing built-in words --- diff --git a/build.rb b/build.rb index 802db8d..eafcafc 100755 --- 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 #------------------------------------------------------------------------------ diff --git a/source/main.c b/source/main.c index a95ebe0..98ab5c6 100755 --- a/source/main.c +++ b/source/main.c @@ -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) { diff --git a/source/onward/onward.c b/source/onward/onward.c index 13f192d..a1427f2 100755 --- a/source/onward/onward.c +++ b/source/onward/onward.c @@ -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 index 0000000..c6e12b0 --- /dev/null +++ b/source/onward/onward.ft @@ -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 index cd8bcc5..0000000 --- a/source/onward/onward.fth +++ /dev/null @@ -1 +0,0 @@ -: foo + ; diff --git a/source/onward/onward.h b/source/onward/onward.h index a1dd754..9f5a844 100755 --- a/source/onward/onward.h +++ b/source/onward/onward.h @@ -148,6 +148,7 @@ decvar(latest); decvar(state); decvar(here); deccode(word); +deccode(dropline); deccode(num); deccode(lit); deccode(find); diff --git a/tests/main.c b/tests/main.c index bbda219..b77f02a 100755 --- a/tests/main.c +++ b/tests/main.c @@ -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 index 89d672c..0000000 --- a/tests/test_compiler.c +++ /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 index 0000000..40f3cd6 --- /dev/null +++ b/tests/test_interpreter.c @@ -0,0 +1,335 @@ +// Unit Test Framework Includes +#include "atf.h" +#include + +// 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 index 0000000..312e06e --- /dev/null +++ b/tests/test_vars.c @@ -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)); + } +}