| ... | @@ -1413,6 +1413,17 @@ pub const Parser = struct { | ... | @@ -1413,6 +1413,17 @@ pub const Parser = struct { |
| 1413 | }) catch unreachable; | 1413 | }) catch unreachable; |
| 1414 | }, | 1414 | }, |
| 1415 | Token.Id.Keyword_extern => { | 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 | stack.append(State { | 1427 | stack.append(State { |
| 1417 | .ContainerExtern = ContainerExternCtx { | 1428 | .ContainerExtern = ContainerExternCtx { |
| 1418 | .dest_ptr = dest_ptr, | 1429 | .dest_ptr = dest_ptr, |
| ... | @@ -1455,7 +1466,26 @@ pub const Parser = struct { | ... | @@ -1455,7 +1466,26 @@ pub const Parser = struct { |
| 1455 | continue; | 1466 | continue; |
| 1456 | }, | 1467 | }, |
| 1457 | Token.Id.Keyword_fn => { | 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 | Token.Id.Keyword_asm => { | 1490 | Token.Id.Keyword_asm => { |
| 1461 | @panic("TODO: inline asm"); | 1491 | @panic("TODO: inline asm"); |
| ... | @@ -2781,41 +2811,14 @@ pub const Parser = struct { | ... | @@ -2781,41 +2811,14 @@ pub const Parser = struct { |
| 2781 | ast.Node.Id.FnProto => { | 2811 | ast.Node.Id.FnProto => { |
| 2782 | const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl); | 2812 | const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl); |
| 2783 | | 2813 | |
| 2784 | if (fn_proto.body_node == null) { | 2814 | if (fn_proto.body_node) |body_node| { |
| 2785 | try stack.append(RenderState { .Text = ";" }); | 2815 | stack.append(RenderState { .Expression = body_node}) catch unreachable; |
| 2786 | } | 2816 | try stack.append(RenderState { .Text = " "}); |
| 2787 | | 2817 | } else { |
| 2788 | try stack.append(RenderState { .FnProtoRParen = fn_proto}); | 2818 | stack.append(RenderState { .Text = ";" }) catch unreachable; |
| 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) }); | | |
| 2812 | } | 2819 | } |
| 2813 | | 2820 | |
| 2814 | if (fn_proto.visib_token) |visib_token| { | 2821 | try stack.append(RenderState { .Expression = decl }); |
| 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 | } | | |
| 2819 | }, | 2822 | }, |
| 2820 | ast.Node.Id.VarDecl => { | 2823 | ast.Node.Id.VarDecl => { |
| 2821 | const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl); | 2824 | const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl); |
| ... | @@ -3386,7 +3389,65 @@ pub const Parser = struct { | ... | @@ -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 | ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), | 3451 | ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), |
| 3391 | ast.Node.Id.Switch => { | 3452 | ast.Node.Id.Switch => { |
| 3392 | const switch_node = @fieldParentPtr(ast.NodeSwitch, "base", base); | 3453 | const switch_node = @fieldParentPtr(ast.NodeSwitch, "base", base); |
| ... | @@ -4461,6 +4522,9 @@ test "zig fmt: fn type" { | ... | @@ -4461,6 +4522,9 @@ test "zig fmt: fn type" { |
| 4461 | \\ return i + 1; | 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 | \\const ap: fn(u8) u8 = a; | 4528 | \\const ap: fn(u8) u8 = a; |
| 4465 | \\ | 4529 | \\ |
| 4466 | ); | 4530 | ); |