|
|
|
@@ -4,16 +4,14 @@ |
|
|
|
#define pass 1 |
|
|
|
#define fail 0 |
|
|
|
|
|
|
|
#define print_assert_equal_fail(variable, value, type, format) \ |
|
|
|
printf("\nAssertion failed for '" #variable "'" \ |
|
|
|
"\n\t in %s:%d" \ |
|
|
|
"\n\texpected: " format \ |
|
|
|
"\n\tgot: " format "\n", \ |
|
|
|
__FILE__, __LINE__, (type)value, (type)variable) |
|
|
|
#define print_assert_equal_fail(variable, value, type, format) \ |
|
|
|
printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \ |
|
|
|
"\n\texpected: " format \ |
|
|
|
"\n\tgot: " format "\n", \ |
|
|
|
__FILE__, __LINE__, (type)value, (type)variable) |
|
|
|
|
|
|
|
#define print_assert_not_equal_fail(variable, value, type, format) \ |
|
|
|
printf("\nAssertion failed for '" #variable "'" \ |
|
|
|
"\n\t in %s:%d" \ |
|
|
|
printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \ |
|
|
|
"\n\texpected not: " format \ |
|
|
|
"\n\tgot anyways: " format "\n", \ |
|
|
|
__FILE__, __LINE__, (type)value, (type)variable) |
|
|
|
@@ -50,6 +48,13 @@ |
|
|
|
return fail; \ |
|
|
|
} |
|
|
|
|
|
|
|
#define assert_equal_string(variable, value) \ |
|
|
|
if (!string_equal(variable, value)) { \ |
|
|
|
print_assert_equal_fail(variable, value, char*, "%s"); \ |
|
|
|
return fail; \ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define assert_null(variable) \ |
|
|
|
assert_equal_int(variable, nullptr) |
|
|
|
|
|
|
|
@@ -74,21 +79,121 @@ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
|
|
|
|
testresult test_parse_atom() { |
|
|
|
int index_in_text = 0; |
|
|
|
char string[] = |
|
|
|
"123 -1.23e-2 " // numbers |
|
|
|
"\"asd\" " // strings |
|
|
|
":key1 :key:2 " // keywords |
|
|
|
"sym +"; // symbols |
|
|
|
|
|
|
|
// test numbers |
|
|
|
Ast_Node* result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Number); |
|
|
|
assert_equal_double(result->value.number->value, 123); |
|
|
|
|
|
|
|
++index_in_text; |
|
|
|
|
|
|
|
result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Number); |
|
|
|
assert_equal_double(result->value.number->value, -1.23e-2); |
|
|
|
|
|
|
|
// test strings |
|
|
|
++index_in_text; |
|
|
|
|
|
|
|
result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_String); |
|
|
|
assert_equal_string(result->value.string->value, "asd"); |
|
|
|
|
|
|
|
// test keywords |
|
|
|
++index_in_text; |
|
|
|
|
|
|
|
result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Keyword); |
|
|
|
assert_equal_string(result->value.keyword->identifier, "key1"); |
|
|
|
|
|
|
|
++index_in_text; |
|
|
|
|
|
|
|
result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Keyword); |
|
|
|
assert_equal_string(result->value.keyword->identifier, "key:2"); |
|
|
|
|
|
|
|
// test symbols |
|
|
|
++index_in_text; |
|
|
|
|
|
|
|
result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.symbol->identifier, "sym"); |
|
|
|
|
|
|
|
++index_in_text; |
|
|
|
|
|
|
|
result = parse_atom(string, &index_in_text); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.symbol->identifier, "+"); |
|
|
|
|
|
|
|
return pass; |
|
|
|
} |
|
|
|
|
|
|
|
testresult test_parse_expression() { |
|
|
|
int index_in_text = 0; |
|
|
|
char string[] = "(fun + 12)"; |
|
|
|
|
|
|
|
Ast_Node* result = parse_expression(string, &index_in_text); |
|
|
|
assert_no_error(error); |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun"); |
|
|
|
|
|
|
|
result = result->value.pair->rest; |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.pair->first->value.symbol->identifier, "+"); |
|
|
|
|
|
|
|
result = result->value.pair->rest; |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Number); |
|
|
|
assert_equal_double(result->value.pair->first->value.number->value, 12); |
|
|
|
|
|
|
|
result = result->value.pair->rest; |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Nil); |
|
|
|
|
|
|
|
char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))"; |
|
|
|
index_in_text = 0; |
|
|
|
|
|
|
|
result = parse_expression(string2, &index_in_text); |
|
|
|
assert_no_error(error); |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.pair->first->value.symbol->identifier, "define"); |
|
|
|
|
|
|
|
result = result->value.pair->rest; |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun"); |
|
|
|
|
|
|
|
result = result->value.pair->rest; |
|
|
|
|
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Pair); |
|
|
|
assert_equal_int(result->value.pair->first->value.pair->first->type, Ast_Node_Type_Symbol); |
|
|
|
assert_equal_string(result->value.pair->first->value.pair->first->value.symbol->identifier, "lambda"); |
|
|
|
|
|
|
|
result = result->value.pair->rest; |
|
|
|
|
|
|
|
|
|
|
|
return pass; |
|
|
|
} |
|
|
|
|
|
|
|
testresult test_built_in_add() { |
|
|
|
Ast_Node* plus = create_ast_node_symbol("+"); |
|
|
|
Ast_Node* ten = create_ast_node_number(10); |
|
|
|
Ast_Node* four = create_ast_node_number(4); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
plus, |
|
|
|
create_ast_node_pair( |
|
|
|
ten, |
|
|
|
create_ast_node_pair( |
|
|
|
four, |
|
|
|
nil))); |
|
|
|
|
|
|
|
Ast_Node* result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string[] = "(+ 10 4)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -99,19 +204,9 @@ testresult test_built_in_add() { |
|
|
|
} |
|
|
|
|
|
|
|
testresult test_built_in_substract() { |
|
|
|
Ast_Node* minus = create_ast_node_symbol("-"); |
|
|
|
Ast_Node* ten = create_ast_node_number(10); |
|
|
|
Ast_Node* four = create_ast_node_number(4); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
minus, |
|
|
|
create_ast_node_pair( |
|
|
|
ten, |
|
|
|
create_ast_node_pair( |
|
|
|
four, |
|
|
|
nil))); |
|
|
|
|
|
|
|
Ast_Node* result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string[] = "(- 10 4)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -123,19 +218,9 @@ testresult test_built_in_substract() { |
|
|
|
|
|
|
|
|
|
|
|
testresult test_built_in_multiply() { |
|
|
|
Ast_Node* times = create_ast_node_symbol("*"); |
|
|
|
Ast_Node* ten = create_ast_node_number(10); |
|
|
|
Ast_Node* four = create_ast_node_number(4); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
times, |
|
|
|
create_ast_node_pair( |
|
|
|
ten, |
|
|
|
create_ast_node_pair( |
|
|
|
four, |
|
|
|
nil))); |
|
|
|
|
|
|
|
Ast_Node* result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string[] = "(* 10 4)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -147,19 +232,9 @@ testresult test_built_in_multiply() { |
|
|
|
|
|
|
|
|
|
|
|
testresult test_built_in_divide() { |
|
|
|
Ast_Node* over = create_ast_node_symbol("/"); |
|
|
|
Ast_Node* ten = create_ast_node_number(20); |
|
|
|
Ast_Node* four = create_ast_node_number(4); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
over, |
|
|
|
create_ast_node_pair( |
|
|
|
ten, |
|
|
|
create_ast_node_pair( |
|
|
|
four, |
|
|
|
nil))); |
|
|
|
|
|
|
|
Ast_Node* result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string[] = "(/ 20 4)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_null(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -171,35 +246,20 @@ testresult test_built_in_divide() { |
|
|
|
|
|
|
|
|
|
|
|
testresult test_built_in_if() { |
|
|
|
Ast_Node* _if = create_ast_node_symbol("if"); |
|
|
|
Ast_Node* cond = create_ast_node_number(1); |
|
|
|
Ast_Node* four = create_ast_node_number(4); |
|
|
|
Ast_Node* five = create_ast_node_number(5); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
_if, |
|
|
|
create_ast_node_pair( |
|
|
|
cond, |
|
|
|
create_ast_node_pair( |
|
|
|
four, |
|
|
|
create_ast_node_pair( |
|
|
|
five, |
|
|
|
nil)))); |
|
|
|
Ast_Node* result; |
|
|
|
|
|
|
|
// test *then* case |
|
|
|
result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string1[] = "(if 1 4 5)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string1); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Number); |
|
|
|
assert_equal_double(result->value.number->value, 4); |
|
|
|
|
|
|
|
// test *else* case |
|
|
|
cond->value.number->value = 0; |
|
|
|
result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string2[] = "(if () 4 5)"; |
|
|
|
expression = parse_single_expression(exp_string2); |
|
|
|
result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_null(error); |
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Number); |
|
|
|
assert_equal_double(result->value.number->value, 5); |
|
|
|
@@ -208,24 +268,9 @@ testresult test_built_in_if() { |
|
|
|
} |
|
|
|
|
|
|
|
testresult test_built_in_and() { |
|
|
|
Ast_Node* _and = create_ast_node_symbol("and"); |
|
|
|
Ast_Node* cond1 = create_ast_node_number(1); |
|
|
|
Ast_Node* cond2 = create_ast_node_string("asd"); |
|
|
|
Ast_Node* cond3 = create_ast_node_number(4); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
_and, |
|
|
|
create_ast_node_pair( |
|
|
|
cond1, |
|
|
|
create_ast_node_pair( |
|
|
|
cond2, |
|
|
|
create_ast_node_pair( |
|
|
|
cond3, |
|
|
|
nil)))); |
|
|
|
Ast_Node* result; |
|
|
|
|
|
|
|
// a true case |
|
|
|
result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string1[] = "(and 1 \"asd\" 4)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string1); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -233,8 +278,9 @@ testresult test_built_in_and() { |
|
|
|
assert_equal_double(result->value.number->value, 1); |
|
|
|
|
|
|
|
// a false case |
|
|
|
cond1->value.number->value = 0; |
|
|
|
result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string2[] = "(and () \"asd\" 4)"; |
|
|
|
expression = parse_single_expression(exp_string2); |
|
|
|
result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -244,20 +290,9 @@ testresult test_built_in_and() { |
|
|
|
} |
|
|
|
|
|
|
|
testresult test_built_in_or() { |
|
|
|
Ast_Node* _or = create_ast_node_symbol("or"); |
|
|
|
Ast_Node* cond1 = create_ast_node_nil(); |
|
|
|
Ast_Node* cond2 = create_ast_node_string("asd"); |
|
|
|
Ast_Node* nil = create_ast_node_nil(); |
|
|
|
Ast_Node* form = create_ast_node_pair( |
|
|
|
_or, |
|
|
|
create_ast_node_pair( |
|
|
|
cond1, |
|
|
|
create_ast_node_pair( |
|
|
|
cond2, nil))); |
|
|
|
Ast_Node* result; |
|
|
|
|
|
|
|
// a true case |
|
|
|
result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string1[] = "(or \"asd\" nil)"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string1); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -265,14 +300,9 @@ testresult test_built_in_or() { |
|
|
|
assert_equal_double(result->value.number->value, 1); |
|
|
|
|
|
|
|
// a false case |
|
|
|
cond2 = create_ast_node_nil(); |
|
|
|
form = create_ast_node_pair( |
|
|
|
_or, |
|
|
|
create_ast_node_pair( |
|
|
|
cond1, |
|
|
|
create_ast_node_pair( |
|
|
|
cond2, nil))); |
|
|
|
result = eval_expr(form, create_empty_environment()); |
|
|
|
char exp_string2[] = "(or () ())"; |
|
|
|
expression = parse_single_expression(exp_string2); |
|
|
|
result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
@@ -282,9 +312,37 @@ testresult test_built_in_or() { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
testresult test_built_in_not() { |
|
|
|
char exp_string1[] = "(not ())"; |
|
|
|
Ast_Node* expression = parse_single_expression(exp_string1); |
|
|
|
Ast_Node* result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
// a true case |
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Number); |
|
|
|
assert_equal_double(result->value.number->value, 1); |
|
|
|
|
|
|
|
// a false case |
|
|
|
char exp_string2[] = "(not \"asd xD\")"; |
|
|
|
expression = parse_single_expression(exp_string2); |
|
|
|
result = eval_expr(expression, create_empty_environment()); |
|
|
|
|
|
|
|
assert_no_error(error); |
|
|
|
assert_not_null(result); |
|
|
|
assert_equal_int(result->type, Ast_Node_Type_Nil); |
|
|
|
|
|
|
|
return pass; |
|
|
|
} |
|
|
|
|
|
|
|
void run_all_tests() { |
|
|
|
log_level = Log_Level_None; |
|
|
|
|
|
|
|
printf("-- Parsing --\n"); |
|
|
|
invoke_test(test_parse_atom); |
|
|
|
invoke_test(test_parse_expression); |
|
|
|
|
|
|
|
printf("\n-- Built ins --\n"); |
|
|
|
invoke_test(test_built_in_add); |
|
|
|
invoke_test(test_built_in_substract); |
|
|
|
invoke_test(test_built_in_multiply); |
|
|
|
@@ -292,5 +350,7 @@ void run_all_tests() { |
|
|
|
invoke_test(test_built_in_if); |
|
|
|
invoke_test(test_built_in_and); |
|
|
|
invoke_test(test_built_in_or); |
|
|
|
invoke_test(test_built_in_not); |
|
|
|
|
|
|
|
|
|
|
|
} |