diff --git a/.gitignore b/.gitignore index 6ca25cb..2faea7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /arcana-lisp -/arcana-lisp-test /src/*.o /tests/*.out diff --git a/Makefile b/Makefile index 53a6238..9502932 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ OBJS = \ src/ctype.c.o \ src/eval.c.o \ src/lexer.c.o \ + src/main.c.o \ src/object.c.o \ src/parser.c.o \ src/syntax.c.o \ @@ -28,14 +29,10 @@ TEST_OUTS = \ tests/type_conv.out \ tests/type_preds.out -MAIN_OBJS = $(OBJS) src/main.c.o -TEST_OBJS = $(OBJS) src/main-test.c.o - repl: arcana-lisp ./arcana-lisp -test: arcana-lisp-test $(TEST_OUTS) - ./arcana-lisp-test +test: $(TEST_OUTS) $(DIFF_Q) tests/arithm_ops.txt tests/arithm_ops.out $(DIFF_Q) tests/basic_data_structs.txt tests/basic_data_structs.out $(DIFF_Q) tests/hello.txt tests/hello.out @@ -47,12 +44,9 @@ test: arcana-lisp-test $(TEST_OUTS) $(DIFF_Q) tests/type_preds.txt tests/type_preds.out clean: - $(RM_F) arcana-lisp arcana-lisp-test $(MAIN_OBJS) $(TEST_OBJS) $(TEST_OUTS) + $(RM_F) arcana-lisp $(OBJS) $(TEST_OUTS) -arcana-lisp: $(MAIN_OBJS) - $(CC) -o $@ $^ $(CFLAGS) - -arcana-lisp-test: $(TEST_OBJS) +arcana-lisp: $(OBJS) $(CC) -o $@ $^ $(CFLAGS) %.c.o: %.c diff --git a/src/main-test.c b/src/main-test.c deleted file mode 100644 index de5cee2..0000000 --- a/src/main-test.c +++ /dev/null @@ -1,1061 +0,0 @@ -#include "eval.h" -#include "object.h" - -#include -#include -#include - -static struct Object *result = NULL; - -// Syntax -static void test_begin(); -static void test_if(); -static void test_quote(); -// Arcana Lisp internals -static void test_arcana_SLASH_tokenize(); -static void test_arcana_SLASH_typeof(); -// Basic data structures -static void test_car(); -static void test_cdr(); -static void test_list(); -// Type predicates -static void test_booleanQN(); -static void test_charQN(); -static void test_nullQN(); -static void test_numberQN(); -static void test_pairQN(); -static void test_procedureQN(); -static void test_stringQN(); -static void test_symbolQN(); -// Type conversion -static void test_number_TO_string(); -static void test_string_TO_symbol(); -static void test_symbol_TO_string(); -// Logical operators -static void test_not(); -// Arithmetic operators -static void test_EQ(); -static void test_PLUS(); -static void test_MINUS(); - -int main() -{ - // Syntax - test_begin(); - test_if(); - test_quote(); - // Arcana Lisp internals - test_arcana_SLASH_tokenize(); - test_arcana_SLASH_typeof(); - // Basic data structures - test_car(); - test_cdr(); - test_list(); - // Type predicates - test_booleanQN(); - test_charQN(); - test_nullQN(); - test_numberQN(); - test_pairQN(); - test_procedureQN(); - test_stringQN(); - test_symbolQN(); - // Type conversion - test_number_TO_string(); - test_string_TO_symbol(); - test_symbol_TO_string(); - // Logical operators - test_not(); - // Arithmetic operators - test_EQ(); - test_PLUS(); - test_MINUS(); - - // #true - // #true - assert(Object_is_true(eval_str("#true"))); - - // 123 - // 123 - result = eval_str("123"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); -} - -/********** - * Syntax * - **********/ - -void test_begin() -{ - // (begin) - // () - assert(OBJECT_IS_NULL(eval_str("(begin)"))); - - // (begin 123) - // 123 - result = eval_str("(begin 123)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // (begin 123 456) - // 456 - result = eval_str("(begin 123 456)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 456); - - // (begin 123 456 789) - // 789 - result = eval_str("(begin 123 456 789)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 789); -} - -void test_if() -{ - // (if #true 123 456) - // 123 - result = eval_str("(if #true 123 456)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // (if "foo" 123 456) - // 123 - result = eval_str("(if \"foo\" 123 456)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // (if #false 123 456) - // 456 - result = eval_str("(if #false 123 456)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 456); -} - -void test_quote() -{ - // (quote +) - // + - result = eval_str("(quote +)"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "+") == 0); - - // '+ - // + - result = eval_str("'+"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "+") == 0); - - // (quote ()) - // () - assert(OBJECT_IS_NULL(eval_str("(quote ())"))); - - // '() - // () - assert(OBJECT_IS_NULL(eval_str("'()"))); - - // (quote #true) - // #true - result = eval_str("(quote #true)"); - assert(Object_is_true(result)); - - // '#true - // #true - result = eval_str("'#true"); - assert(Object_is_true(result)); - - // (quote #false) - // #false - result = eval_str("(quote #false)"); - assert(Object_is_false(result)); - - // '#false - // #false - result = eval_str("'#false"); - assert(Object_is_false(result)); - - // (quote #\n) - // #\n - result = eval(Object_build_list( - 2, - Object_new_symbol("quote"), - Object_new_char('\n') - )); - assert(Object_is_char(result)); - assert(result->chr == '\n'); - - // '#\n - // #\n - result = eval(Object_build_list( - 2, - Object_new_symbol("quote"), - Object_new_char('\n') - )); - assert(Object_is_char(result)); - assert(result->chr == '\n'); - - // (quote foo) - // foo - result = eval_str("(quote foo)"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "foo") == 0); - - // 'foo - // foo - result = eval_str("'foo"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "foo") == 0); - - // (quote "foo") - // "foo" - result = eval_str("(quote \"foo\")"); - assert(Object_is_string(result)); - assert(strcmp(result->s, "foo") == 0); - - // '"foo" - // "foo" - result = eval_str("'\"foo\""); - assert(Object_is_string(result)); - assert(strcmp(result->s, "foo") == 0); - - // (quote 123) - // 123 - result = eval_str("(quote 123)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // '123 - // 123 - result = eval_str("'123"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // (quote (cons 123 456)) - // (cons 123 456) - result = eval_str("(quote (cons 123 456))"); - assert(Object_is_pair(result)); - assert(Object_is_pair(result->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr)); - assert(OBJECT_IS_NULL(result->pair.cdr->pair.cdr->pair.cdr)); - assert(Object_is_symbol(result->pair.car)); - assert(Object_is_number(result->pair.cdr->pair.car)); - assert(Object_is_number(result->pair.cdr->pair.cdr->pair.car)); - assert(strcmp(result->pair.car->s, "cons") == 0); - assert(result->pair.cdr->pair.car->number.i64 == 123); - assert(result->pair.cdr->pair.cdr->pair.car->number.i64 == 456); - - // '(cons 123 456) - // (cons 123 456) - result = eval_str("'(cons 123 456)"); - assert(Object_is_pair(result)); - assert(Object_is_pair(result->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr)); - assert(OBJECT_IS_NULL(result->pair.cdr->pair.cdr->pair.cdr)); - assert(Object_is_symbol(result->pair.car)); - assert(Object_is_number(result->pair.cdr->pair.car)); - assert(Object_is_number(result->pair.cdr->pair.cdr->pair.car)); - assert(strcmp(result->pair.car->s, "cons") == 0); - assert(result->pair.cdr->pair.car->number.i64 == 123); - assert(result->pair.cdr->pair.cdr->pair.car->number.i64 == 456); -} - -/************************* - * Arcana Lisp internals * - *************************/ - -void test_arcana_SLASH_tokenize() -{ - // (arcana/tokenize "(") - // ((TOKEN_ROUND_OPEN . "")) - result = eval_str("(arcana/tokenize \"(\")"); - assert(Object_is_pair(result)); - assert(OBJECT_IS_NULL(result->pair.cdr)); - assert(Object_is_pair(result->pair.car)); - assert(Object_is_symbol(result->pair.car->pair.car)); - assert(Object_is_string(result->pair.car->pair.cdr)); - assert(strcmp(result->pair.car->pair.car->s, "TOKEN_ROUND_OPEN") == 0); - assert(strcmp(result->pair.car->pair.cdr->s, "(") == 0); - - // (arcana/tokenize "#false") - // ((TOKEN_TAG . "false")) - result = eval_str("(arcana/tokenize \"#false\")"); - assert(Object_is_pair(result)); - assert(OBJECT_IS_NULL(result->pair.cdr)); - assert(Object_is_pair(result->pair.car)); - assert(Object_is_symbol(result->pair.car->pair.car)); - assert(Object_is_string(result->pair.car->pair.cdr)); - assert(strcmp(result->pair.car->pair.car->s, "TOKEN_TAG") == 0); - assert(strcmp(result->pair.car->pair.cdr->s, "false") == 0); - - // (arcana/tokenize "\"\"") - // ((TOKEN_STRING . "")) - result = eval(Object_build_list( - 2, - Object_new_symbol("arcana/tokenize"), - Object_new_string("\"\"") - )); - assert(Object_is_pair(result)); - assert(OBJECT_IS_NULL(result->pair.cdr)); - assert(Object_is_pair(result->pair.car)); - assert(Object_is_symbol(result->pair.car->pair.car)); - assert(Object_is_string(result->pair.car->pair.cdr)); - assert(strcmp(result->pair.car->pair.car->s, "TOKEN_STRING") == 0); - assert(strcmp(result->pair.car->pair.cdr->s, "") == 0); - - // (arcana/tokenize "\"qwe\"") - // ((TOKEN_STRING . "")) - result = eval(Object_build_list( - 2, - Object_new_symbol("arcana/tokenize"), - Object_new_string("\"qwe\"") - )); - assert(Object_is_pair(result)); - assert(OBJECT_IS_NULL(result->pair.cdr)); - assert(Object_is_pair(result->pair.car)); - assert(Object_is_symbol(result->pair.car->pair.car)); - assert(Object_is_string(result->pair.car->pair.cdr)); - assert(strcmp(result->pair.car->pair.car->s, "TOKEN_STRING") == 0); - assert(strcmp(result->pair.car->pair.cdr->s, "qwe") == 0); - - // (arcana/tokenize "(displayln (list 1))") - // ((TOKEN_ROUND_OPEN . "(") (TOKEN_IDENT . "displayln") (TOKEN_ROUND_OPEN . "(") (TOKEN_IDENT . "list") (TOKEN_NUM . "1") (TOKEN_ROUND_CLOSE . ")") (TOKEN_ROUND_CLOSE . ")")) - result = eval_str("(arcana/tokenize \"(displayln (list 1))\")"); - { - assert(Object_is_pair(result)); - assert(Object_is_pair(result->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr->pair.cdr->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr)); - assert(Object_is_pair(result->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr)); - assert(OBJECT_IS_NULL(result->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr)); - - struct Object *const token_open1 = result->pair.car; - struct Object *const token_ident_displayln = result->pair.cdr->pair.car; - struct Object *const token_open2 = result->pair.cdr->pair.cdr->pair.car; - struct Object *const token_ident_list = result->pair.cdr->pair.cdr->pair.cdr->pair.car; - struct Object *const token_num_1 = result->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.car; - struct Object *const token_close2 = result->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.car; - struct Object *const token_close1 = result->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.cdr->pair.car; - - assert(Object_is_pair(token_open1)); - assert(Object_is_pair(token_ident_displayln)); - assert(Object_is_pair(token_open2)); - assert(Object_is_pair(token_ident_list)); - assert(Object_is_pair(token_num_1)); - assert(Object_is_pair(token_close2)); - assert(Object_is_pair(token_close1)); - - assert(Object_is_symbol(token_open1->pair.car)); - assert(Object_is_symbol(token_ident_displayln->pair.car)); - assert(Object_is_symbol(token_open2->pair.car)); - assert(Object_is_symbol(token_ident_list->pair.car)); - assert(Object_is_symbol(token_num_1->pair.car)); - assert(Object_is_symbol(token_close2->pair.car)); - assert(Object_is_symbol(token_close1->pair.car)); - - assert(0 == strcmp("TOKEN_ROUND_OPEN", token_open1->pair.car->s)); - assert(0 == strcmp("TOKEN_IDENT", token_ident_displayln->pair.car->s)); - assert(0 == strcmp("TOKEN_ROUND_OPEN", token_open2->pair.car->s)); - assert(0 == strcmp("TOKEN_IDENT", token_ident_list->pair.car->s)); - assert(0 == strcmp("TOKEN_NUM", token_num_1->pair.car->s)); - assert(0 == strcmp("TOKEN_ROUND_CLOSE", token_close2->pair.car->s)); - assert(0 == strcmp("TOKEN_ROUND_CLOSE", token_close1->pair.car->s)); - - assert(Object_is_string(token_open1->pair.cdr)); - assert(Object_is_string(token_ident_displayln->pair.cdr)); - assert(Object_is_string(token_open2->pair.cdr)); - assert(Object_is_string(token_ident_list->pair.cdr)); - assert(Object_is_string(token_num_1->pair.cdr)); - assert(Object_is_string(token_close2->pair.cdr)); - assert(Object_is_string(token_close1->pair.cdr)); - - assert(0 == strcmp("(", token_open1->pair.cdr->s)); - assert(0 == strcmp("displayln", token_ident_displayln->pair.cdr->s)); - assert(0 == strcmp("(", token_open2->pair.cdr->s)); - assert(0 == strcmp("list", token_ident_list->pair.cdr->s)); - assert(0 == strcmp("1", token_num_1->pair.cdr->s)); - assert(0 == strcmp(")", token_close2->pair.cdr->s)); - assert(0 == strcmp(")", token_close1->pair.cdr->s)); - } -} - -void test_arcana_SLASH_typeof() -{ - // (arcana/typeof '()) - // null - result = eval_str("(arcana/typeof '())"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "null") == 0); - - // (arcana/typeof +) - // procedure - result = eval_str("(arcana/typeof +)"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "procedure") == 0); - - // (arcana/typeof (cons 123 456)) - // pair - result = eval_str("(arcana/typeof (cons 123 456))"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "pair") == 0); - - // (arcana/typeof #false) - // boolean - result = eval_str("(arcana/typeof #false)"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "boolean") == 0); - - // (arcana/typeof #\n) - // char - result = eval(Object_build_list( - 2, - Object_new_symbol("arcana/typeof"), - Object_new_char('\n') - )); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "char") == 0); - - // (arcana/typeof 'foo) - // symbol - result = eval_str("(arcana/typeof 'foo)"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "symbol") == 0); - - // (arcana/typeof "foo") - // string - result = eval_str("(arcana/typeof \"foo\")"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "string") == 0); - - // (arcana/typeof 123) - // number - result = eval_str("(arcana/typeof 123)"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "number") == 0); -} - -/************************* - * Basic data structures * - *************************/ - -void test_car() -{ - // (car (cons 123 456)) - // 123 - result = eval_str("(car (cons 123 456))"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); -} - -void test_cdr() -{ - // (cdr (cons 123 456)) - // 456 - result = eval_str("(cdr (cons 123 456))"); - assert(Object_is_number(result)); - assert(result->number.i64 == 456); -} - -void test_list() -{ - // (list) - // () - assert(eval_str("(list)") == NULL); - - // (list 123) - // (123) - result = eval_str("(list 123)"); - assert(Object_is_pair(result)); - assert(Object_is_number(result->pair.car)); - assert(result->pair.car->number.i64 == 123); - assert(OBJECT_IS_NULL(result->pair.cdr)); - - // (list 123 456) - // (123 456) - result = eval_str("(list 123 456)"); - assert(Object_is_pair(result)); - assert(Object_is_number(result->pair.car)); - assert(result->pair.car->number.i64 == 123); - assert(Object_is_pair(result->pair.cdr)); - assert(Object_is_number(result->pair.cdr->pair.car)); - assert(result->pair.cdr->pair.car->number.i64 == 456); - assert(OBJECT_IS_NULL(result->pair.cdr->pair.cdr)); -} - -/******************* - * Type predicates * - *******************/ - -void test_booleanQN() -{ - // (boolean? +) - // #false - assert(Object_is_false(eval_str("(boolean? +)"))); - - // (boolean? '()) - // #false - assert(Object_is_false(eval_str("(boolean? '())"))); - - // (boolean? #true) - // #true - assert(Object_is_true(eval_str("(boolean? #true)"))); - - // (boolean? #false) - // #true - assert(Object_is_true(eval_str("(boolean? #false)"))); - - // (boolean? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("boolean?"), - Object_new_char('\n') - )))); - - // (boolean? 'foo) - // #false - assert(Object_is_false(eval_str("(boolean? 'foo)"))); - - // (boolean? "foo") - // #false - assert(Object_is_false(eval_str("(boolean? \"foo\")"))); - - // (boolean? 123) - // #false - assert(Object_is_false(eval_str("(boolean? 123)"))); - - // (boolean? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(boolean? (cons 123 456))"))); -} - -void test_charQN() -{ - // (char? +) - // #false - assert(Object_is_false(eval_str("(char? +)"))); - - // (char? '()) - // #false - assert(Object_is_false(eval_str("(char? '())"))); - - // (char? #true) - // #false - assert(Object_is_false(eval_str("(char? #true)"))); - - // (char? #false) - // #false - assert(Object_is_false(eval_str("(char? #false)"))); - - // (char? #\n) - // #true - assert(Object_is_true(eval(Object_build_list( - 2, - Object_new_symbol("char?"), - Object_new_char('\n') - )))); - - // (char? 'foo) - // #false - assert(Object_is_false(eval_str("(char? 'foo)"))); - - // (char? "foo") - // #false - assert(Object_is_false(eval_str("(char? \"foo\")"))); - - // (char? 123) - // #false - assert(Object_is_false(eval_str("(char? 123)"))); - - // (char? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(char? (cons 123 456))"))); -} - -void test_nullQN() -{ - // (null? +) - // #false - assert(Object_is_false(eval_str("(null? +)"))); - - // (null? '()) - // #true - assert(Object_is_true(eval_str("(null? '())"))); - - // (null? #true) - // #false - assert(Object_is_false(eval_str("(null? #true)"))); - - // (null? #false) - // #false - assert(Object_is_false(eval_str("(null? #false)"))); - - // (null? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("null?"), - Object_new_char('\n') - )))); - - // (null? 'foo) - // #false - assert(Object_is_false(eval_str("(null? 'foo)"))); - - // (null? "foo") - // #false - assert(Object_is_false(eval_str("(null? \"foo\")"))); - - // (null? 123) - // #false - assert(Object_is_false(eval_str("(null? 123)"))); - - // (null? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(null? (cons 123 456))"))); -} - -void test_numberQN() -{ - // (number? +) - // #false - assert(Object_is_false(eval_str("(number? +)"))); - - // (number? '()) - // #false - assert(Object_is_false(eval_str("(number? '())"))); - - // (number? #true) - // #false - assert(Object_is_false(eval_str("(number? #true)"))); - - // (number? #false) - // #false - assert(Object_is_false(eval_str("(number? #false)"))); - - // (number? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("number?"), - Object_new_char('\n') - )))); - - // (number? 'foo) - // #false - assert(Object_is_false(eval_str("(number? 'foo)"))); - - // (number? "foo") - // #false - assert(Object_is_false(eval_str("(number? \"foo\")"))); - - // (number? 123) - // #true - assert(Object_is_true(eval_str("(number? 123)"))); - - // (number? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(number? (cons 123 456))"))); -} - -void test_pairQN() -{ - // (pair? +) - // #false - assert(Object_is_false(eval_str("(pair? +)"))); - - // (pair? '()) - // #false - assert(Object_is_false(eval_str("(pair? '())"))); - - // (pair? #true) - // #false - assert(Object_is_false(eval_str("(pair? #true)"))); - - // (pair? #false) - // #false - assert(Object_is_false(eval_str("(pair? #false)"))); - - // (pair? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("pair?"), - Object_new_char('\n') - )))); - - // (pair? 'foo) - // #false - assert(Object_is_false(eval_str("(pair? 'foo)"))); - - // (pair? "foo") - // #false - assert(Object_is_false(eval_str("(pair? \"foo\")"))); - - // (pair? 123) - // #false - assert(Object_is_false(eval_str("(pair? 123)"))); - - // (pair? (cons 123 456)) - // #true - assert(Object_is_true(eval_str("(pair? (cons 123 456))"))); -} - -void test_procedureQN() -{ - // (procedure? +) - // #true - assert(Object_is_true(eval_str("(procedure? +)"))); - - // (procedure? '()) - // #false - assert(Object_is_false(eval_str("(procedure? '())"))); - - // (procedure? #true) - // #false - assert(Object_is_false(eval_str("(procedure? #true)"))); - - // (procedure? #false) - // #false - assert(Object_is_false(eval_str("(procedure? #false)"))); - - // (procedure? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("procedure?"), - Object_new_char('\n') - )))); - - // (procedure? 'foo) - // #false - assert(Object_is_false(eval_str("(procedure? 'foo)"))); - - // (procedure? "foo") - // #false - assert(Object_is_false(eval_str("(procedure? \"foo\")"))); - - // (procedure? 123) - // #false - assert(Object_is_false(eval_str("(procedure? 123)"))); - - // (procedure? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(procedure? (cons 123 456))"))); -} - -void test_stringQN() -{ - // (string? +) - // #false - assert(Object_is_false(eval_str("(string? +)"))); - - // (string? '()) - // #false - assert(Object_is_false(eval_str("(string? '())"))); - - // (string? #true) - // #false - assert(Object_is_false(eval_str("(string? #true)"))); - - // (string? #false) - // #false - assert(Object_is_false(eval_str("(string? #false)"))); - - // (string? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("string?"), - Object_new_char('\n') - )))); - - // (string? 'foo) - // #false - assert(Object_is_false(eval_str("(string? 'foo)"))); - - // (string? "foo") - // #true - assert(Object_is_true(eval_str("(string? \"foo\")"))); - - // (string? 123) - // #false - assert(Object_is_false(eval_str("(string? 123)"))); - - // (string? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(string? (cons 123 456))"))); -} - -void test_symbolQN() -{ - // (symbol? +) - // #false - assert(Object_is_false(eval_str("(symbol? +)"))); - - // (symbol? '()) - // #false - assert(Object_is_false(eval_str("(symbol? '())"))); - - // (symbol? #true) - // #false - assert(Object_is_false(eval_str("(symbol? #true)"))); - - // (symbol? #false) - // #false - assert(Object_is_false(eval_str("(symbol? #false)"))); - - // (symbol? #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("symbol?"), - Object_new_char('\n') - )))); - - // (symbol? 'foo) - // #true - assert(Object_is_true(eval_str("(symbol? 'foo)"))); - - // (symbol? "foo") - // #false - assert(Object_is_false(eval_str("(symbol? \"foo\")"))); - - // (symbol? 123) - // #false - assert(Object_is_false(eval_str("(symbol? 123)"))); - - // (symbol? (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(symbol? (cons 123 456))"))); -} - -/******************* - * Type conversion * - *******************/ - -void test_number_TO_string() -{ - // (number->string 123) - // "123" - result = eval_str("(number->string 123)"); - assert(Object_is_string(result)); - assert(strcmp(result->s, "123") == 0); - - // (number->string -123) - // "-123" - result = eval(Object_build_list( - 2, - Object_new_symbol("number->string"), - Object_new_number(-123) - )); - assert(Object_is_string(result)); - assert(strcmp(result->s, "-123") == 0); - - // (number->string 123456 16) - // "1e240" - result = eval_str("(number->string 123456 16)"); - assert(Object_is_string(result)); - assert(strcmp(result->s, "1e240") == 0); -} - -void test_string_TO_symbol() -{ - // (string->symbol "") - // || - result = eval_str("(string->symbol \"\")"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "") == 0); - - // (string->symbol " ") - // | | - result = eval_str("(string->symbol \" \")"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, " ") == 0); - - // (string->symbol "foo") - // |foo| - result = eval_str("(string->symbol \"foo\")"); - assert(Object_is_symbol(result)); - assert(strcmp(result->s, "foo") == 0); -} - -void test_symbol_TO_string() -{ - // (symbol->string 'foo) - // "foo" - result = eval_str("(symbol->string 'foo)"); - assert(Object_is_string(result)); - assert(strcmp(result->s, "foo") == 0); -} - -/********************* - * Logical operators * - *********************/ - -void test_not() -{ - // (not '()) - // #false - assert(Object_is_false(eval_str("(not '())"))); - - // (not #true) - // #false - assert(Object_is_false(eval_str("(not #true)"))); - - // (not #false) - // #true - assert(Object_is_true(eval_str("(not #false)"))); - - // (not #\n) - // #false - assert(Object_is_false(eval(Object_build_list( - 2, - Object_new_symbol("not"), - Object_new_char('\n') - )))); - - // (not 'foo) - // #false - assert(Object_is_false(eval_str("(not 'foo)"))); - - // (not "foo") - // #false - assert(Object_is_false(eval_str("(not \"foo\")"))); - - // (not 123) - // #false - assert(Object_is_false(eval_str("(not 123)"))); - - // (not (cons 123 456)) - // #false - assert(Object_is_false(eval_str("(not (cons 123 456))"))); -} - -/************************ - * Arithmetic operators * - ************************/ - -void test_EQ() -{ - // (= 123) - // #true - assert(Object_is_true(eval_str("(= 123)"))); - - // (= 123 123) - // #true - assert(Object_is_true(eval_str("(= 123 123)"))); - - // (= 123 456) - // #false - assert(Object_is_false(eval_str("(= 123 456)"))); - - // (= 123 123 123) - // #true - assert(Object_is_true(eval_str("(= 123 123 123)"))); - - // (= 456 123 123) - // #false - assert(Object_is_false(eval_str("(= 456 123 123)"))); - - // (= 123 456 123) - // #false - assert(Object_is_false(eval_str("(= 123 456 123)"))); - - // (= 123 123 456) - // #false - assert(Object_is_false(eval_str("(= 123 123 456)"))); - - // (= 123 123 123 123) - // #true - assert(Object_is_true(eval_str("(= 123 123 123 123)"))); - - // (= 456 123 123 123) - // #false - assert(Object_is_false(eval_str("(= 456 123 123 123)"))); - - // (= 123 456 123 123) - // #false - assert(Object_is_false(eval_str("(= 123 456 123 123)"))); - - // (= 123 123 456 123) - // #false - assert(Object_is_false(eval_str("(= 123 123 456 123)"))); - - // (= 123 123 123 456) - // #false - assert(Object_is_false(eval_str("(= 123 123 123 456)"))); -} - -void test_PLUS() -{ - // (+) - // 0 - result = eval_str("(+)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 0); - - // (+ 123) - // 123 - result = eval_str("(+ 123)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // (+ 1 10) - // 11 - result = eval_str("(+ 1 10)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 11); - - // (+ 1 10 100) - // 111 - result = eval_str("(+ 1 10 100)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 111); - - // (+ 1 10 100 1000) - // 1111 - result = eval_str("(+ 1 10 100 1000)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 1111); -} - -void test_MINUS() -{ - // (- 0) - // 0 - result = eval_str("(- 0)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 0); - - // (- 123) - // 123 - result = eval_str("(- 123)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 123); - - // (- 100 1) - // 99 - result = eval_str("(- 100 1)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 99); - - // (- 100 1 2) - // 97 - result = eval_str("(- 100 1 2)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 97); - - // (- 100 1 2 3) - // 94 - result = eval_str("(- 100 1 2 3)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 94); - - // (- 100 1 2 3 4) - // 90 - result = eval_str("(- 100 1 2 3 4)"); - assert(Object_is_number(result)); - assert(result->number.i64 == 90); -}