@@ -1413,6 +1413,17 @@ pub const Parser = struct {
1413
1413
}) catch unreachable ;
1414
1414
},
1415
1415
Token .Id .Keyword_extern = > {
1416
+ const next = self .getNextToken ();
1417
+ if (next .id == Token .Id .Keyword_fn ) {
1418
+ // TODO shouldn't need this cast
1419
+ const fn_proto = try self .createFnProto (arena , next ,
1420
+ (? Token )(token ), (? & ast .Node )(null ), (? Token )(null ), (? Token )(null ), (? Token )(null ));
1421
+ dest_ptr .store (& fn_proto .base );
1422
+ stack .append (State { .FnProto = fn_proto }) catch unreachable ;
1423
+ continue ;
1424
+ }
1425
+
1426
+ self .putBackToken (next );
1416
1427
stack .append (State {
1417
1428
.ContainerExtern = ContainerExternCtx {
1418
1429
.dest_ptr = dest_ptr ,
@@ -1455,7 +1466,26 @@ pub const Parser = struct {
1455
1466
continue ;
1456
1467
},
1457
1468
Token .Id .Keyword_fn = > {
1458
- @panic ("TODO: fn proto" );
1469
+ // TODO shouldn't need these casts
1470
+ const fn_proto = try self .createFnProto (arena , token ,
1471
+ (? Token )(null ), (? & ast .Node )(null ), (? Token )(null ), (? Token )(null ), (? Token )(null ));
1472
+ dest_ptr .store (& fn_proto .base );
1473
+ stack .append (State { .FnProto = fn_proto }) catch unreachable ;
1474
+ continue ;
1475
+ },
1476
+ Token .Id .Keyword_nakedcc , Token .Id .Keyword_stdcallcc = > {
1477
+ // TODO shouldn't need this cast
1478
+ const fn_proto = try self .createFnProto (arena , undefined ,
1479
+ (? Token )(null ), (? & ast .Node )(null ), (? Token )(token ), (? Token )(null ), (? Token )(null ));
1480
+ dest_ptr .store (& fn_proto .base );
1481
+ stack .append (State { .FnProto = fn_proto }) catch unreachable ;
1482
+ try stack .append (State {
1483
+ .ExpectTokenSave = ExpectTokenSave {
1484
+ .id = Token .Id .Keyword_fn ,
1485
+ .ptr = & fn_proto .fn_token ,
1486
+ }
1487
+ });
1488
+ continue ;
1459
1489
},
1460
1490
Token .Id .Keyword_asm = > {
1461
1491
@panic ("TODO: inline asm" );
@@ -2781,41 +2811,14 @@ pub const Parser = struct {
2781
2811
ast .Node .Id .FnProto = > {
2782
2812
const fn_proto = @fieldParentPtr (ast .NodeFnProto , "base" , decl );
2783
2813
2784
- if (fn_proto .body_node == null ) {
2785
- try stack .append (RenderState { .Text = ";" });
2786
- }
2787
-
2788
- try stack .append (RenderState { .FnProtoRParen = fn_proto });
2789
- var i = fn_proto .params .len ;
2790
- while (i != 0 ) {
2791
- i -= 1 ;
2792
- const param_decl_node = fn_proto .params .items [i ];
2793
- try stack .append (RenderState { .ParamDecl = param_decl_node });
2794
- if (i != 0 ) {
2795
- try stack .append (RenderState { .Text = ", " });
2796
- }
2797
- }
2798
-
2799
- try stack .append (RenderState { .Text = "(" });
2800
- if (fn_proto .name_token ) | name_token | {
2801
- try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (name_token ) });
2802
- }
2803
-
2804
- try stack .append (RenderState { .Text = "fn " });
2805
- if (fn_proto .lib_name ) | lib_name | {
2806
- try stack .append (RenderState { .Text = " " });
2807
- try stack .append (RenderState { .Expression = lib_name });
2808
- }
2809
- if (fn_proto .extern_token ) | extern_token | {
2810
- try stack .append (RenderState { .Text = " " });
2811
- try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (extern_token ) });
2814
+ if (fn_proto .body_node ) | body_node | {
2815
+ stack .append (RenderState { .Expression = body_node }) catch unreachable ;
2816
+ try stack .append (RenderState { .Text = " " });
2817
+ } else {
2818
+ stack .append (RenderState { .Text = ";" }) catch unreachable ;
2812
2819
}
2813
2820
2814
- if (fn_proto .visib_token ) | visib_token | {
2815
- assert (visib_token .id == Token .Id .Keyword_pub or visib_token .id == Token .Id .Keyword_export );
2816
- try stack .append (RenderState { .Text = " " });
2817
- try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (visib_token ) });
2818
- }
2821
+ try stack .append (RenderState { .Expression = decl });
2819
2822
},
2820
2823
ast .Node .Id .VarDecl = > {
2821
2824
const var_decl = @fieldParentPtr (ast .NodeVarDecl , "base" , decl );
@@ -3386,7 +3389,65 @@ pub const Parser = struct {
3386
3389
}
3387
3390
}
3388
3391
},
3389
- ast .Node .Id .FnProto = > @panic ("TODO fn proto in an expression" ),
3392
+ ast .Node .Id .FnProto = > {
3393
+ const fn_proto = @fieldParentPtr (ast .NodeFnProto , "base" , base );
3394
+
3395
+ switch (fn_proto .return_type ) {
3396
+ ast .NodeFnProto .ReturnType .Explicit = > | node | {
3397
+ try stack .append (RenderState { .Expression = node });
3398
+ },
3399
+ ast .NodeFnProto .ReturnType .Infer = > {
3400
+ try stack .append (RenderState { .Text = "var" });
3401
+ },
3402
+ ast .NodeFnProto .ReturnType .InferErrorSet = > | node | {
3403
+ try stack .append (RenderState { .Expression = node });
3404
+ try stack .append (RenderState { .Text = "!" });
3405
+ },
3406
+ }
3407
+
3408
+ if (fn_proto .align_expr != null ) {
3409
+ @panic ("TODO" );
3410
+ }
3411
+
3412
+ try stack .append (RenderState { .Text = ") " });
3413
+ var i = fn_proto .params .len ;
3414
+ while (i != 0 ) {
3415
+ i -= 1 ;
3416
+ const param_decl_node = fn_proto .params .items [i ];
3417
+ try stack .append (RenderState { .ParamDecl = param_decl_node });
3418
+ if (i != 0 ) {
3419
+ try stack .append (RenderState { .Text = ", " });
3420
+ }
3421
+ }
3422
+
3423
+ try stack .append (RenderState { .Text = "(" });
3424
+ if (fn_proto .name_token ) | name_token | {
3425
+ try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (name_token ) });
3426
+ try stack .append (RenderState { .Text = " " });
3427
+ }
3428
+
3429
+ try stack .append (RenderState { .Text = "fn" });
3430
+
3431
+ if (fn_proto .cc_token ) | cc_token | {
3432
+ try stack .append (RenderState { .Text = " " });
3433
+ try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (cc_token ) });
3434
+ }
3435
+
3436
+ if (fn_proto .lib_name ) | lib_name | {
3437
+ try stack .append (RenderState { .Text = " " });
3438
+ try stack .append (RenderState { .Expression = lib_name });
3439
+ }
3440
+ if (fn_proto .extern_token ) | extern_token | {
3441
+ try stack .append (RenderState { .Text = " " });
3442
+ try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (extern_token ) });
3443
+ }
3444
+
3445
+ if (fn_proto .visib_token ) | visib_token | {
3446
+ assert (visib_token .id == Token .Id .Keyword_pub or visib_token .id == Token .Id .Keyword_export );
3447
+ try stack .append (RenderState { .Text = " " });
3448
+ try stack .append (RenderState { .Text = self .tokenizer .getTokenSlice (visib_token ) });
3449
+ }
3450
+ },
3390
3451
ast .Node .Id .LineComment = > @panic ("TODO render line comment in an expression" ),
3391
3452
ast .Node .Id .Switch = > {
3392
3453
const switch_node = @fieldParentPtr (ast .NodeSwitch , "base" , base );
@@ -4461,6 +4522,9 @@ test "zig fmt: fn type" {
4461
4522
\\ return i + 1;
4462
4523
\\}
4463
4524
\\
4525
+ \\const a: fn(u8) u8 = undefined;
4526
+ \\const b: extern fn(u8) u8 = undefined;
4527
+ \\const c: nakedcc fn(u8) u8 = undefined;
4464
4528
\\const ap: fn(u8) u8 = a;
4465
4529
\\
4466
4530
);
0 commit comments