authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-01 02:08:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-01 02:08:58-07:00
log58e375d0a1423c04f4d3faabe4d84bfc11028d56
tree733056bbfef07b984aabaea612d1dae67f698f68
parent29f24e3c5066e7cb28876d40a811a4a64f9d4b33

support multiple files


8 files changed, 168 insertions(+), 53 deletions(-)

README.md-1
...@@ -43,7 +43,6 @@ make...@@ -43,7 +43,6 @@ make
43## Roadmap43## Roadmap
4444
45 * variable declarations and assignment expressions45 * variable declarations and assignment expressions
46 * Multiple files
47 * Type checking46 * Type checking
48 * inline assembly and syscalls47 * inline assembly and syscalls
49 * running code at compile time48 * running code at compile time
example/multiple_files/foo.zig+1-1
...@@ -6,6 +6,6 @@ fn private_function() {...@@ -6,6 +6,6 @@ fn private_function() {
6 puts("it works!");6 puts("it works!");
7}7}
88
9fn print_text() {9pub fn print_text() {
10 private_function();10 private_function();
11}11}
example/multiple_files/libc.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1#link("c")1#link("c")
2extern {2extern {
3 fn puts(s: *mut u8) -> i32;3 pub fn puts(s: *mut u8) -> i32;
4 fn exit(code: i32) -> unreachable;4 pub fn exit(code: i32) -> unreachable;
5}5}
example/multiple_files/main.zig+1-1
...@@ -3,7 +3,7 @@ export executable "test";...@@ -3,7 +3,7 @@ export executable "test";
3use "libc.zig";3use "libc.zig";
4use "foo.zig";4use "foo.zig";
55
6fn _start() -> unreachable {6export fn _start() -> unreachable {
7 private_function();7 private_function();
8}8}
99
src/analyze.cpp+73-30
...@@ -137,6 +137,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -137,6 +137,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
137 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);137 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
138 assert(fn_decl->type == NodeTypeFnDecl);138 assert(fn_decl->type == NodeTypeFnDecl);
139 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;139 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
140 bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub);
140 resolve_function_proto(g, fn_proto);141 resolve_function_proto(g, fn_proto);
141 Buf *name = &fn_proto->data.fn_proto.name;142 Buf *name = &fn_proto->data.fn_proto.name;
142143
...@@ -145,7 +146,12 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -145,7 +146,12 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
145 fn_table_entry->is_extern = true;146 fn_table_entry->is_extern = true;
146 fn_table_entry->calling_convention = LLVMCCallConv;147 fn_table_entry->calling_convention = LLVMCCallConv;
147 fn_table_entry->import_entry = import;148 fn_table_entry->import_entry = import;
148 g->fn_table.put(name, fn_table_entry);149
150 g->fn_protos.append(fn_table_entry);
151 import->fn_table.put(name, fn_table_entry);
152 if (is_pub) {
153 g->fn_table.put(name, fn_table_entry);
154 }
149 }155 }
150 break;156 break;
151 case NodeTypeFnDef:157 case NodeTypeFnDef:
...@@ -153,27 +159,44 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -153,27 +159,44 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
153 AstNode *proto_node = node->data.fn_def.fn_proto;159 AstNode *proto_node = node->data.fn_def.fn_proto;
154 assert(proto_node->type == NodeTypeFnProto);160 assert(proto_node->type == NodeTypeFnProto);
155 Buf *proto_name = &proto_node->data.fn_proto.name;161 Buf *proto_name = &proto_node->data.fn_proto.name;
156 auto entry = g->fn_table.maybe_get(proto_name);162 auto entry = import->fn_table.maybe_get(proto_name);
163 bool skip = false;
164 bool is_internal = (proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport);
165 bool is_pub = (proto_node->data.fn_proto.visib_mod == FnProtoVisibModPub);
157 if (entry) {166 if (entry) {
158 add_node_error(g, node,167 add_node_error(g, node,
159 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));168 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
160 assert(!node->codegen_node);169 assert(!node->codegen_node);
161 node->codegen_node = allocate<CodeGenNode>(1);170 node->codegen_node = allocate<CodeGenNode>(1);
162 node->codegen_node->data.fn_def_node.skip = true;171 node->codegen_node->data.fn_def_node.skip = true;
163 } else {172 skip = true;
173 } else if (is_pub) {
174 auto entry = g->fn_table.maybe_get(proto_name);
175 if (entry) {
176 add_node_error(g, node,
177 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
178 assert(!node->codegen_node);
179 node->codegen_node = allocate<CodeGenNode>(1);
180 node->codegen_node->data.fn_def_node.skip = true;
181 skip = true;
182 }
183 }
184 if (!skip) {
164 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);185 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
165 fn_table_entry->import_entry = import;186 fn_table_entry->import_entry = import;
166 fn_table_entry->proto_node = proto_node;187 fn_table_entry->proto_node = proto_node;
167 fn_table_entry->fn_def_node = node;188 fn_table_entry->fn_def_node = node;
168 fn_table_entry->internal_linkage = proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport;189 fn_table_entry->internal_linkage = is_internal;
169 if (fn_table_entry->internal_linkage) {190 fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;
170 fn_table_entry->calling_convention = LLVMFastCallConv;191
171 } else {192 g->fn_protos.append(fn_table_entry);
172 fn_table_entry->calling_convention = LLVMCCallConv;
173 }
174 g->fn_table.put(proto_name, fn_table_entry);
175 g->fn_defs.append(fn_table_entry);193 g->fn_defs.append(fn_table_entry);
176194
195 import->fn_table.put(proto_name, fn_table_entry);
196 if (is_pub) {
197 g->fn_table.put(proto_name, fn_table_entry);
198 }
199
177 resolve_function_proto(g, proto_node);200 resolve_function_proto(g, proto_node);
178 }201 }
179 }202 }
...@@ -297,28 +320,31 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {...@@ -297,28 +320,31 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
297 }320 }
298}321}
299322
300static void analyze_expression(CodeGen *g, AstNode *node) {323static void analyze_expression(CodeGen *g, ImportTableEntry *import, AstNode *node) {
301 switch (node->type) {324 switch (node->type) {
302 case NodeTypeBlock:325 case NodeTypeBlock:
303 for (int i = 0; i < node->data.block.statements.length; i += 1) {326 for (int i = 0; i < node->data.block.statements.length; i += 1) {
304 AstNode *child = node->data.block.statements.at(i);327 AstNode *child = node->data.block.statements.at(i);
305 analyze_expression(g, child);328 analyze_expression(g, import, child);
306 }329 }
307 break;330 break;
308 case NodeTypeReturnExpr:331 case NodeTypeReturnExpr:
309 if (node->data.return_expr.expr) {332 if (node->data.return_expr.expr) {
310 analyze_expression(g, node->data.return_expr.expr);333 analyze_expression(g, import, node->data.return_expr.expr);
311 }334 }
312 break;335 break;
313 case NodeTypeBinOpExpr:336 case NodeTypeBinOpExpr:
314 analyze_expression(g, node->data.bin_op_expr.op1);337 analyze_expression(g, import, node->data.bin_op_expr.op1);
315 analyze_expression(g, node->data.bin_op_expr.op2);338 analyze_expression(g, import, node->data.bin_op_expr.op2);
316 break;339 break;
317 case NodeTypeFnCallExpr:340 case NodeTypeFnCallExpr:
318 {341 {
319 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);342 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
320343
321 auto entry = g->fn_table.maybe_get(name);344 auto entry = import->fn_table.maybe_get(name);
345 if (!entry)
346 entry = g->fn_table.maybe_get(name);
347
322 if (!entry) {348 if (!entry) {
323 add_node_error(g, node,349 add_node_error(g, node,
324 buf_sprintf("undefined function: '%s'", buf_ptr(name)));350 buf_sprintf("undefined function: '%s'", buf_ptr(name)));
...@@ -336,7 +362,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) {...@@ -336,7 +362,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) {
336362
337 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {363 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
338 AstNode *child = node->data.fn_call_expr.params.at(i);364 AstNode *child = node->data.fn_call_expr.params.at(i);
339 analyze_expression(g, child);365 analyze_expression(g, import, child);
340 }366 }
341 break;367 break;
342 }368 }
...@@ -366,7 +392,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) {...@@ -366,7 +392,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) {
366 }392 }
367}393}
368394
369static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {395static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, AstNode *node) {
370 switch (node->type) {396 switch (node->type) {
371 case NodeTypeFnDef:397 case NodeTypeFnDef:
372 {398 {
...@@ -387,7 +413,7 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {...@@ -387,7 +413,7 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
387 }413 }
388414
389 check_fn_def_control_flow(g, node);415 check_fn_def_control_flow(g, node);
390 analyze_expression(g, node->data.fn_def.body);416 analyze_expression(g, import, node->data.fn_def.body);
391 }417 }
392 break;418 break;
393419
...@@ -423,33 +449,50 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {...@@ -423,33 +449,50 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
423 }449 }
424}450}
425451
426static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {452static void find_function_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
427 assert(node->type == NodeTypeRoot);453 assert(node->type == NodeTypeRoot);
428454
429 // find function declarations
430 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {455 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
431 AstNode *child = node->data.root.top_level_decls.at(i);456 AstNode *child = node->data.root.top_level_decls.at(i);
432 preview_function_declarations(g, import, child);457 preview_function_declarations(g, import, child);
433 }458 }
434459
460}
461
462static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
463 assert(node->type == NodeTypeRoot);
464
435 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {465 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
436 AstNode *child = node->data.root.top_level_decls.at(i);466 AstNode *child = node->data.root.top_level_decls.at(i);
437 analyze_top_level_declaration(g, child);467 analyze_top_level_declaration(g, import, child);
438 }468 }
439
440}469}
441470
442void semantic_analyze(CodeGen *g) {471void semantic_analyze(CodeGen *g) {
443 auto it = g->import_table.entry_iterator();472 {
444 for (;;) {473 auto it = g->import_table.entry_iterator();
445 auto *entry = it.next();474 for (;;) {
446 if (!entry)475 auto *entry = it.next();
447 break;476 if (!entry)
477 break;
448478
449 ImportTableEntry *import = entry->value;479 ImportTableEntry *import = entry->value;
450 analyze_root(g, import, import->root);480 find_function_declarations_root(g, import, import->root);
481 }
482 }
483 {
484 auto it = g->import_table.entry_iterator();
485 for (;;) {
486 auto *entry = it.next();
487 if (!entry)
488 break;
489
490 ImportTableEntry *import = entry->value;
491 analyze_top_level_decls_root(g, import, import->root);
492 }
451 }493 }
452494
495
453 if (!g->root_out_name) {496 if (!g->root_out_name) {
454 add_node_error(g, g->root_import->root,497 add_node_error(g, g->root_import->root,
455 buf_sprintf("missing export declaration and output name not provided"));498 buf_sprintf("missing export declaration and output name not provided"));
src/codegen.cpp+13-11
...@@ -125,7 +125,13 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -125,7 +125,13 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
125125
126 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);126 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
127127
128 FnTableEntry *fn_table_entry = g->fn_table.get(name);128 FnTableEntry *fn_table_entry;
129 auto entry = g->cur_fn->import_entry->fn_table.maybe_get(name);
130 if (entry)
131 fn_table_entry = entry->value;
132 else
133 fn_table_entry = g->fn_table.get(name);
134
129 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);135 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
130 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;136 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;
131 int actual_param_count = node->data.fn_call_expr.params.length;137 int actual_param_count = node->data.fn_call_expr.params.length;
...@@ -478,13 +484,8 @@ static void do_code_gen(CodeGen *g) {...@@ -478,13 +484,8 @@ static void do_code_gen(CodeGen *g) {
478484
479485
480 // Generate function prototypes486 // Generate function prototypes
481 auto it = g->fn_table.entry_iterator();487 for (int i = 0; i < g->fn_protos.length; i += 1) {
482 for (;;) {488 FnTableEntry *fn_table_entry = g->fn_protos.at(i);
483 auto *entry = it.next();
484 if (!entry)
485 break;
486
487 FnTableEntry *fn_table_entry = entry->value;
488489
489 AstNode *proto_node = fn_table_entry->proto_node;490 AstNode *proto_node = fn_table_entry->proto_node;
490 assert(proto_node->type == NodeTypeFnProto);491 assert(proto_node->type == NodeTypeFnProto);
...@@ -547,6 +548,7 @@ static void do_code_gen(CodeGen *g) {...@@ -547,6 +548,7 @@ static void do_code_gen(CodeGen *g) {
547 assert(codegen_node);548 assert(codegen_node);
548549
549 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;550 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
551 assert(codegen_fn_def);
550 codegen_fn_def->params = allocate<LLVMValueRef>(LLVMCountParams(fn));552 codegen_fn_def->params = allocate<LLVMValueRef>(LLVMCountParams(fn));
551 LLVMGetParams(fn, codegen_fn_def->params);553 LLVMGetParams(fn, codegen_fn_def->params);
552554
...@@ -733,9 +735,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou...@@ -733,9 +735,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou
733 if (!entry) {735 if (!entry) {
734 Buf full_path = BUF_INIT;736 Buf full_path = BUF_INIT;
735 os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path);737 os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path);
736 Buf import_code = BUF_INIT;738 Buf *import_code = buf_alloc();
737 os_fetch_file_path(&full_path, &import_code);739 os_fetch_file_path(&full_path, import_code);
738 codegen_add_code(g, &top_level_decl->data.use.path, &import_code);740 codegen_add_code(g, &top_level_decl->data.use.path, import_code);
739 }741 }
740 }742 }
741743
src/semantic_info.hpp+7
...@@ -80,7 +80,14 @@ struct CodeGen {...@@ -80,7 +80,14 @@ struct CodeGen {
80 Buf *root_source_dir;80 Buf *root_source_dir;
81 Buf *root_out_name;81 Buf *root_out_name;
82 ZigList<LLVMZigDIScope *> block_scopes;82 ZigList<LLVMZigDIScope *> block_scopes;
83
84 // The function definitions this module includes. There must be a corresponding
85 // fn_protos entry.
83 ZigList<FnTableEntry *> fn_defs;86 ZigList<FnTableEntry *> fn_defs;
87 // The function prototypes this module includes. In the case of external declarations,
88 // there will not be a corresponding fn_defs entry.
89 ZigList<FnTableEntry *> fn_protos;
90
84 OutType out_type;91 OutType out_type;
85 FnTableEntry *cur_fn;92 FnTableEntry *cur_fn;
86 bool c_stdint_used;93 bool c_stdint_used;
test/run_tests.cpp+71-7
...@@ -14,13 +14,13 @@...@@ -14,13 +14,13 @@
1414
15struct TestSourceFile {15struct TestSourceFile {
16 const char *relative_path;16 const char *relative_path;
17 const char *text;17 const char *source_code;
18};18};
1919
20struct TestCase {20struct TestCase {
21 const char *case_name;21 const char *case_name;
22 const char *output;22 const char *output;
23 const char *source;23 ZigList<TestSourceFile> source_files;
24 ZigList<const char *> compile_errors;24 ZigList<const char *> compile_errors;
25 ZigList<const char *> compiler_args;25 ZigList<const char *> compiler_args;
26 ZigList<const char *> program_args;26 ZigList<const char *> program_args;
...@@ -31,11 +31,20 @@ static const char *tmp_source_path = ".tmp_source.zig";...@@ -31,11 +31,20 @@ static const char *tmp_source_path = ".tmp_source.zig";
31static const char *tmp_exe_path = "./.tmp_exe";31static const char *tmp_exe_path = "./.tmp_exe";
32static const char *zig_exe = "./zig";32static const char *zig_exe = "./zig";
3333
34static void add_simple_case(const char *case_name, const char *source, const char *output) {34static void add_source_file(TestCase *test_case, const char *path, const char *source) {
35 test_case->source_files.add_one();
36 test_case->source_files.last().relative_path = path;
37 test_case->source_files.last().source_code = source;
38}
39
40static TestCase *add_simple_case(const char *case_name, const char *source, const char *output) {
35 TestCase *test_case = allocate<TestCase>(1);41 TestCase *test_case = allocate<TestCase>(1);
36 test_case->case_name = case_name;42 test_case->case_name = case_name;
37 test_case->output = output;43 test_case->output = output;
38 test_case->source = source;44
45 test_case->source_files.resize(1);
46 test_case->source_files.at(0).relative_path = tmp_source_path;
47 test_case->source_files.at(0).source_code = source;
3948
40 test_case->compiler_args.append("build");49 test_case->compiler_args.append("build");
41 test_case->compiler_args.append(tmp_source_path);50 test_case->compiler_args.append(tmp_source_path);
...@@ -52,15 +61,19 @@ static void add_simple_case(const char *case_name, const char *source, const cha...@@ -52,15 +61,19 @@ static void add_simple_case(const char *case_name, const char *source, const cha
52 test_case->compiler_args.append("on");61 test_case->compiler_args.append("on");
5362
54 test_cases.append(test_case);63 test_cases.append(test_case);
64
65 return test_case;
55}66}
5667
57static void add_compile_fail_case(const char *case_name, const char *source, int count, ...) {68static TestCase *add_compile_fail_case(const char *case_name, const char *source, int count, ...) {
58 va_list ap;69 va_list ap;
59 va_start(ap, count);70 va_start(ap, count);
6071
61 TestCase *test_case = allocate<TestCase>(1);72 TestCase *test_case = allocate<TestCase>(1);
62 test_case->case_name = case_name;73 test_case->case_name = case_name;
63 test_case->source = source;74 test_case->source_files.resize(1);
75 test_case->source_files.at(0).relative_path = tmp_source_path;
76 test_case->source_files.at(0).source_code = source;
6477
65 for (int i = 0; i < count; i += 1) {78 for (int i = 0; i < count; i += 1) {
66 const char *arg = va_arg(ap, const char *);79 const char *arg = va_arg(ap, const char *);
...@@ -78,6 +91,8 @@ static void add_compile_fail_case(const char *case_name, const char *source, int...@@ -78,6 +91,8 @@ static void add_compile_fail_case(const char *case_name, const char *source, int
78 test_cases.append(test_case);91 test_cases.append(test_case);
7992
80 va_end(ap);93 va_end(ap);
94
95 return test_case;
81}96}
8297
83static void add_compiling_test_cases(void) {98static void add_compiling_test_cases(void) {
...@@ -135,6 +150,45 @@ static void add_compiling_test_cases(void) {...@@ -135,6 +150,45 @@ static void add_compiling_test_cases(void) {
135 exit(0);150 exit(0);
136 }151 }
137 )SOURCE", "OK\n");152 )SOURCE", "OK\n");
153
154 {
155 TestCase *tc = add_simple_case("multiple files with private function", R"SOURCE(
156 use "libc.zig";
157 use "foo.zig";
158
159 export fn _start() -> unreachable {
160 private_function();
161 }
162
163 fn private_function() -> unreachable {
164 print_text();
165 exit(0);
166 }
167 )SOURCE", "OK\n");
168
169 add_source_file(tc, "libc.zig", R"SOURCE(
170 #link("c")
171 extern {
172 pub fn puts(s: *mut u8) -> i32;
173 pub fn exit(code: i32) -> unreachable;
174 }
175 )SOURCE");
176
177 add_source_file(tc, "foo.zig", R"SOURCE(
178 use "libc.zig";
179
180 // purposefully conflicting function with main source file
181 // but it's private so it should be OK
182 fn private_function() {
183 puts("OK");
184 }
185
186 pub fn print_text() {
187 private_function();
188 }
189 )SOURCE");
190 }
191
138}192}
139193
140static void add_compile_failure_test_cases(void) {194static void add_compile_failure_test_cases(void) {
...@@ -207,7 +261,12 @@ static void print_compiler_invokation(TestCase *test_case, Buf *zig_stderr) {...@@ -207,7 +261,12 @@ static void print_compiler_invokation(TestCase *test_case, Buf *zig_stderr) {
207}261}
208262
209static void run_test(TestCase *test_case) {263static void run_test(TestCase *test_case) {
210 os_write_file(buf_create_from_str(tmp_source_path), buf_create_from_str(test_case->source));264 for (int i = 0; i < test_case->source_files.length; i += 1) {
265 TestSourceFile *test_source = &test_case->source_files.at(i);
266 os_write_file(
267 buf_create_from_str(test_source->relative_path),
268 buf_create_from_str(test_source->source_code));
269 }
211270
212 Buf zig_stderr = BUF_INIT;271 Buf zig_stderr = BUF_INIT;
213 Buf zig_stdout = BUF_INIT;272 Buf zig_stdout = BUF_INIT;
...@@ -265,6 +324,11 @@ static void run_test(TestCase *test_case) {...@@ -265,6 +324,11 @@ static void run_test(TestCase *test_case) {
265 printf("=======================================\n");324 printf("=======================================\n");
266 exit(1);325 exit(1);
267 }326 }
327
328 for (int i = 0; i < test_case->source_files.length; i += 1) {
329 TestSourceFile *test_source = &test_case->source_files.at(i);
330 remove(test_source->relative_path);
331 }
268}332}
269333
270static void run_all_tests(void) {334static void run_all_tests(void) {