You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

examples.t.c 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #ifdef __unix__
  2. #include "vm/vm.h"
  3. #include "parse/parse.h"
  4. #include <sys/types.h>
  5. #include <libgen.h>
  6. #include <dirent.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #include <snow/snow.h>
  11. static char example_path[512];
  12. static char example_expected_path[512];
  13. static char example_actual_path[512];
  14. static char *error_message = NULL;
  15. static void check_diff(const char *expected, const char *actual) {
  16. FILE *e = fopen(expected, "r");
  17. if (e == NULL) {
  18. snow_fail("%s: %s\n Actual result stored in %s", expected, strerror(errno), actual);
  19. }
  20. FILE *a = fopen(actual, "r");
  21. if (a == NULL) {
  22. fclose(e);
  23. snow_fail("%s: %s", actual, strerror(errno));
  24. }
  25. int line = 1;
  26. int ch = 1;
  27. while (1) {
  28. int ech = fgetc(e);
  29. int ach = fgetc(a);
  30. if (ech != ach) {
  31. fclose(e);
  32. fclose(a);
  33. snow_fail("%s differs at location %i:%i:\n Expected %c(%i), got %c(%i)",
  34. actual, line, ch, ech, ech, ach, ach);
  35. }
  36. if (ech == EOF) {
  37. break;
  38. }
  39. if (ech == '\n') {
  40. line += 1;
  41. ch = 1;
  42. } else {
  43. ch += 1;
  44. }
  45. }
  46. fclose(e);
  47. fclose(a);
  48. }
  49. static void check_impl(const char *name) {
  50. char fname[] = __FILE__;
  51. char *dname = dirname(fname);
  52. snprintf(example_path, sizeof(example_path), "%s/../examples/%s", dname, name);
  53. snprintf(example_expected_path, sizeof(example_path), "%s/../examples/%s.expected", dname, name);
  54. snprintf(example_actual_path, sizeof(example_path), "%s/../examples/%s.actual", dname, name);
  55. FILE *inf = fopen(example_path, "r");
  56. if (inf == NULL) {
  57. snow_fail("%s: %s", example_path, strerror(errno));
  58. }
  59. struct l2_io_file_reader input ={
  60. .r.read = l2_io_file_read,
  61. .f = inf,
  62. };
  63. struct l2_io_mem_writer bytecode = {
  64. .w.write = l2_io_mem_write,
  65. };
  66. struct l2_lexer lexer;
  67. l2_lexer_init(&lexer, &input.r);
  68. struct l2_generator gen;
  69. l2_gen_init(&gen, &bytecode.w);
  70. struct l2_parse_error err;
  71. if (l2_parse_program(&lexer, &gen, &err) < 0) {
  72. free(bytecode.mem);
  73. fclose(input.f);
  74. error_message = err.message;
  75. snow_fail("%s:%i:%i: %s", example_path, err.line, err.ch, err.message);
  76. }
  77. l2_gen_free(&gen);
  78. fclose(inf);
  79. FILE *outf = fopen(example_actual_path, "w");
  80. if (outf == NULL) {
  81. snow_fail("%s: %s", example_actual_path, strerror(errno));
  82. }
  83. struct l2_io_file_writer output = {
  84. .w.write = l2_io_file_write,
  85. .f = outf,
  86. };
  87. struct l2_vm vm;
  88. l2_vm_init(&vm, bytecode.mem, bytecode.len / sizeof(l2_word));
  89. vm.std_output = &output.w;
  90. // Run a GC after every instruction to uncover potential GC issues
  91. while (!vm.halted) {
  92. l2_vm_step(&vm);
  93. l2_vm_gc(&vm);
  94. }
  95. l2_vm_free(&vm);
  96. free(bytecode.mem);
  97. fclose(output.f);
  98. check_diff(example_expected_path, example_actual_path);
  99. }
  100. #define check(name) do { \
  101. snow_fail_update(); \
  102. test(name) { check_impl(name); } \
  103. } while (0)
  104. describe(exaples) {
  105. check("namespaces.l2");
  106. check("arrays.l2");
  107. check("functions.l2");
  108. check("dynamic-lookups.l2");
  109. check("builtins.l2");
  110. if (error_message != NULL) {
  111. free(error_message);
  112. }
  113. }
  114. #endif