@@ -24,6 +24,7 @@ const Visib = @import("visib.zig").Visib;
24
24
const ParsedFile = @import ("parsed_file.zig" ).ParsedFile ;
25
25
const Value = @import ("value.zig" ).Value ;
26
26
const Type = Value .Type ;
27
+ const Span = errmsg .Span ;
27
28
28
29
pub const Module = struct {
29
30
loop : * event.Loop ,
@@ -148,13 +149,14 @@ pub const Module = struct {
148
149
Overflow ,
149
150
NotSupported ,
150
151
BufferTooSmall ,
151
- Unimplemented ,
152
+ Unimplemented , // TODO remove this one
153
+ SemanticAnalysisFailed , // TODO remove this one
152
154
};
153
155
154
156
pub const Event = union (enum ) {
155
157
Ok ,
156
- Fail : []* errmsg.Msg ,
157
158
Error : BuildError ,
159
+ Fail : []* errmsg.Msg ,
158
160
};
159
161
160
162
pub const DarwinVersionMin = union (enum ) {
@@ -413,21 +415,32 @@ pub const Module = struct {
413
415
while (true ) {
414
416
// TODO directly awaiting async should guarantee memory allocation elision
415
417
// TODO also async before suspending should guarantee memory allocation elision
416
- (await (async self .addRootSrc () catch unreachable )) catch | err | {
417
- await (async self .events .put (Event { .Error = err }) catch unreachable );
418
- return ;
419
- };
418
+ const build_result = await (async self .addRootSrc () catch unreachable );
419
+
420
+ // this makes a handy error return trace and stack trace in debug mode
421
+ if (std .debug .runtime_safety ) {
422
+ build_result catch unreachable ;
423
+ }
424
+
420
425
const compile_errors = blk : {
421
426
const held = await (async self .compile_errors .acquire () catch unreachable );
422
427
defer held .release ();
423
428
break :blk held .value .toOwnedSlice ();
424
429
};
425
430
426
- if (compile_errors .len == 0 ) {
427
- await (async self .events .put (Event .Ok ) catch unreachable );
428
- } else {
429
- await (async self .events .put (Event { .Fail = compile_errors }) catch unreachable );
431
+ if (build_result ) | _ | {
432
+ if (compile_errors .len == 0 ) {
433
+ await (async self .events .put (Event .Ok ) catch unreachable );
434
+ } else {
435
+ await (async self .events .put (Event { .Fail = compile_errors }) catch unreachable );
436
+ }
437
+ } else | err | {
438
+ // if there's an error then the compile errors have dangling references
439
+ self .a ().free (compile_errors );
440
+
441
+ await (async self .events .put (Event { .Error = err }) catch unreachable );
430
442
}
443
+
431
444
// for now we stop after 1
432
445
return ;
433
446
}
@@ -477,7 +490,7 @@ pub const Module = struct {
477
490
const fn_proto = @fieldParentPtr (ast .Node .FnProto , "base" , decl );
478
491
479
492
const name = if (fn_proto .name_token ) | name_token | tree .tokenSlice (name_token ) else {
480
- try self .addCompileError (parsed_file , errmsg. Span {
493
+ try self .addCompileError (parsed_file , Span {
481
494
.first = fn_proto .fn_token ,
482
495
.last = fn_proto .fn_token + 1 ,
483
496
}, "missing function name" );
@@ -518,27 +531,23 @@ pub const Module = struct {
518
531
}
519
532
}
520
533
521
- fn addCompileError (self : * Module , parsed_file : * ParsedFile , span : errmsg. Span , comptime fmt : []const u8 , args : ... ) ! void {
534
+ fn addCompileError (self : * Module , parsed_file : * ParsedFile , span : Span , comptime fmt : []const u8 , args : ... ) ! void {
522
535
const text = try std .fmt .allocPrint (self .loop .allocator , fmt , args );
523
536
errdefer self .loop .allocator .free (text );
524
537
525
- try self .build_group .call (addCompileErrorAsync , self , parsed_file , span . first , span . last , text );
538
+ try self .build_group .call (addCompileErrorAsync , self , parsed_file , span , text );
526
539
}
527
540
528
541
async fn addCompileErrorAsync (
529
542
self : * Module ,
530
543
parsed_file : * ParsedFile ,
531
- first_token : ast.TokenIndex ,
532
- last_token : ast.TokenIndex ,
544
+ span : Span ,
533
545
text : []u8 ,
534
546
) ! void {
535
547
const msg = try self .loop .allocator .create (errmsg.Msg {
536
548
.path = parsed_file .realpath ,
537
549
.text = text ,
538
- .span = errmsg.Span {
539
- .first = first_token ,
540
- .last = last_token ,
541
- },
550
+ .span = span ,
542
551
.tree = & parsed_file .tree ,
543
552
});
544
553
errdefer self .loop .allocator .destroy (msg );
@@ -624,6 +633,7 @@ pub async fn resolveDecl(module: *Module, decl: *Decl) !void {
624
633
if (@atomicRmw (u8 , & decl .resolution_in_progress , AtomicRmwOp .Xchg , 1 , AtomicOrder .SeqCst ) == 0 ) {
625
634
decl .resolution .data = await (async generateDecl (module , decl ) catch unreachable );
626
635
decl .resolution .resolve ();
636
+ return decl .resolution .data ;
627
637
} else {
628
638
return (await (async decl .resolution .get () catch unreachable )).* ;
629
639
}
@@ -655,12 +665,41 @@ async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
655
665
656
666
fn_decl .value = Decl.Fn.Val { .Ok = fn_val };
657
667
658
- const code = try await (async ir .gen (
668
+ const unanalyzed_code = ( await (async ir .gen (
659
669
module ,
660
670
body_node ,
661
671
& fndef_scope .base ,
672
+ Span .token (body_node .lastToken ()),
673
+ fn_decl .base .parsed_file ,
674
+ ) catch unreachable )) catch | err | switch (err ) {
675
+ // This poison value should not cause the errdefers to run. It simply means
676
+ // that self.compile_errors is populated.
677
+ error .SemanticAnalysisFailed = > return {},
678
+ else = > return err ,
679
+ };
680
+ defer unanalyzed_code .destroy (module .a ());
681
+
682
+ if (module .verbose_ir ) {
683
+ std .debug .warn ("unanalyzed:\n " );
684
+ unanalyzed_code .dump ();
685
+ }
686
+
687
+ const analyzed_code = (await (async ir .analyze (
688
+ module ,
662
689
fn_decl .base .parsed_file ,
663
- ) catch unreachable );
664
- //code.dump();
665
- //try await (async irAnalyze(module, func) catch unreachable);
690
+ unanalyzed_code ,
691
+ null ,
692
+ ) catch unreachable )) catch | err | switch (err ) {
693
+ // This poison value should not cause the errdefers to run. It simply means
694
+ // that self.compile_errors is populated.
695
+ error .SemanticAnalysisFailed = > return {},
696
+ else = > return err ,
697
+ };
698
+ defer analyzed_code .destroy (module .a ());
699
+
700
+ if (module .verbose_ir ) {
701
+ std .debug .warn ("analyzed:\n " );
702
+ analyzed_code .dump ();
703
+ }
704
+ // TODO now render to LLVM module
666
705
}
0 commit comments