| ... | @@ -861,12 +861,121 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn | ... | @@ -861,12 +861,121 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn |
| 861 | => return structInitExpr(gz, scope, rl, node, tree.structInit(node)), | 861 | => return structInitExpr(gz, scope, rl, node, tree.structInit(node)), |
| 862 | | 862 | |
| 863 | .@"anytype" => return astgen.failNode(node, "TODO implement astgen.expr for .anytype", .{}), | 863 | .@"anytype" => return astgen.failNode(node, "TODO implement astgen.expr for .anytype", .{}), |
| 864 | .fn_proto_simple, | 864 | |
| 865 | .fn_proto_multi, | 865 | .fn_proto_simple => { |
| 866 | .fn_proto_one, | 866 | var params: [1]ast.Node.Index = undefined; |
| 867 | .fn_proto, | 867 | return fnProtoExpr(gz, scope, rl, tree.fnProtoSimple(&params, node)); |
| 868 | => return astgen.failNode(node, "TODO implement astgen.expr for function prototypes", .{}), | 868 | }, |
| | 869 | .fn_proto_multi => { |
| | 870 | return fnProtoExpr(gz, scope, rl, tree.fnProtoMulti(node)); |
| | 871 | }, |
| | 872 | .fn_proto_one => { |
| | 873 | var params: [1]ast.Node.Index = undefined; |
| | 874 | return fnProtoExpr(gz, scope, rl, tree.fnProtoOne(&params, node)); |
| | 875 | }, |
| | 876 | .fn_proto => { |
| | 877 | return fnProtoExpr(gz, scope, rl, tree.fnProto(node)); |
| | 878 | }, |
| | 879 | } |
| | 880 | } |
| | 881 | |
| | 882 | pub fn fnProtoExpr( |
| | 883 | gz: *GenZir, |
| | 884 | scope: *Scope, |
| | 885 | rl: ResultLoc, |
| | 886 | fn_proto: ast.full.FnProto, |
| | 887 | ) InnerError!Zir.Inst.Ref { |
| | 888 | const astgen = gz.astgen; |
| | 889 | const gpa = astgen.gpa; |
| | 890 | const tree = &astgen.file.tree; |
| | 891 | const token_tags = tree.tokens.items(.tag); |
| | 892 | |
| | 893 | const is_extern = blk: { |
| | 894 | const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false; |
| | 895 | break :blk token_tags[maybe_extern_token] == .keyword_extern; |
| | 896 | }; |
| | 897 | assert(!is_extern); |
| | 898 | |
| | 899 | // The AST params array does not contain anytype and ... parameters. |
| | 900 | // We must iterate to count how many param types to allocate. |
| | 901 | const param_count = blk: { |
| | 902 | var count: usize = 0; |
| | 903 | var it = fn_proto.iterate(tree.*); |
| | 904 | while (it.next()) |param| { |
| | 905 | if (param.anytype_ellipsis3) |token| switch (token_tags[token]) { |
| | 906 | .ellipsis3 => break, |
| | 907 | .keyword_anytype => {}, |
| | 908 | else => unreachable, |
| | 909 | }; |
| | 910 | count += 1; |
| | 911 | } |
| | 912 | break :blk count; |
| | 913 | }; |
| | 914 | const param_types = try gpa.alloc(Zir.Inst.Ref, param_count); |
| | 915 | defer gpa.free(param_types); |
| | 916 | |
| | 917 | var is_var_args = false; |
| | 918 | { |
| | 919 | var param_type_i: usize = 0; |
| | 920 | var it = fn_proto.iterate(tree.*); |
| | 921 | while (it.next()) |param| : (param_type_i += 1) { |
| | 922 | if (param.anytype_ellipsis3) |token| { |
| | 923 | switch (token_tags[token]) { |
| | 924 | .keyword_anytype => { |
| | 925 | param_types[param_type_i] = .none; |
| | 926 | continue; |
| | 927 | }, |
| | 928 | .ellipsis3 => { |
| | 929 | is_var_args = true; |
| | 930 | break; |
| | 931 | }, |
| | 932 | else => unreachable, |
| | 933 | } |
| | 934 | } |
| | 935 | const param_type_node = param.type_expr; |
| | 936 | assert(param_type_node != 0); |
| | 937 | param_types[param_type_i] = |
| | 938 | try expr(gz, scope, .{ .ty = .type_type }, param_type_node); |
| | 939 | } |
| | 940 | assert(param_type_i == param_count); |
| | 941 | } |
| | 942 | |
| | 943 | assert(fn_proto.ast.align_expr == 0); // caught by the parser |
| | 944 | assert(fn_proto.ast.section_expr == 0); // caught by the parser |
| | 945 | |
| | 946 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; |
| | 947 | const is_inferred_error = token_tags[maybe_bang] == .bang; |
| | 948 | if (is_inferred_error) { |
| | 949 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| 869 | } | 950 | } |
| | 951 | const return_type_inst = try AstGen.expr( |
| | 952 | gz, |
| | 953 | scope, |
| | 954 | .{ .ty = .type_type }, |
| | 955 | fn_proto.ast.return_type, |
| | 956 | ); |
| | 957 | |
| | 958 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) |
| | 959 | try AstGen.expr( |
| | 960 | gz, |
| | 961 | scope, |
| | 962 | .{ .ty = .calling_convention_type }, |
| | 963 | fn_proto.ast.callconv_expr, |
| | 964 | ) |
| | 965 | else |
| | 966 | Zir.Inst.Ref.none; |
| | 967 | |
| | 968 | const result = try gz.addFunc(.{ |
| | 969 | .src_node = fn_proto.ast.proto_node, |
| | 970 | .ret_ty = return_type_inst, |
| | 971 | .param_types = param_types, |
| | 972 | .body = &[0]Zir.Inst.Index{}, |
| | 973 | .cc = cc, |
| | 974 | .lib_name = 0, |
| | 975 | .is_var_args = is_var_args, |
| | 976 | .is_inferred_error = false, |
| | 977 | }); |
| | 978 | return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node); |
| 870 | } | 979 | } |
| 871 | | 980 | |
| 872 | pub fn arrayInitExpr( | 981 | pub fn arrayInitExpr( |
| ... | @@ -2506,11 +2615,11 @@ fn fnDecl( | ... | @@ -2506,11 +2615,11 @@ fn fnDecl( |
| 2506 | Zir.Inst.Ref.none; | 2615 | Zir.Inst.Ref.none; |
| 2507 | | 2616 | |
| 2508 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { | 2617 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { |
| 2509 | if (is_extern) { | 2618 | if (!is_extern) { |
| 2510 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); | 2619 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); |
| 2511 | } | 2620 | } |
| 2512 | if (is_inferred_error) { | 2621 | if (is_inferred_error) { |
| 2513 | return astgen.failTok(maybe_bang, "function prototype requires explicit error set", .{}); | 2622 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| 2514 | } | 2623 | } |
| 2515 | break :func try decl_gz.addFunc(.{ | 2624 | break :func try decl_gz.addFunc(.{ |
| 2516 | .src_node = fn_proto.ast.proto_node, | 2625 | .src_node = fn_proto.ast.proto_node, |