Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

675 строки
22 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_equal_int(variable, value) \
  16. if (variable != value) { \
  17. print_assert_equal_fail(variable, value, size_t, "%zd"); \
  18. return fail; \
  19. }
  20. #define assert_not_equal_int(variable, value) \
  21. if (variable == value) { \
  22. print_assert_not_equal_fail(variable, value, size_t, "%zd"); \
  23. return fail; \
  24. }
  25. #define assert_no_error() \
  26. if (Globals::error) { \
  27. print_assert_equal_fail(Globals::error, 0, size_t, "%zd"); \
  28. printf("\nExpected no error to occur," \
  29. " but an error occured anyways:\n"); \
  30. log_error(); \
  31. return fail; \
  32. } \
  33. #define assert_error() \
  34. if (!Globals::error) { \
  35. print_assert_not_equal_fail(Globals::error, 0, size_t, "%zd"); \
  36. printf("\nExpected an error to occur," \
  37. " but no error occured:\n"); \
  38. return fail; \
  39. } \
  40. #define assert_equal_double(variable, value) \
  41. if (fabs((double)variable - (double)value) > epsilon) { \
  42. print_assert_equal_fail(variable, value, double, "%f"); \
  43. return fail; \
  44. }
  45. #define assert_not_equal_double(variable, value) \
  46. if (fabs((double)variable - (double)value) <= epsilon) { \
  47. print_assert_not_equal_fail(variable, value, double, "%f"); \
  48. return fail; \
  49. }
  50. #define assert_equal_string(variable, value) \
  51. if (!string_equal(variable, value)) { \
  52. print_assert_equal_fail(&variable->data, value, char*, "%s"); \
  53. return fail; \
  54. }
  55. #define assert_equal_type(node, _type) \
  56. if (Memory::get_type(node) != _type) { \
  57. print_assert_equal_fail( \
  58. Lisp_Object_Type_to_string(Memory::get_type(node)), \
  59. Lisp_Object_Type_to_string(_type), char*, "%s"); \
  60. return fail; \
  61. } \
  62. #define assert_null(variable) \
  63. assert_equal_int(variable, nullptr)
  64. #define assert_not_null(variable) \
  65. assert_not_equal_int(variable, nullptr)
  66. #define invoke_test(name) \
  67. fputs("" #name ":", stdout); \
  68. if (name() == pass) { \
  69. for(size_t i = strlen(#name); i < 70; ++i) \
  70. fputs((i%3==1)? "." : " ", stdout); \
  71. fputs(console_green "passed\n" console_normal, stdout); \
  72. } \
  73. else { \
  74. result = false; \
  75. for(int i = -1; i < 70; ++i) \
  76. fputs((i%3==1)? "." : " ", stdout); \
  77. fputs(console_red "failed\n" console_normal, stdout); \
  78. if(Globals::error) { \
  79. free(Globals::error); \
  80. Globals::error = nullptr; \
  81. } \
  82. } \
  83. #define invoke_test_script(name) \
  84. fputs("" name ":", stdout); \
  85. if (test_file("tests/" name ".slime") == pass) { \
  86. for(size_t i = strlen(name); i < 70; ++i) \
  87. fputs((i%3==1)? "." : " ", stdout); \
  88. fputs(console_green "passed\n" console_normal, stdout); \
  89. } \
  90. else { \
  91. result = false; \
  92. for(int i = -1; i < 70; ++i) \
  93. fputs((i%3==1)? "." : " ", stdout); \
  94. fputs(console_red "failed\n" console_normal, stdout); \
  95. if(Globals::error) { \
  96. free(Globals::error); \
  97. Globals::error = nullptr; \
  98. } \
  99. }
  100. proc test_array_lists_adding_and_removing() -> testresult {
  101. // test adding and removing
  102. Array_List<int> list;
  103. list.append(1);
  104. list.append(2);
  105. list.append(3);
  106. list.append(4);
  107. assert_equal_int(list.next_index, 4);
  108. list.remove_index(0);
  109. assert_equal_int(list.next_index, 3);
  110. assert_equal_int(list[0], 4);
  111. assert_equal_int(list[1], 2);
  112. assert_equal_int(list[2], 3);
  113. list.remove_index(2);
  114. assert_equal_int(list.next_index, 2);
  115. assert_equal_int(list[0], 4);
  116. assert_equal_int(list[1], 2);
  117. return pass;
  118. }
  119. proc test_array_lists_sorting() -> testresult {
  120. // test adding and removing
  121. Array_List<int> list;
  122. list.append(1);
  123. list.append(2);
  124. list.append(3);
  125. list.append(4);
  126. list.sort();
  127. assert_equal_int(list.next_index, 4);
  128. assert_equal_int(list[0], 1);
  129. assert_equal_int(list[1], 2);
  130. assert_equal_int(list[2], 3);
  131. assert_equal_int(list[3], 4);
  132. list.append(0);
  133. list.append(5);
  134. assert_equal_int(list.next_index, 6);
  135. list.sort();
  136. assert_equal_int(list[0], 0);
  137. assert_equal_int(list[1], 1);
  138. assert_equal_int(list[2], 2);
  139. assert_equal_int(list[3], 3);
  140. assert_equal_int(list[4], 4);
  141. assert_equal_int(list[5], 5);
  142. return pass;
  143. }
  144. proc test_array_lists_searching() -> testresult {
  145. Array_List<int> list;
  146. list.append(1);
  147. list.append(2);
  148. list.append(3);
  149. list.append(4);
  150. int index = list.sorted_find(3);
  151. assert_equal_int(index, 2);
  152. index = list.sorted_find(1);
  153. assert_equal_int(index, 0);
  154. index = list.sorted_find(5);
  155. assert_equal_int(index, -1);
  156. return pass;
  157. }
  158. proc test_eval_operands() -> testresult {
  159. char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
  160. Lisp_Object* operands = Parser::parse_single_expression(operands_string);
  161. try operands = eval_arguments(operands);
  162. assert_no_error();
  163. assert_equal_int(list_length(operands), 4);
  164. assert_equal_type(operands, Lisp_Object_Type::Pair);
  165. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::Number);
  166. assert_equal_double(operands->value.pair.first->value.number, 1);
  167. operands = operands->value.pair.rest;
  168. assert_equal_type(operands, Lisp_Object_Type::Pair);
  169. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::Number);
  170. assert_equal_double(operands->value.pair.first->value.number, 3);
  171. operands = operands->value.pair.rest;
  172. assert_equal_type(operands, Lisp_Object_Type::Pair);
  173. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::String);
  174. assert_equal_string(operands->value.pair.first->value.string, "okay");
  175. operands = operands->value.pair.rest;
  176. assert_equal_type(operands, Lisp_Object_Type::Pair);
  177. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::Keyword);
  178. assert_equal_string(operands->value.pair.first->value.symbol, "haha");
  179. return pass;
  180. }
  181. proc test_parse_atom() -> testresult {
  182. int index_in_text = 0;
  183. char string[] =
  184. "123 -1.23e-2 " // numbers
  185. "\"asd\" " // strings
  186. ":key1 :key:2 " // keywords
  187. "sym +"; // symbols
  188. // test numbers
  189. Lisp_Object* result = Parser::parse_atom(string, &index_in_text);
  190. assert_equal_type(result, Lisp_Object_Type::Number);
  191. assert_equal_double(result->value.number, 123);
  192. ++index_in_text;
  193. result = Parser::parse_atom(string, &index_in_text);
  194. assert_equal_type(result, Lisp_Object_Type::Number);
  195. assert_equal_double(result->value.number, -1.23e-2);
  196. // test strings
  197. ++index_in_text;
  198. result = Parser::parse_atom(string, &index_in_text);
  199. assert_equal_type(result, Lisp_Object_Type::String);
  200. assert_equal_string(result->value.string, "asd");
  201. // test keywords
  202. ++index_in_text;
  203. result = Parser::parse_atom(string, &index_in_text);
  204. assert_equal_type(result, Lisp_Object_Type::Keyword);
  205. assert_equal_string(result->value.symbol, "key1");
  206. ++index_in_text;
  207. result = Parser::parse_atom(string, &index_in_text);
  208. assert_equal_type(result, Lisp_Object_Type::Keyword);
  209. assert_equal_string(result->value.symbol, "key:2");
  210. // test symbols
  211. ++index_in_text;
  212. result = Parser::parse_atom(string, &index_in_text);
  213. assert_equal_type(result, Lisp_Object_Type::Symbol);
  214. assert_equal_string(result->value.symbol, "sym");
  215. ++index_in_text;
  216. result = Parser::parse_atom(string, &index_in_text);
  217. assert_equal_type(result, Lisp_Object_Type::Symbol);
  218. assert_equal_string(result->value.symbol, "+");
  219. return pass;
  220. }
  221. proc test_parse_expression() -> testresult {
  222. int index_in_text = 0;
  223. char string[] = "(fun + 12)";
  224. Lisp_Object* result = Parser::parse_expression(string, &index_in_text);
  225. assert_no_error();
  226. assert_equal_type(result, Lisp_Object_Type::Pair);
  227. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  228. assert_equal_string(result->value.pair.first->value.symbol, "fun");
  229. result = result->value.pair.rest;
  230. assert_equal_type(result, Lisp_Object_Type::Pair);
  231. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  232. assert_equal_string(result->value.pair.first->value.symbol, "+");
  233. result = result->value.pair.rest;
  234. assert_equal_type(result, Lisp_Object_Type::Pair);
  235. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Number);
  236. assert_equal_double(result->value.pair.first->value.number, 12);
  237. result = result->value.pair.rest;
  238. assert_equal_type(result, Lisp_Object_Type::Nil);
  239. char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))";
  240. index_in_text = 0;
  241. result = Parser::parse_expression(string2, &index_in_text);
  242. assert_no_error();
  243. assert_equal_type(result, Lisp_Object_Type::Pair);
  244. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  245. assert_equal_string(result->value.pair.first->value.symbol, "define");
  246. result = result->value.pair.rest;
  247. assert_equal_type(result, Lisp_Object_Type::Pair);
  248. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  249. assert_equal_string(result->value.pair.first->value.symbol, "fun");
  250. result = result->value.pair.rest;
  251. assert_equal_type(result, Lisp_Object_Type::Pair);
  252. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Pair);
  253. assert_equal_type(result->value.pair.first->value.pair.first, Lisp_Object_Type::Symbol);
  254. assert_equal_string(result->value.pair.first->value.pair.first->value.symbol, "lambda");
  255. result = result->value.pair.rest;
  256. return pass;
  257. }
  258. proc test_built_in_add() -> testresult {
  259. char exp_string[] = "(+ 10 4)";
  260. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  261. Lisp_Object* result;
  262. try result = eval_expr(expression);
  263. assert_no_error();
  264. assert_not_null(result);
  265. assert_equal_type(result, Lisp_Object_Type::Number);
  266. assert_equal_double(result->value.number, 14);
  267. return pass;
  268. }
  269. proc test_built_in_substract() -> testresult {
  270. char exp_string[] = "(- 10 4)";
  271. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  272. Lisp_Object* result;
  273. try result = eval_expr(expression);
  274. assert_no_error();
  275. assert_not_null(result);
  276. assert_equal_type(result, Lisp_Object_Type::Number);
  277. assert_equal_double(result->value.number, 6);
  278. return pass;
  279. }
  280. proc test_built_in_multiply() -> testresult {
  281. char exp_string[] = "(* 10 4)";
  282. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  283. Lisp_Object* result;
  284. try result = eval_expr(expression);
  285. assert_no_error();
  286. assert_not_null(result);
  287. assert_equal_type(result, Lisp_Object_Type::Number);
  288. assert_equal_double(result->value.number, 40);
  289. return pass;
  290. }
  291. proc test_built_in_divide() -> testresult {
  292. char exp_string[] = "(/ 20 4)";
  293. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  294. Lisp_Object* result;
  295. try result = eval_expr(expression);
  296. assert_no_error();
  297. assert_not_null(result);
  298. assert_equal_type(result, Lisp_Object_Type::Number);
  299. assert_equal_double(result->value.number, 5);
  300. return pass;
  301. }
  302. proc test_built_in_if() -> testresult {
  303. char exp_string1[] = "(if 1 4 5)";
  304. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  305. Lisp_Object* result;
  306. try result = eval_expr(expression);
  307. assert_no_error();
  308. assert_not_null(result);
  309. assert_equal_type(result, Lisp_Object_Type::Number);
  310. assert_equal_double(result->value.number, 4);
  311. char exp_string2[] = "(if () 4 5)";
  312. expression = Parser::parse_single_expression(exp_string2);
  313. try result = eval_expr(expression);
  314. assert_no_error();
  315. assert_not_null(result);
  316. assert_equal_type(result, Lisp_Object_Type::Number);
  317. assert_equal_double(result->value.number, 5);
  318. return pass;
  319. }
  320. proc test_built_in_and() -> testresult {
  321. char exp_string1[] = "(and 1 \"asd\" 4)";
  322. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  323. Lisp_Object* result;
  324. try result = eval_expr(expression);
  325. assert_no_error();
  326. assert_not_null(result);
  327. assert_equal_type(result, Lisp_Object_Type::T);
  328. // a false case
  329. char exp_string2[] = "(and () \"asd\" 4)";
  330. expression = Parser::parse_single_expression(exp_string2);
  331. try result = eval_expr(expression);
  332. assert_no_error();
  333. assert_not_null(result);
  334. assert_equal_type(result, Lisp_Object_Type::Nil);
  335. return pass;
  336. }
  337. proc test_built_in_or() -> testresult {
  338. char exp_string1[] = "(or \"asd\" nil)";
  339. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  340. Lisp_Object* result;
  341. try result = eval_expr(expression);
  342. assert_no_error();
  343. assert_not_null(result);
  344. assert_equal_type(result, Lisp_Object_Type::T);
  345. // a false case
  346. char exp_string2[] = "(or () ())";
  347. expression = Parser::parse_single_expression(exp_string2);
  348. try result = eval_expr(expression);
  349. assert_no_error();
  350. assert_not_null(result);
  351. assert_equal_type(result, Lisp_Object_Type::Nil);
  352. return pass;
  353. }
  354. proc test_built_in_not() -> testresult {
  355. char exp_string1[] = "(not ())";
  356. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  357. Lisp_Object* result;
  358. try result = eval_expr(expression);
  359. // a true case
  360. assert_no_error();
  361. assert_not_null(result);
  362. assert_equal_type(result, Lisp_Object_Type::T);
  363. // a false case
  364. char exp_string2[] = "(not \"asd xD\")";
  365. expression = Parser::parse_single_expression(exp_string2);
  366. try result = eval_expr(expression);
  367. assert_no_error();
  368. assert_not_null(result);
  369. assert_equal_type(result, Lisp_Object_Type::Nil);
  370. return pass;
  371. }
  372. proc test_built_in_type() -> testresult {
  373. // Environment* env;
  374. // try env = get_root_environment();
  375. // normal type testing
  376. char exp_string1[] = "(begin (define a 10)(type a))";
  377. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  378. Lisp_Object* result = eval_expr(expression);
  379. assert_no_error();
  380. assert_not_null(result);
  381. assert_equal_type(result, Lisp_Object_Type::Keyword);
  382. assert_equal_string(result->value.symbol, "number");
  383. // setting user type
  384. char exp_string2[] = "(begin (set-type! a :my-type)(type a))";
  385. expression = Parser::parse_single_expression(exp_string2);
  386. result = eval_expr(expression);
  387. assert_no_error();
  388. assert_not_null(result);
  389. assert_equal_type(result, Lisp_Object_Type::Keyword);
  390. assert_equal_string(result->value.symbol, "my-type");
  391. // // trying to set invalid user type
  392. // char exp_string3[] = "(begin (set-type! a \"wrong tpye\")(type a))";
  393. // expression = Parser::parse_single_expression(exp_string3);
  394. // assert_no_error();
  395. // ignore_logging {
  396. // dont_break_on_errors {
  397. // result = eval_expr(expression);
  398. // }
  399. // }
  400. // assert_error();
  401. // delete_error();
  402. // deleting user type
  403. char exp_string4[] = "(begin (delete-type! a)(type a))";
  404. expression = Parser::parse_single_expression(exp_string4);
  405. result = eval_expr(expression);
  406. assert_no_error();
  407. assert_not_null(result);
  408. assert_equal_type(result, Lisp_Object_Type::Keyword);
  409. assert_equal_string(result->value.symbol, "number");
  410. return pass;
  411. }
  412. proc test_singular_t_and_nil() -> testresult {
  413. // nil testing
  414. char exp_string1[] = "()";
  415. char exp_string2[] = "nil";
  416. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  417. Lisp_Object* result = eval_expr(expression);
  418. assert_no_error();
  419. assert_not_null(result);
  420. assert_equal_type(result, Lisp_Object_Type::Nil);
  421. assert_equal_int(expression, result);
  422. Lisp_Object* expression2 = Parser::parse_single_expression(exp_string2);
  423. Lisp_Object* result2 = eval_expr(expression2);
  424. assert_no_error();
  425. assert_not_null(result);
  426. assert_equal_type(result, Lisp_Object_Type::Nil);
  427. assert_equal_int(result, result2);
  428. assert_equal_int(expression, Memory::nil);
  429. // t testing
  430. char exp_string3[] = "t";
  431. Lisp_Object* expression3 = Parser::parse_single_expression(exp_string3);
  432. Lisp_Object* result3 = eval_expr(expression3);
  433. assert_no_error();
  434. assert_not_null(result3);
  435. return pass;
  436. }
  437. proc test_singular_symbols() -> testresult {
  438. auto cc_s_aa = Memory::get_or_create_lisp_object_symbol("aa");
  439. auto cc_s_aa2 = Memory::get_or_create_lisp_object_symbol("aa2");
  440. auto s_s_aa = Memory::get_or_create_lisp_object_symbol(Memory::create_string("aa"));
  441. auto s_s_aa2 = Memory::get_or_create_lisp_object_symbol(Memory::create_string("aa2"));
  442. assert_equal_int(cc_s_aa, s_s_aa);
  443. assert_equal_int(cc_s_aa2, s_s_aa2);
  444. assert_not_equal_int(cc_s_aa, cc_s_aa2);
  445. return pass;
  446. }
  447. proc test_file(const char* file) -> testresult {
  448. Memory::reset();
  449. assert_no_error();
  450. Environment* root_env = get_root_environment();
  451. Environment* user_env = Memory::create_child_environment(root_env);
  452. assert_no_error();
  453. push_environment(user_env);
  454. defer {
  455. pop_environment();
  456. };
  457. try built_in_load(Memory::create_string(file));
  458. assert_no_error();
  459. return pass;
  460. }
  461. proc run_all_tests() -> bool {
  462. bool result = true;
  463. try Memory::init(409600);
  464. printf("-- Util --\n");
  465. // invoke_test(test_array_lists_adding_and_removing);
  466. // invoke_test(test_array_lists_sorting);
  467. // invoke_test(test_array_lists_searching);
  468. printf("\n -- Parsing --\n");
  469. invoke_test(test_parse_atom);
  470. invoke_test(test_parse_expression);
  471. printf("\n-- Basic evaluating --\n");
  472. invoke_test(test_eval_operands);
  473. printf("\n-- Built ins --\n");
  474. invoke_test(test_built_in_add);
  475. invoke_test(test_built_in_substract);
  476. invoke_test(test_built_in_multiply);
  477. invoke_test(test_built_in_divide);
  478. invoke_test(test_built_in_if);
  479. invoke_test(test_built_in_and);
  480. invoke_test(test_built_in_or);
  481. invoke_test(test_built_in_not);
  482. invoke_test(test_built_in_type);
  483. printf("\n-- Memory management --\n");
  484. invoke_test(test_singular_t_and_nil);
  485. invoke_test(test_singular_symbols);
  486. printf("\n-- Test Files --\n");
  487. invoke_test_script("evaluation_of_default_args");
  488. invoke_test_script("alists");
  489. invoke_test_script("case_and_cond");
  490. invoke_test_script("lexical_scope");
  491. invoke_test_script("class_macro");
  492. invoke_test_script("import_and_load");
  493. invoke_test_script("macro_expand");
  494. invoke_test_script("automata");
  495. invoke_test_script("sicp");
  496. invoke_test_script("hashmaps");
  497. invoke_test_script("singular_imports");
  498. // // Memory::print_status();
  499. return result;
  500. }
  501. #undef epsilon
  502. #undef testresult
  503. #undef pass
  504. #undef fail
  505. #undef print_assert_equal_fail
  506. #undef print_assert_not_equal_fail
  507. #undef assert_no_error
  508. #undef assert_equal_int
  509. #undef assert_not_equal_int
  510. #undef assert_equal_double
  511. #undef assert_not_equal_double
  512. #undef assert_equal_string
  513. #undef assert_equal_type
  514. #undef assert_null
  515. #undef assert_not_null
  516. #undef invoke_test
  517. #undef invoke_test_script