summaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-07-17 23:21:03 +0200
committerJo-Philipp Wich <jo@mein.io>2022-07-30 13:46:23 +0200
commit10e056d3744384a029f05de5903c489898722fc3 (patch)
treee6621194f1053fdc314dfee02358972028a6a5ff /tests
parent862e49de33bd07daea129d553968579019c79b59 (diff)
compiler: add support for import/export statements
This commit introduces syntax level support for ES6 style module import and export statements. Imports are resolved at compile time and the corresponding module code is compiled into the main program. Also add testcases to cover import and export statement semantics. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/custom/04_modules/01_export_variable_declaration29
-rw-r--r--tests/custom/04_modules/02_export_function_declaration22
-rw-r--r--tests/custom/04_modules/03_export_list27
-rw-r--r--tests/custom/04_modules/04_export_rename28
-rw-r--r--tests/custom/04_modules/05_export_default38
-rw-r--r--tests/custom/04_modules/06_export_errors89
-rw-r--r--tests/custom/04_modules/07_import_default99
-rw-r--r--tests/custom/04_modules/08_import_list105
-rw-r--r--tests/custom/04_modules/09_import_wildcard73
-rw-r--r--tests/custom/04_modules/10_import_none18
-rw-r--r--tests/custom/04_modules/11_import_many_exec_once28
-rw-r--r--tests/custom/04_modules/12_import_immutability52
-rw-r--r--tests/custom/04_modules/13_import_liveness29
-rw-r--r--tests/custom/99_bugs/01_try_catch_stack_mismatch (renamed from tests/custom/04_bugs/01_try_catch_stack_mismatch)0
-rw-r--r--tests/custom/99_bugs/02_array_pop_use_after_free (renamed from tests/custom/04_bugs/02_array_pop_use_after_free)0
-rw-r--r--tests/custom/99_bugs/03_switch_fallthrough_miscompilation (renamed from tests/custom/04_bugs/03_switch_fallthrough_miscompilation)0
-rw-r--r--tests/custom/99_bugs/04_property_set_abort (renamed from tests/custom/04_bugs/04_property_set_abort)0
-rw-r--r--tests/custom/99_bugs/05_duplicate_resource_type (renamed from tests/custom/04_bugs/05_duplicate_resource_type)0
-rw-r--r--tests/custom/99_bugs/06_lexer_escape_at_boundary (renamed from tests/custom/04_bugs/06_lexer_escape_at_boundary)0
-rw-r--r--tests/custom/99_bugs/07_lexer_overlong_lines (renamed from tests/custom/04_bugs/07_lexer_overlong_lines)0
-rw-r--r--tests/custom/99_bugs/08_compiler_arrow_fn_expressions (renamed from tests/custom/04_bugs/08_compiler_arrow_fn_expressions)0
-rw-r--r--tests/custom/99_bugs/09_reject_invalid_array_indexes (renamed from tests/custom/04_bugs/09_reject_invalid_array_indexes)0
-rw-r--r--tests/custom/99_bugs/10_break_stack_mismatch (renamed from tests/custom/04_bugs/10_break_stack_mismatch)0
-rw-r--r--tests/custom/99_bugs/11_switch_stack_mismatch (renamed from tests/custom/04_bugs/11_switch_stack_mismatch)0
-rw-r--r--tests/custom/99_bugs/12_altblock_stack_mismatch (renamed from tests/custom/04_bugs/12_altblock_stack_mismatch)0
-rw-r--r--tests/custom/99_bugs/13_split_by_string_leading_trailing (renamed from tests/custom/04_bugs/13_split_by_string_leading_trailing)0
-rw-r--r--tests/custom/99_bugs/14_incomplete_expression_at_eof (renamed from tests/custom/04_bugs/14_incomplete_expression_at_eof)0
-rw-r--r--tests/custom/99_bugs/15_segfault_on_prefix_increment (renamed from tests/custom/04_bugs/15_segfault_on_prefix_increment)0
-rw-r--r--tests/custom/99_bugs/16_hang_on_regexp_at_eof (renamed from tests/custom/04_bugs/16_hang_on_regexp_at_eof)0
-rw-r--r--tests/custom/99_bugs/17_hang_on_unclosed_expression_block (renamed from tests/custom/04_bugs/17_hang_on_unclosed_expression_block)0
-rw-r--r--tests/custom/99_bugs/18_hang_on_line_comments_at_eof (renamed from tests/custom/04_bugs/18_hang_on_line_comments_at_eof)0
-rw-r--r--tests/custom/99_bugs/19_truncated_format_string (renamed from tests/custom/04_bugs/19_truncated_format_string)0
-rw-r--r--tests/custom/99_bugs/20_use_strict_stack_mismatch (renamed from tests/custom/04_bugs/20_use_strict_stack_mismatch)0
-rw-r--r--tests/custom/99_bugs/21_compiler_parenthesized_prop_keyword (renamed from tests/custom/04_bugs/21_compiler_parenthesized_prop_keyword)0
-rw-r--r--tests/custom/99_bugs/22_compiler_break_continue_scoping (renamed from tests/custom/04_bugs/22_compiler_break_continue_scoping)0
-rw-r--r--tests/custom/99_bugs/23_compiler_parenthesized_division (renamed from tests/custom/04_bugs/23_compiler_parenthesized_division)0
-rw-r--r--tests/custom/99_bugs/24_compiler_local_for_loop_declaration (renamed from tests/custom/04_bugs/24_compiler_local_for_loop_declaration)0
-rw-r--r--tests/custom/99_bugs/25_lexer_shifted_offsets (renamed from tests/custom/04_bugs/25_lexer_shifted_offsets)0
-rw-r--r--tests/custom/99_bugs/26_compiler_jmp_to_zero (renamed from tests/custom/04_bugs/26_compiler_jmp_to_zero)0
-rw-r--r--tests/custom/99_bugs/27_invalid_sparse_array_set (renamed from tests/custom/04_bugs/27_invalid_sparse_array_set)0
-rw-r--r--tests/custom/99_bugs/28_null_equality (renamed from tests/custom/04_bugs/28_null_equality)0
-rw-r--r--tests/custom/99_bugs/29_empty_string_as_number (renamed from tests/custom/04_bugs/29_empty_string_as_number)0
-rw-r--r--tests/custom/99_bugs/30_nan_strict_equality (renamed from tests/custom/04_bugs/30_nan_strict_equality)0
-rw-r--r--tests/custom/99_bugs/31_vallist_8bit_shortstrings (renamed from tests/custom/04_bugs/31_vallist_8bit_shortstrings)0
-rw-r--r--tests/custom/99_bugs/32_compiler_switch_patchlist_corruption (renamed from tests/custom/04_bugs/32_compiler_switch_patchlist_corruption)0
-rw-r--r--tests/custom/99_bugs/33_vm_computed_prop_decl_crash (renamed from tests/custom/04_bugs/33_vm_computed_prop_decl_crash)0
-rw-r--r--tests/custom/99_bugs/34_dirname_off_by_one (renamed from tests/custom/04_bugs/34_dirname_off_by_one)0
-rw-r--r--tests/custom/99_bugs/35_vm_callframe_double_free (renamed from tests/custom/04_bugs/35_vm_callframe_double_free)0
-rw-r--r--tests/custom/99_bugs/36_vm_nested_call_return (renamed from tests/custom/04_bugs/36_vm_nested_call_return)0
-rw-r--r--tests/custom/99_bugs/37_compiler_unexpected_unary_op (renamed from tests/custom/04_bugs/37_compiler_unexpected_unary_op)0
-rw-r--r--tests/custom/99_bugs/38_index_segfault (renamed from tests/custom/04_bugs/38_index_segfault)0
-rw-r--r--tests/custom/99_bugs/39_compiler_switch_continue_mismatch (renamed from tests/custom/04_bugs/39_compiler_switch_continue_mismatch)0
-rw-r--r--tests/custom/99_bugs/40_lexer_bug_on_lstrip_off (renamed from tests/custom/04_bugs/40_lexer_bug_on_lstrip_off)0
53 files changed, 637 insertions, 0 deletions
diff --git a/tests/custom/04_modules/01_export_variable_declaration b/tests/custom/04_modules/01_export_variable_declaration
new file mode 100644
index 0000000..19a1c11
--- /dev/null
+++ b/tests/custom/04_modules/01_export_variable_declaration
@@ -0,0 +1,29 @@
+Variable declarations can be prepended with `export` to automatically
+export each variable using the same name as the variable itself.
+
+Updates to the variable after the export are reflected properly in
+the including scope.
+
+-- File test-var-decl.uc --
+export let a, b, c;
+export let d = 4, e = 5, f = 6;
+export const g = 7, h = 8, i = 9;
+
+a = 1;
+b = 2;
+c = 3;
+-- End --
+
+-- Testcase --
+import { a, b, c, d, e, f, g, h, i } from "./files/test-var-decl.uc";
+
+print([ a, b, c, d, e, f, g, h, i ], "\n");
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+-- End --
diff --git a/tests/custom/04_modules/02_export_function_declaration b/tests/custom/04_modules/02_export_function_declaration
new file mode 100644
index 0000000..4067da9
--- /dev/null
+++ b/tests/custom/04_modules/02_export_function_declaration
@@ -0,0 +1,22 @@
+A named function declaration can be prepended with `export` to
+automatically export the function.
+
+-- File test-func-decl.uc --
+export function func() {
+ print("Hello, world!\n");
+};
+-- End --
+
+-- Testcase --
+import { func } from "./files/test-func-decl.uc";
+
+func();
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+Hello, world!
+-- End --
diff --git a/tests/custom/04_modules/03_export_list b/tests/custom/04_modules/03_export_list
new file mode 100644
index 0000000..8f93f08
--- /dev/null
+++ b/tests/custom/04_modules/03_export_list
@@ -0,0 +1,27 @@
+Already declared local variables and functions may be exported using the
+curly brace export list syntax.
+
+-- File test-var-decl.uc --
+let testvar = 123;
+const testconst = "Test";
+
+function testfunc() {
+ print("Hello, world!\n");
+}
+
+export { testvar, testconst, testfunc };
+-- End --
+
+-- Testcase --
+import { testvar, testconst, testfunc } from "./files/test-var-decl.uc";
+
+print([ testvar, testconst, testfunc ], "\n");
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 123, "Test", "function testfunc() { ... }" ]
+-- End --
diff --git a/tests/custom/04_modules/04_export_rename b/tests/custom/04_modules/04_export_rename
new file mode 100644
index 0000000..49057fd
--- /dev/null
+++ b/tests/custom/04_modules/04_export_rename
@@ -0,0 +1,28 @@
+By using the `as` keyword, exports may be renamed when using the export
+list syntax. It is also possible to specify string aliases which are not
+valid variable names, in this case a rename on import is mandatory.
+
+-- File test.uc --
+let testvar = 123;
+const testconst = "Test";
+
+function testfunc() {
+ print("Hello, world!\n");
+}
+
+export { testvar as modvar, testconst as 'define', testfunc as "module-function" };
+-- End --
+
+-- Testcase --
+import { modvar, define, "module-function" as func } from "./files/test.uc";
+
+print([ modvar, define, func ], "\n");
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 123, "Test", "function testfunc() { ... }" ]
+-- End --
diff --git a/tests/custom/04_modules/05_export_default b/tests/custom/04_modules/05_export_default
new file mode 100644
index 0000000..a4c8a43
--- /dev/null
+++ b/tests/custom/04_modules/05_export_default
@@ -0,0 +1,38 @@
+The `export default` statement can be used to declare a default export
+value for a module. The value for `export default` can be an arbitrary
+expression, it must not refer to a local variable.
+
+When using the export list syntax, the alias "default" can be used to
+designate the default export.
+
+-- File test-default-expr.uc --
+export default 7 * 21;
+-- End --
+
+-- File test-default-func.uc --
+export default function() {
+ return "Hello, world!";
+};
+-- End --
+
+-- File test-default-alias.uc --
+let a = 1, b = 2, c = 3;
+
+export { a, b as default, c };
+-- End --
+
+-- Testcase --
+import def1 from "./files/test-default-expr.uc";
+import def2 from "./files/test-default-func.uc";
+import def3 from "./files/test-default-alias.uc";
+
+print([ def1, def2(), def3 ], "\n");
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 147, "Hello, world!", 2 ]
+-- End --
diff --git a/tests/custom/04_modules/06_export_errors b/tests/custom/04_modules/06_export_errors
new file mode 100644
index 0000000..c02a547
--- /dev/null
+++ b/tests/custom/04_modules/06_export_errors
@@ -0,0 +1,89 @@
+Export statements are only allowed at the toplevel of a module.
+
+-- Testcase --
+export let x = 1;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Exports may only appear at top level of a module
+
+ `export let x = 1;`
+ ^-- Near here
+
+
+-- End --
+
+
+Export statements are not allowed within functions or nested blocks.
+
+-- Testcase --
+import "./files/test.uc";
+-- End --
+
+-- File test.uc --
+{
+ export let x = 1;
+}
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Unable to compile module './files/test.uc':
+Syntax error: Exports may only appear at top level of a module
+In line 2, byte 2:
+
+ ` export let x = 1;`
+ ^-- Near here
+
+
+
+In line 1, byte 25:
+
+ `import "./files/test.uc";`
+ Near here --------------^
+
+
+-- End --
+
+
+Duplicate export names should result in an error.
+
+-- Testcase --
+import "./files/test-duplicate.uc";
+-- End --
+
+-- File test-duplicate.uc --
+let x = 1, y = 2;
+
+export { x };
+export { y as x };
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Unable to compile module './files/test-duplicate.uc':
+Syntax error: Duplicate export 'x' for module './files/test-duplicate.uc'
+In line 4, byte 15:
+
+ `export { y as x };`
+ Near here ----^
+
+
+
+In line 1, byte 35:
+
+ `import "./files/test-duplicate.uc";`
+ Near here ------------------------^
+
+
+-- End --
diff --git a/tests/custom/04_modules/07_import_default b/tests/custom/04_modules/07_import_default
new file mode 100644
index 0000000..7190a22
--- /dev/null
+++ b/tests/custom/04_modules/07_import_default
@@ -0,0 +1,99 @@
+An `import` statement with a sole label will import the modules default
+export and bind it to a local variable named after the label.
+
+-- Testcase --
+import defVal from "./files/test1.uc";
+
+print(defVal, "\n");
+-- End --
+
+-- File test1.uc --
+export default "This is the default export";
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+This is the default export
+-- End --
+
+
+Attemping to import a default export from a module without default
+export will raise an error.
+
+-- Testcase --
+import defVal from "./files/test2.uc";
+
+print(defVal, "\n");
+-- End --
+
+-- File test2.uc --
+export const x = "This is a non-default export";
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Module ./files/test2.uc has no default export
+In line 1, byte 20:
+
+ `import defVal from "./files/test2.uc";`
+ Near here ---------^
+
+
+-- End --
+
+
+In import statements usign the list syntax, the `default` keyword can be
+used to refer to default exports.
+
+-- Testcase --
+import { default as defVal } from "./files/test3.uc";
+
+print(defVal, "\n");
+-- End --
+
+-- File test3.uc --
+export default "This is the default export";
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+This is the default export
+-- End --
+
+
+When using the default keyword within the list syntax, the `as` keyword is
+mandatory to assign a non-reserved keyword as name.
+
+-- Testcase --
+import { default } from "./files/test4.uc";
+
+print(defVal, "\n");
+-- End --
+
+-- File test4.uc --
+export default "This is the default export";
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Unexpected token
+Expecting 'as'
+In line 1, byte 18:
+
+ `import { default } from "./files/test4.uc";`
+ Near here -------^
+
+
+-- End --
diff --git a/tests/custom/04_modules/08_import_list b/tests/custom/04_modules/08_import_list
new file mode 100644
index 0000000..1a4f116
--- /dev/null
+++ b/tests/custom/04_modules/08_import_list
@@ -0,0 +1,105 @@
+An `import` statement followed by a curly brace enclosed list of names
+will import the corresponding exports from the module.
+
+-- Testcase --
+import { a, b, c } from "./files/test1.uc";
+
+print([ a, b, c ], "\n");
+-- End --
+
+-- File test1.uc --
+export const a = 1, b = 2, c = 3;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 1, 2, 3 ]
+-- End --
+
+
+Attemping to import a not exported name will raise an error.
+
+-- Testcase --
+import y from "./files/test2.uc";
+
+print(y, "\n");
+-- End --
+
+-- File test2.uc --
+export const x = "This is a test";
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Module ./files/test2.uc has no default export
+In line 1, byte 15:
+
+ `import y from "./files/test2.uc";`
+ Near here ----^
+
+
+-- End --
+
+
+Imports may be renamed to assign an alternative local name to the
+exported module symbols. Renaming is also required for string export
+names which are no valid variable identifiers.
+
+-- Testcase --
+import { a as var1, bool as var2, "my function" as var3 } from "./files/test3.uc";
+
+print([ var1, var2, var3 ], "\n");
+-- End --
+
+-- File test3.uc --
+const a = "A string";
+
+let b = 123;
+
+function c() {
+ return "A function"
+}
+
+export {
+ a,
+ b as bool,
+ c as "my function"
+};
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ "A string", 123, "function c() { ... }" ]
+-- End --
+
+
+A list expression may follow a default import expression in an `import`
+statment.
+
+-- Testcase --
+import defVal, { a as x, b as y, c as z } from "./files/test4.uc";
+
+print([defVal, x, y, z], "\n");
+-- End --
+
+-- File test4.uc --
+export const a = 1, b = 2, c = 3;
+export default a + b + c;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 6, 1, 2, 3 ]
+-- End --
diff --git a/tests/custom/04_modules/09_import_wildcard b/tests/custom/04_modules/09_import_wildcard
new file mode 100644
index 0000000..aa3dc82
--- /dev/null
+++ b/tests/custom/04_modules/09_import_wildcard
@@ -0,0 +1,73 @@
+By specifying `*` instead of a label or an import list after an `import`
+keyword, all of the modules exports are aggregated into an object whose
+keys and values refer to the exported names and their corresponding
+values respectively.
+
+-- Testcase --
+import * as mod from "./files/test1.uc";
+
+print(mod, "\n");
+-- End --
+
+-- File test1.uc --
+export const a = 1, b = 2, c = 3;
+export default a + b + c;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+{ "a": 1, "b": 2, "c": 3, "default": 6 }
+-- End --
+
+
+When using the wildcard import syntax, assigning a name using the `as`
+expression is mandatory.
+
+-- Testcase --
+import * from "./files/test2.uc";
+-- End --
+
+-- File test2.uc --
+export const x = "This is a test";
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Unexpected token
+Expecting 'as'
+In line 1, byte 10:
+
+ `import * from "./files/test2.uc";`
+ ^-- Near here
+
+
+-- End --
+
+
+A wildcard expression may follow a default import expression in an `import`
+statment.
+
+-- Testcase --
+import defVal, * as mod from "./files/test3.uc";
+
+print([defVal, mod], "\n");
+-- End --
+
+-- File test3.uc --
+export const a = 1, b = 2, c = 3;
+export default a + b + c;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+[ 6, { "a": 1, "b": 2, "c": 3, "default": 6 } ]
+-- End --
diff --git a/tests/custom/04_modules/10_import_none b/tests/custom/04_modules/10_import_none
new file mode 100644
index 0000000..be30106
--- /dev/null
+++ b/tests/custom/04_modules/10_import_none
@@ -0,0 +1,18 @@
+An `import` statement may omit a default name, wildcard expression or name
+lsit entirely to execute a module code solely for its side effects.
+
+-- Testcase --
+import "./files/test.uc";
+-- End --
+
+-- File test.uc --
+print("This is the test module running\n");
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+This is the test module running
+-- End --
diff --git a/tests/custom/04_modules/11_import_many_exec_once b/tests/custom/04_modules/11_import_many_exec_once
new file mode 100644
index 0000000..f469c7f
--- /dev/null
+++ b/tests/custom/04_modules/11_import_many_exec_once
@@ -0,0 +1,28 @@
+When multiple imports refer to the same module, the module will only be
+executed once. The equivalence of module paths is tested after canonicalizing
+the requested path.
+
+-- Testcase --
+import { counter as counter1 } from "./files/test/example.uc";
+import { counter as counter2 } from "files/test/example.uc";
+import { counter as counter3 } from "test.example";
+
+print([ counter1, counter2, counter3 ], "\n");
+-- End --
+
+-- File test/example.uc --
+print("This is the test module running\n");
+
+export let counter = 0;
+
+counter++;
+-- End --
+
+-- Args --
+-R -L ./files
+-- End --
+
+-- Expect stdout --
+This is the test module running
+[ 1, 1, 1 ]
+-- End --
diff --git a/tests/custom/04_modules/12_import_immutability b/tests/custom/04_modules/12_import_immutability
new file mode 100644
index 0000000..37c0bc6
--- /dev/null
+++ b/tests/custom/04_modules/12_import_immutability
@@ -0,0 +1,52 @@
+Module imports are read-only bindings to the exported module variables.
+
+-- Testcase --
+import { a } from "./files/test.uc";
+
+a = 2;
+-- End --
+
+-- File test.uc --
+export let a = 1;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Syntax error: Invalid assignment to constant 'a'
+In line 3, byte 5:
+
+ `a = 2;`
+ ^-- Near here
+
+
+-- End --
+
+
+Aggregated module objects are read-only as well.
+
+-- Testcase --
+import * as mod from "./files/test.uc";
+
+mod.a = 2;
+-- End --
+
+-- File test.uc --
+export let a = 1;
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stderr --
+Type error: object value is immutable
+In line 3, byte 9:
+
+ `mod.a = 2;`
+ ^-- Near here
+
+
+-- End --
diff --git a/tests/custom/04_modules/13_import_liveness b/tests/custom/04_modules/13_import_liveness
new file mode 100644
index 0000000..ca7ff35
--- /dev/null
+++ b/tests/custom/04_modules/13_import_liveness
@@ -0,0 +1,29 @@
+Imported bindings to exported module variables are live, they'll reflect
+every change to the exported variable values.
+
+-- Testcase --
+import { counter, count } from "./files/test.uc";
+
+print(counter, "\n");
+count();
+print(counter, "\n");
+-- End --
+
+-- File test.uc --
+let counter = 1;
+
+function count() {
+ counter++;
+}
+
+export { counter, count };
+-- End --
+
+-- Args --
+-R
+-- End --
+
+-- Expect stdout --
+1
+2
+-- End --
diff --git a/tests/custom/04_bugs/01_try_catch_stack_mismatch b/tests/custom/99_bugs/01_try_catch_stack_mismatch
index f6e5a0a..f6e5a0a 100644
--- a/tests/custom/04_bugs/01_try_catch_stack_mismatch
+++ b/tests/custom/99_bugs/01_try_catch_stack_mismatch
diff --git a/tests/custom/04_bugs/02_array_pop_use_after_free b/tests/custom/99_bugs/02_array_pop_use_after_free
index 22f63ff..22f63ff 100644
--- a/tests/custom/04_bugs/02_array_pop_use_after_free
+++ b/tests/custom/99_bugs/02_array_pop_use_after_free
diff --git a/tests/custom/04_bugs/03_switch_fallthrough_miscompilation b/tests/custom/99_bugs/03_switch_fallthrough_miscompilation
index 3e6410e..3e6410e 100644
--- a/tests/custom/04_bugs/03_switch_fallthrough_miscompilation
+++ b/tests/custom/99_bugs/03_switch_fallthrough_miscompilation
diff --git a/tests/custom/04_bugs/04_property_set_abort b/tests/custom/99_bugs/04_property_set_abort
index 8af477f..8af477f 100644
--- a/tests/custom/04_bugs/04_property_set_abort
+++ b/tests/custom/99_bugs/04_property_set_abort
diff --git a/tests/custom/04_bugs/05_duplicate_resource_type b/tests/custom/99_bugs/05_duplicate_resource_type
index 6d8d8f5..6d8d8f5 100644
--- a/tests/custom/04_bugs/05_duplicate_resource_type
+++ b/tests/custom/99_bugs/05_duplicate_resource_type
diff --git a/tests/custom/04_bugs/06_lexer_escape_at_boundary b/tests/custom/99_bugs/06_lexer_escape_at_boundary
index e80b0a1..e80b0a1 100644
--- a/tests/custom/04_bugs/06_lexer_escape_at_boundary
+++ b/tests/custom/99_bugs/06_lexer_escape_at_boundary
diff --git a/tests/custom/04_bugs/07_lexer_overlong_lines b/tests/custom/99_bugs/07_lexer_overlong_lines
index d2dd3be..d2dd3be 100644
--- a/tests/custom/04_bugs/07_lexer_overlong_lines
+++ b/tests/custom/99_bugs/07_lexer_overlong_lines
diff --git a/tests/custom/04_bugs/08_compiler_arrow_fn_expressions b/tests/custom/99_bugs/08_compiler_arrow_fn_expressions
index 5cd8960..5cd8960 100644
--- a/tests/custom/04_bugs/08_compiler_arrow_fn_expressions
+++ b/tests/custom/99_bugs/08_compiler_arrow_fn_expressions
diff --git a/tests/custom/04_bugs/09_reject_invalid_array_indexes b/tests/custom/99_bugs/09_reject_invalid_array_indexes
index a7e5272..a7e5272 100644
--- a/tests/custom/04_bugs/09_reject_invalid_array_indexes
+++ b/tests/custom/99_bugs/09_reject_invalid_array_indexes
diff --git a/tests/custom/04_bugs/10_break_stack_mismatch b/tests/custom/99_bugs/10_break_stack_mismatch
index c9c82c5..c9c82c5 100644
--- a/tests/custom/04_bugs/10_break_stack_mismatch
+++ b/tests/custom/99_bugs/10_break_stack_mismatch
diff --git a/tests/custom/04_bugs/11_switch_stack_mismatch b/tests/custom/99_bugs/11_switch_stack_mismatch
index 0cf82f0..0cf82f0 100644
--- a/tests/custom/04_bugs/11_switch_stack_mismatch
+++ b/tests/custom/99_bugs/11_switch_stack_mismatch
diff --git a/tests/custom/04_bugs/12_altblock_stack_mismatch b/tests/custom/99_bugs/12_altblock_stack_mismatch
index e350660..e350660 100644
--- a/tests/custom/04_bugs/12_altblock_stack_mismatch
+++ b/tests/custom/99_bugs/12_altblock_stack_mismatch
diff --git a/tests/custom/04_bugs/13_split_by_string_leading_trailing b/tests/custom/99_bugs/13_split_by_string_leading_trailing
index 10a6062..10a6062 100644
--- a/tests/custom/04_bugs/13_split_by_string_leading_trailing
+++ b/tests/custom/99_bugs/13_split_by_string_leading_trailing
diff --git a/tests/custom/04_bugs/14_incomplete_expression_at_eof b/tests/custom/99_bugs/14_incomplete_expression_at_eof
index 474e87c..474e87c 100644
--- a/tests/custom/04_bugs/14_incomplete_expression_at_eof
+++ b/tests/custom/99_bugs/14_incomplete_expression_at_eof
diff --git a/tests/custom/04_bugs/15_segfault_on_prefix_increment b/tests/custom/99_bugs/15_segfault_on_prefix_increment
index 280b680..280b680 100644
--- a/tests/custom/04_bugs/15_segfault_on_prefix_increment
+++ b/tests/custom/99_bugs/15_segfault_on_prefix_increment
diff --git a/tests/custom/04_bugs/16_hang_on_regexp_at_eof b/tests/custom/99_bugs/16_hang_on_regexp_at_eof
index d8702ca..d8702ca 100644
--- a/tests/custom/04_bugs/16_hang_on_regexp_at_eof
+++ b/tests/custom/99_bugs/16_hang_on_regexp_at_eof
diff --git a/tests/custom/04_bugs/17_hang_on_unclosed_expression_block b/tests/custom/99_bugs/17_hang_on_unclosed_expression_block
index 29553ab..29553ab 100644
--- a/tests/custom/04_bugs/17_hang_on_unclosed_expression_block
+++ b/tests/custom/99_bugs/17_hang_on_unclosed_expression_block
diff --git a/tests/custom/04_bugs/18_hang_on_line_comments_at_eof b/tests/custom/99_bugs/18_hang_on_line_comments_at_eof
index 5fc811e..5fc811e 100644
--- a/tests/custom/04_bugs/18_hang_on_line_comments_at_eof
+++ b/tests/custom/99_bugs/18_hang_on_line_comments_at_eof
diff --git a/tests/custom/04_bugs/19_truncated_format_string b/tests/custom/99_bugs/19_truncated_format_string
index ead0fdb..ead0fdb 100644
--- a/tests/custom/04_bugs/19_truncated_format_string
+++ b/tests/custom/99_bugs/19_truncated_format_string
diff --git a/tests/custom/04_bugs/20_use_strict_stack_mismatch b/tests/custom/99_bugs/20_use_strict_stack_mismatch
index 7294d23..7294d23 100644
--- a/tests/custom/04_bugs/20_use_strict_stack_mismatch
+++ b/tests/custom/99_bugs/20_use_strict_stack_mismatch
diff --git a/tests/custom/04_bugs/21_compiler_parenthesized_prop_keyword b/tests/custom/99_bugs/21_compiler_parenthesized_prop_keyword
index 472b2af..472b2af 100644
--- a/tests/custom/04_bugs/21_compiler_parenthesized_prop_keyword
+++ b/tests/custom/99_bugs/21_compiler_parenthesized_prop_keyword
diff --git a/tests/custom/04_bugs/22_compiler_break_continue_scoping b/tests/custom/99_bugs/22_compiler_break_continue_scoping
index 461b144..461b144 100644
--- a/tests/custom/04_bugs/22_compiler_break_continue_scoping
+++ b/tests/custom/99_bugs/22_compiler_break_continue_scoping
diff --git a/tests/custom/04_bugs/23_compiler_parenthesized_division b/tests/custom/99_bugs/23_compiler_parenthesized_division
index a70703f..a70703f 100644
--- a/tests/custom/04_bugs/23_compiler_parenthesized_division
+++ b/tests/custom/99_bugs/23_compiler_parenthesized_division
diff --git a/tests/custom/04_bugs/24_compiler_local_for_loop_declaration b/tests/custom/99_bugs/24_compiler_local_for_loop_declaration
index aafde55..aafde55 100644
--- a/tests/custom/04_bugs/24_compiler_local_for_loop_declaration
+++ b/tests/custom/99_bugs/24_compiler_local_for_loop_declaration
diff --git a/tests/custom/04_bugs/25_lexer_shifted_offsets b/tests/custom/99_bugs/25_lexer_shifted_offsets
index db10121..db10121 100644
--- a/tests/custom/04_bugs/25_lexer_shifted_offsets
+++ b/tests/custom/99_bugs/25_lexer_shifted_offsets
diff --git a/tests/custom/04_bugs/26_compiler_jmp_to_zero b/tests/custom/99_bugs/26_compiler_jmp_to_zero
index e7e0127..e7e0127 100644
--- a/tests/custom/04_bugs/26_compiler_jmp_to_zero
+++ b/tests/custom/99_bugs/26_compiler_jmp_to_zero
diff --git a/tests/custom/04_bugs/27_invalid_sparse_array_set b/tests/custom/99_bugs/27_invalid_sparse_array_set
index 4c47039..4c47039 100644
--- a/tests/custom/04_bugs/27_invalid_sparse_array_set
+++ b/tests/custom/99_bugs/27_invalid_sparse_array_set
diff --git a/tests/custom/04_bugs/28_null_equality b/tests/custom/99_bugs/28_null_equality
index b71a3b1..b71a3b1 100644
--- a/tests/custom/04_bugs/28_null_equality
+++ b/tests/custom/99_bugs/28_null_equality
diff --git a/tests/custom/04_bugs/29_empty_string_as_number b/tests/custom/99_bugs/29_empty_string_as_number
index 51a93b2..51a93b2 100644
--- a/tests/custom/04_bugs/29_empty_string_as_number
+++ b/tests/custom/99_bugs/29_empty_string_as_number
diff --git a/tests/custom/04_bugs/30_nan_strict_equality b/tests/custom/99_bugs/30_nan_strict_equality
index 4ec32e2..4ec32e2 100644
--- a/tests/custom/04_bugs/30_nan_strict_equality
+++ b/tests/custom/99_bugs/30_nan_strict_equality
diff --git a/tests/custom/04_bugs/31_vallist_8bit_shortstrings b/tests/custom/99_bugs/31_vallist_8bit_shortstrings
index 9d02f42..9d02f42 100644
--- a/tests/custom/04_bugs/31_vallist_8bit_shortstrings
+++ b/tests/custom/99_bugs/31_vallist_8bit_shortstrings
diff --git a/tests/custom/04_bugs/32_compiler_switch_patchlist_corruption b/tests/custom/99_bugs/32_compiler_switch_patchlist_corruption
index d256de5..d256de5 100644
--- a/tests/custom/04_bugs/32_compiler_switch_patchlist_corruption
+++ b/tests/custom/99_bugs/32_compiler_switch_patchlist_corruption
diff --git a/tests/custom/04_bugs/33_vm_computed_prop_decl_crash b/tests/custom/99_bugs/33_vm_computed_prop_decl_crash
index 60b276c..60b276c 100644
--- a/tests/custom/04_bugs/33_vm_computed_prop_decl_crash
+++ b/tests/custom/99_bugs/33_vm_computed_prop_decl_crash
diff --git a/tests/custom/04_bugs/34_dirname_off_by_one b/tests/custom/99_bugs/34_dirname_off_by_one
index 34ef7c7..34ef7c7 100644
--- a/tests/custom/04_bugs/34_dirname_off_by_one
+++ b/tests/custom/99_bugs/34_dirname_off_by_one
diff --git a/tests/custom/04_bugs/35_vm_callframe_double_free b/tests/custom/99_bugs/35_vm_callframe_double_free
index bb816eb..bb816eb 100644
--- a/tests/custom/04_bugs/35_vm_callframe_double_free
+++ b/tests/custom/99_bugs/35_vm_callframe_double_free
diff --git a/tests/custom/04_bugs/36_vm_nested_call_return b/tests/custom/99_bugs/36_vm_nested_call_return
index 6a52b78..6a52b78 100644
--- a/tests/custom/04_bugs/36_vm_nested_call_return
+++ b/tests/custom/99_bugs/36_vm_nested_call_return
diff --git a/tests/custom/04_bugs/37_compiler_unexpected_unary_op b/tests/custom/99_bugs/37_compiler_unexpected_unary_op
index e652319..e652319 100644
--- a/tests/custom/04_bugs/37_compiler_unexpected_unary_op
+++ b/tests/custom/99_bugs/37_compiler_unexpected_unary_op
diff --git a/tests/custom/04_bugs/38_index_segfault b/tests/custom/99_bugs/38_index_segfault
index e29b99f..e29b99f 100644
--- a/tests/custom/04_bugs/38_index_segfault
+++ b/tests/custom/99_bugs/38_index_segfault
diff --git a/tests/custom/04_bugs/39_compiler_switch_continue_mismatch b/tests/custom/99_bugs/39_compiler_switch_continue_mismatch
index c9b9ec6..c9b9ec6 100644
--- a/tests/custom/04_bugs/39_compiler_switch_continue_mismatch
+++ b/tests/custom/99_bugs/39_compiler_switch_continue_mismatch
diff --git a/tests/custom/04_bugs/40_lexer_bug_on_lstrip_off b/tests/custom/99_bugs/40_lexer_bug_on_lstrip_off
index dc4f8dd..dc4f8dd 100644
--- a/tests/custom/04_bugs/40_lexer_bug_on_lstrip_off
+++ b/tests/custom/99_bugs/40_lexer_bug_on_lstrip_off