| ... | ... | @@ -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 | ); |