您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

415 行
15 KiB

  1. #define epsilon 2.2204460492503131E-16
  2. #define testresult int
  3. #define pass 1
  4. #define fail 0
  5. #define print_assert_equal_fail(variable, value, type, format) \
  6. printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
  7. "\n\texpected: " format \
  8. "\n\tgot: " format "\n", \
  9. __FILE__, __LINE__, (type)value, (type)variable)
  10. #define print_assert_not_equal_fail(variable, value, type, format) \
  11. printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
  12. "\n\texpected not: " format \
  13. "\n\tgot anyways: " format "\n", \
  14. __FILE__, __LINE__, (type)value, (type)variable)
  15. #define assert_no_error(error) \
  16. if (error) { \
  17. printf("\nExpected no error to occur," \
  18. " but an error occured anyways:\n"); \
  19. log_error(); \
  20. return fail; \
  21. } \
  22. #define assert_equal_int(variable, value) \
  23. if (variable != value) { \
  24. print_assert_equal_fail(variable, value, size_t, "%zd"); \
  25. return fail; \
  26. }
  27. #define assert_not_equal_int(variable, value) \
  28. if (variable == value) { \
  29. print_assert_not_equal_fail(variable, value, size_t, "%zd"); \
  30. return fail; \
  31. }
  32. #define assert_equal_double(variable, value) \
  33. if (fabs((double)variable - (double)value) > epsilon) { \
  34. print_assert_equal_fail(variable, value, double, "%f"); \
  35. return fail; \
  36. }
  37. #define assert_not_equal_double(variable, value) \
  38. if (fabs((double)variable - (double)value) <= epsilon) { \
  39. print_assert_not_equal_fail(variable, value, double, "%f"); \
  40. return fail; \
  41. }
  42. #define assert_equal_string(variable, value) \
  43. if (!string_equal(variable, value)) { \
  44. print_assert_equal_fail(&variable->data, value, char*, "%s"); \
  45. return fail; \
  46. }
  47. #define assert_equal_type(node, _type) \
  48. if (node->type != _type) { \
  49. print_assert_equal_fail( \
  50. Lisp_Object_Type_to_string(node->type), \
  51. Lisp_Object_Type_to_string(_type), char*, "%s"); \
  52. return fail; \
  53. } \
  54. #define assert_null(variable) \
  55. assert_equal_int(variable, nullptr)
  56. #define assert_not_null(variable) \
  57. assert_not_equal_int(variable, nullptr)
  58. #define invoke_test(name) \
  59. printf("" #name ":"); \
  60. if (name() == pass) { \
  61. for(size_t i = strlen(#name); i < 70; ++i) \
  62. printf((i%3==1)? "." : " "); \
  63. printf("%spassed%s\n", console_green, console_normal); \
  64. } \
  65. else { \
  66. for(int i = -1; i < 70; ++i) \
  67. printf((i%3==1)? "." : " "); \
  68. printf("%sfailed%s\n", console_red, console_normal); \
  69. if(error) { \
  70. free(error); \
  71. error = nullptr; \
  72. } \
  73. } \
  74. proc test_eval_operands() -> testresult {
  75. char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
  76. Lisp_Object* operands = Parser::parse_single_expression(operands_string);
  77. int operands_length;
  78. operands = eval_arguments(operands, Memory::create_built_ins_environment(), &operands_length);
  79. assert_no_error(error);
  80. assert_equal_int(list_length(operands), 4);
  81. assert_equal_type(operands, Lisp_Object_Type::Pair);
  82. assert_equal_type(operands->value.pair->first, Lisp_Object_Type::Number);
  83. assert_equal_double(operands->value.pair->first->value.number->value, 1);
  84. operands = operands->value.pair->rest;
  85. assert_equal_type(operands, Lisp_Object_Type::Pair);
  86. assert_equal_type(operands->value.pair->first, Lisp_Object_Type::Number);
  87. assert_equal_double(operands->value.pair->first->value.number->value, 3);
  88. operands = operands->value.pair->rest;
  89. assert_equal_type(operands, Lisp_Object_Type::Pair);
  90. assert_equal_type(operands->value.pair->first, Lisp_Object_Type::String);
  91. assert_equal_string(operands->value.pair->first->value.string, "okay");
  92. operands = operands->value.pair->rest;
  93. assert_equal_type(operands, Lisp_Object_Type::Pair);
  94. assert_equal_type(operands->value.pair->first, Lisp_Object_Type::Keyword);
  95. assert_equal_string(operands->value.pair->first->value.keyword->identifier, "haha");
  96. return pass;
  97. }
  98. proc test_parse_atom() -> testresult {
  99. int index_in_text = 0;
  100. char string[] =
  101. "123 -1.23e-2 " // numbers
  102. "\"asd\" " // strings
  103. ":key1 :key:2 " // keywords
  104. "sym +"; // symbols
  105. // test numbers
  106. Lisp_Object* result = Parser::parse_atom(string, &index_in_text);
  107. assert_equal_type(result, Lisp_Object_Type::Number);
  108. assert_equal_double(result->value.number->value, 123);
  109. ++index_in_text;
  110. result = Parser::parse_atom(string, &index_in_text);
  111. assert_equal_type(result, Lisp_Object_Type::Number);
  112. assert_equal_double(result->value.number->value, -1.23e-2);
  113. // test strings
  114. ++index_in_text;
  115. result = Parser::parse_atom(string, &index_in_text);
  116. assert_equal_type(result, Lisp_Object_Type::String);
  117. assert_equal_string(result->value.string, "asd");
  118. // test keywords
  119. ++index_in_text;
  120. result = Parser::parse_atom(string, &index_in_text);
  121. assert_equal_type(result, Lisp_Object_Type::Keyword);
  122. assert_equal_string(result->value.keyword->identifier, "key1");
  123. ++index_in_text;
  124. result = Parser::parse_atom(string, &index_in_text);
  125. assert_equal_type(result, Lisp_Object_Type::Keyword);
  126. assert_equal_string(result->value.keyword->identifier, "key:2");
  127. // test symbols
  128. ++index_in_text;
  129. result = Parser::parse_atom(string, &index_in_text);
  130. assert_equal_type(result, Lisp_Object_Type::Symbol);
  131. assert_equal_string(result->value.symbol->identifier, "sym");
  132. ++index_in_text;
  133. result = Parser::parse_atom(string, &index_in_text);
  134. assert_equal_type(result, Lisp_Object_Type::Symbol);
  135. assert_equal_string(result->value.symbol->identifier, "+");
  136. return pass;
  137. }
  138. proc test_parse_expression() -> testresult {
  139. int index_in_text = 0;
  140. char string[] = "(fun + 12)";
  141. Lisp_Object* result = Parser::parse_expression(string, &index_in_text);
  142. assert_no_error(error);
  143. assert_equal_type(result, Lisp_Object_Type::Pair);
  144. assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol);
  145. assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun");
  146. result = result->value.pair->rest;
  147. assert_equal_type(result, Lisp_Object_Type::Pair);
  148. assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol);
  149. assert_equal_string(result->value.pair->first->value.symbol->identifier, "+");
  150. result = result->value.pair->rest;
  151. assert_equal_type(result, Lisp_Object_Type::Pair);
  152. assert_equal_type(result->value.pair->first, Lisp_Object_Type::Number);
  153. assert_equal_double(result->value.pair->first->value.number->value, 12);
  154. result = result->value.pair->rest;
  155. assert_equal_type(result, Lisp_Object_Type::Nil);
  156. char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))";
  157. index_in_text = 0;
  158. result = Parser::parse_expression(string2, &index_in_text);
  159. assert_no_error(error);
  160. assert_equal_type(result, Lisp_Object_Type::Pair);
  161. assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol);
  162. assert_equal_string(result->value.pair->first->value.symbol->identifier, "define");
  163. result = result->value.pair->rest;
  164. assert_equal_type(result, Lisp_Object_Type::Pair);
  165. assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol);
  166. assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun");
  167. result = result->value.pair->rest;
  168. assert_equal_type(result, Lisp_Object_Type::Pair);
  169. assert_equal_type(result->value.pair->first, Lisp_Object_Type::Pair);
  170. assert_equal_type(result->value.pair->first->value.pair->first, Lisp_Object_Type::Symbol);
  171. assert_equal_string(result->value.pair->first->value.pair->first->value.symbol->identifier, "lambda");
  172. result = result->value.pair->rest;
  173. return pass;
  174. }
  175. proc test_built_in_add() -> testresult {
  176. char exp_string[] = "(+ 10 4)";
  177. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  178. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  179. assert_no_error(error);
  180. assert_not_null(result);
  181. assert_equal_type(result, Lisp_Object_Type::Number);
  182. assert_equal_double(result->value.number->value, 14);
  183. return pass;
  184. }
  185. proc test_built_in_substract() -> testresult {
  186. char exp_string[] = "(- 10 4)";
  187. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  188. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  189. assert_no_error(error);
  190. assert_not_null(result);
  191. assert_equal_type(result, Lisp_Object_Type::Number);
  192. assert_equal_double(result->value.number->value, 6);
  193. return pass;
  194. }
  195. proc test_built_in_multiply() -> testresult {
  196. char exp_string[] = "(* 10 4)";
  197. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  198. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  199. assert_no_error(error);
  200. assert_not_null(result);
  201. assert_equal_type(result, Lisp_Object_Type::Number);
  202. assert_equal_double(result->value.number->value, 40);
  203. return pass;
  204. }
  205. proc test_built_in_divide() -> testresult {
  206. char exp_string[] = "(/ 20 4)";
  207. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  208. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  209. assert_null(error);
  210. assert_not_null(result);
  211. assert_equal_type(result, Lisp_Object_Type::Number);
  212. assert_equal_double(result->value.number->value, 5);
  213. return pass;
  214. }
  215. proc test_built_in_if() -> testresult {
  216. char exp_string1[] = "(if 1 4 5)";
  217. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  218. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  219. assert_no_error(error);
  220. assert_not_null(result);
  221. assert_equal_type(result, Lisp_Object_Type::Number);
  222. assert_equal_double(result->value.number->value, 4);
  223. char exp_string2[] = "(if () 4 5)";
  224. expression = Parser::parse_single_expression(exp_string2);
  225. result = eval_expr(expression, Memory::create_built_ins_environment());
  226. assert_no_error(error);
  227. assert_not_null(result);
  228. assert_equal_type(result, Lisp_Object_Type::Number);
  229. assert_equal_double(result->value.number->value, 5);
  230. return pass;
  231. }
  232. proc test_built_in_and() -> testresult {
  233. char exp_string1[] = "(and 1 \"asd\" 4)";
  234. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  235. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  236. assert_no_error(error);
  237. assert_not_null(result);
  238. assert_equal_type(result, Lisp_Object_Type::T);
  239. // a false case
  240. char exp_string2[] = "(and () \"asd\" 4)";
  241. expression = Parser::parse_single_expression(exp_string2);
  242. result = eval_expr(expression, Memory::create_built_ins_environment());
  243. assert_no_error(error);
  244. assert_not_null(result);
  245. assert_equal_type(result, Lisp_Object_Type::Nil);
  246. return pass;
  247. }
  248. proc test_built_in_or() -> testresult {
  249. char exp_string1[] = "(or \"asd\" nil)";
  250. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  251. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  252. assert_no_error(error);
  253. assert_not_null(result);
  254. assert_equal_type(result, Lisp_Object_Type::T);
  255. // a false case
  256. char exp_string2[] = "(or () ())";
  257. expression = Parser::parse_single_expression(exp_string2);
  258. result = eval_expr(expression, Memory::create_built_ins_environment());
  259. assert_no_error(error);
  260. assert_not_null(result);
  261. assert_equal_type(result, Lisp_Object_Type::Nil);
  262. return pass;
  263. }
  264. proc test_built_in_not() -> testresult {
  265. char exp_string1[] = "(not ())";
  266. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  267. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  268. // a true case
  269. assert_no_error(error);
  270. assert_not_null(result);
  271. assert_equal_type(result, Lisp_Object_Type::T);
  272. // a false case
  273. char exp_string2[] = "(not \"asd xD\")";
  274. expression = Parser::parse_single_expression(exp_string2);
  275. result = eval_expr(expression, Memory::create_built_ins_environment());
  276. assert_no_error(error);
  277. assert_not_null(result);
  278. assert_equal_type(result, Lisp_Object_Type::Nil);
  279. return pass;
  280. }
  281. proc run_all_tests() -> void {
  282. log_level = Log_Level::None;
  283. Memory::init();
  284. Parser::init(Memory::create_built_ins_environment());
  285. printf("-- Parsing --\n");
  286. invoke_test(test_parse_atom);
  287. invoke_test(test_parse_expression);
  288. printf("\n-- Basic evaluating --\n");
  289. invoke_test(test_eval_operands);
  290. printf("\n-- Built ins --\n");
  291. invoke_test(test_built_in_add);
  292. invoke_test(test_built_in_substract);
  293. invoke_test(test_built_in_multiply);
  294. invoke_test(test_built_in_divide);
  295. invoke_test(test_built_in_if);
  296. invoke_test(test_built_in_and);
  297. invoke_test(test_built_in_or);
  298. invoke_test(test_built_in_not);
  299. }
  300. #undef epsilon
  301. #undef testresult
  302. #undef pass
  303. #undef fail
  304. #undef print_assert_equal_fail
  305. #undef print_assert_not_equal_fail
  306. #undef assert_no_error
  307. #undef assert_equal_int
  308. #undef assert_not_equal_int
  309. #undef assert_equal_double
  310. #undef assert_not_equal_double
  311. #undef assert_equal_string
  312. #undef assert_equal_type
  313. #undef assert_null
  314. #undef assert_not_null
  315. #undef invoke_test