| ... | ... | @@ -55,6 +55,7 @@ pub const Parser = struct { |
| 55 | 55 | const TopLevelDeclCtx = struct { |
| 56 | 56 | visib_token: ?Token, |
| 57 | 57 | extern_token: ?Token, |
| 58 | lib_name: ?&ast.Node, |
| 58 | 59 | }; |
| 59 | 60 | |
| 60 | 61 | const DestPtr = union(enum) { |
| ... | ... | @@ -183,8 +184,9 @@ pub const Parser = struct { |
| 183 | 184 | if (lbrace.id != Token.Id.LBrace) |
| 184 | 185 | return self.parseError(token, "expected {}, found {}", @tagName(Token.Id.LBrace), @tagName(name_token.id)); |
| 185 | 186 | |
| 187 | const name = try self.createStringLiteral(arena, name_token); |
| 186 | 188 | const block = try self.createBlock(arena, token); |
| 187 | | const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, name_token, block); |
| 189 | const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block); |
| 188 | 190 | try stack.append(State { .Block = block }); |
| 189 | 191 | continue; |
| 190 | 192 | }, |
| ... | ... | @@ -202,10 +204,22 @@ pub const Parser = struct { |
| 202 | 204 | State.TopLevelExtern => |visib_token| { |
| 203 | 205 | const token = self.getNextToken(); |
| 204 | 206 | if (token.id == Token.Id.Keyword_extern) { |
| 207 | const lib_name_token = self.getNextToken(); |
| 208 | const lib_name = blk: { |
| 209 | if (lib_name_token.id == Token.Id.StringLiteral) { |
| 210 | const res = try self.createStringLiteral(arena, lib_name_token); |
| 211 | break :blk &res.base; |
| 212 | } else { |
| 213 | self.putBackToken(lib_name_token); |
| 214 | break :blk null; |
| 215 | } |
| 216 | }; |
| 217 | |
| 205 | 218 | stack.append(State { |
| 206 | 219 | .TopLevelDecl = TopLevelDeclCtx { |
| 207 | 220 | .visib_token = visib_token, |
| 208 | 221 | .extern_token = token, |
| 222 | .lib_name = lib_name, |
| 209 | 223 | }, |
| 210 | 224 | }) catch unreachable; |
| 211 | 225 | continue; |
| ... | ... | @@ -215,6 +229,7 @@ pub const Parser = struct { |
| 215 | 229 | .TopLevelDecl = TopLevelDeclCtx { |
| 216 | 230 | .visib_token = visib_token, |
| 217 | 231 | .extern_token = null, |
| 232 | .lib_name = null, |
| 218 | 233 | }, |
| 219 | 234 | }) catch unreachable; |
| 220 | 235 | continue; |
| ... | ... | @@ -226,7 +241,7 @@ pub const Parser = struct { |
| 226 | 241 | stack.append(State.TopLevel) catch unreachable; |
| 227 | 242 | // TODO shouldn't need these casts |
| 228 | 243 | const var_decl_node = try self.createAttachVarDecl(arena, &root_node.decls, ctx.visib_token, |
| 229 | | token, (?Token)(null), ctx.extern_token); |
| 244 | token, (?Token)(null), ctx.extern_token, ctx.lib_name); |
| 230 | 245 | try stack.append(State { .VarDecl = var_decl_node }); |
| 231 | 246 | continue; |
| 232 | 247 | }, |
| ... | ... | @@ -234,20 +249,17 @@ pub const Parser = struct { |
| 234 | 249 | stack.append(State.TopLevel) catch unreachable; |
| 235 | 250 | // TODO shouldn't need these casts |
| 236 | 251 | const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, token, |
| 237 | | ctx.extern_token, (?Token)(null), ctx.visib_token, (?Token)(null)); |
| 252 | ctx.extern_token, ctx.lib_name, (?Token)(null), ctx.visib_token, (?Token)(null)); |
| 238 | 253 | try stack.append(State { .FnDef = fn_proto }); |
| 239 | 254 | try stack.append(State { .FnProto = fn_proto }); |
| 240 | 255 | continue; |
| 241 | 256 | }, |
| 242 | | Token.Id.StringLiteral => { |
| 243 | | @panic("TODO extern with string literal"); |
| 244 | | }, |
| 245 | 257 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { |
| 246 | 258 | stack.append(State.TopLevel) catch unreachable; |
| 247 | 259 | const fn_token = try self.eatToken(Token.Id.Keyword_fn); |
| 248 | 260 | // TODO shouldn't need this cast |
| 249 | 261 | const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, fn_token, |
| 250 | | ctx.extern_token, (?Token)(token), (?Token)(null), (?Token)(null)); |
| 262 | ctx.extern_token, ctx.lib_name, (?Token)(token), (?Token)(null), (?Token)(null)); |
| 251 | 263 | try stack.append(State { .FnDef = fn_proto }); |
| 252 | 264 | try stack.append(State { .FnProto = fn_proto }); |
| 253 | 265 | continue; |
| ... | ... | @@ -437,11 +449,7 @@ pub const Parser = struct { |
| 437 | 449 | continue; |
| 438 | 450 | }, |
| 439 | 451 | Token.Id.StringLiteral => { |
| 440 | | const node = try arena.create(ast.NodeStringLiteral); |
| 441 | | *node = ast.NodeStringLiteral { |
| 442 | | .base = self.initNode(ast.Node.Id.StringLiteral), |
| 443 | | .token = token, |
| 444 | | }; |
| 452 | const node = try self.createStringLiteral(arena, token); |
| 445 | 453 | try stack.append(State { |
| 446 | 454 | .Operand = &node.base |
| 447 | 455 | }); |
| ... | ... | @@ -722,7 +730,7 @@ pub const Parser = struct { |
| 722 | 730 | if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) { |
| 723 | 731 | // TODO shouldn't need these casts |
| 724 | 732 | const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null), |
| 725 | | mut_token, (?Token)(comptime_token), (?Token)(null)); |
| 733 | mut_token, (?Token)(comptime_token), (?Token)(null), null); |
| 726 | 734 | try stack.append(State { .VarDecl = var_decl }); |
| 727 | 735 | continue; |
| 728 | 736 | } |
| ... | ... | @@ -736,7 +744,7 @@ pub const Parser = struct { |
| 736 | 744 | if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) { |
| 737 | 745 | // TODO shouldn't need these casts |
| 738 | 746 | const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null), |
| 739 | | mut_token, (?Token)(null), (?Token)(null)); |
| 747 | mut_token, (?Token)(null), (?Token)(null), null); |
| 740 | 748 | try stack.append(State { .VarDecl = var_decl }); |
| 741 | 749 | continue; |
| 742 | 750 | } |
| ... | ... | @@ -852,7 +860,7 @@ pub const Parser = struct { |
| 852 | 860 | } |
| 853 | 861 | |
| 854 | 862 | fn createVarDecl(self: &Parser, arena: &mem.Allocator, visib_token: &const ?Token, mut_token: &const Token, |
| 855 | | comptime_token: &const ?Token, extern_token: &const ?Token) !&ast.NodeVarDecl |
| 863 | comptime_token: &const ?Token, extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl |
| 856 | 864 | { |
| 857 | 865 | const node = try arena.create(ast.NodeVarDecl); |
| 858 | 866 | |
| ... | ... | @@ -865,7 +873,7 @@ pub const Parser = struct { |
| 865 | 873 | .type_node = null, |
| 866 | 874 | .align_node = null, |
| 867 | 875 | .init_node = null, |
| 868 | | .lib_name = null, |
| 876 | .lib_name = lib_name, |
| 869 | 877 | // initialized later |
| 870 | 878 | .name_token = undefined, |
| 871 | 879 | .eq_token = undefined, |
| ... | ... | @@ -874,7 +882,18 @@ pub const Parser = struct { |
| 874 | 882 | return node; |
| 875 | 883 | } |
| 876 | 884 | |
| 877 | | fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name_token: &const Token, |
| 885 | fn createStringLiteral(self: &Parser, arena: &mem.Allocator, token: &const Token) !&ast.NodeStringLiteral { |
| 886 | const node = try arena.create(ast.NodeStringLiteral); |
| 887 | |
| 888 | assert(token.id == Token.Id.StringLiteral); |
| 889 | *node = ast.NodeStringLiteral { |
| 890 | .base = self.initNode(ast.Node.Id.StringLiteral), |
| 891 | .token = *token, |
| 892 | }; |
| 893 | return node; |
| 894 | } |
| 895 | |
| 896 | fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name: &ast.Node, |
| 878 | 897 | block: &ast.NodeBlock) !&ast.NodeTestDecl |
| 879 | 898 | { |
| 880 | 899 | const node = try arena.create(ast.NodeTestDecl); |
| ... | ... | @@ -882,14 +901,14 @@ pub const Parser = struct { |
| 882 | 901 | *node = ast.NodeTestDecl { |
| 883 | 902 | .base = self.initNode(ast.Node.Id.TestDecl), |
| 884 | 903 | .test_token = *test_token, |
| 885 | | .name_token = *name_token, |
| 904 | .name = name, |
| 886 | 905 | .body_node = &block.base, |
| 887 | 906 | }; |
| 888 | 907 | return node; |
| 889 | 908 | } |
| 890 | 909 | |
| 891 | 910 | fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token, |
| 892 | | cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto |
| 911 | lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto |
| 893 | 912 | { |
| 894 | 913 | const node = try arena.create(ast.NodeFnProto); |
| 895 | 914 | |
| ... | ... | @@ -905,7 +924,7 @@ pub const Parser = struct { |
| 905 | 924 | .inline_token = *inline_token, |
| 906 | 925 | .cc_token = *cc_token, |
| 907 | 926 | .body_node = null, |
| 908 | | .lib_name = null, |
| 927 | .lib_name = lib_name, |
| 909 | 928 | .align_expr = null, |
| 910 | 929 | }; |
| 911 | 930 | return node; |
| ... | ... | @@ -1015,27 +1034,27 @@ pub const Parser = struct { |
| 1015 | 1034 | } |
| 1016 | 1035 | |
| 1017 | 1036 | fn createAttachFnProto(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node), fn_token: &const Token, |
| 1018 | | extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token, |
| 1037 | extern_token: &const ?Token, lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token, |
| 1019 | 1038 | inline_token: &const ?Token) !&ast.NodeFnProto |
| 1020 | 1039 | { |
| 1021 | | const node = try self.createFnProto(arena, fn_token, extern_token, cc_token, visib_token, inline_token); |
| 1040 | const node = try self.createFnProto(arena, fn_token, extern_token, lib_name, cc_token, visib_token, inline_token); |
| 1022 | 1041 | try list.append(&node.base); |
| 1023 | 1042 | return node; |
| 1024 | 1043 | } |
| 1025 | 1044 | |
| 1026 | 1045 | fn createAttachVarDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node), |
| 1027 | 1046 | visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token, |
| 1028 | | extern_token: &const ?Token) !&ast.NodeVarDecl |
| 1047 | extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl |
| 1029 | 1048 | { |
| 1030 | | const node = try self.createVarDecl(arena, visib_token, mut_token, comptime_token, extern_token); |
| 1049 | const node = try self.createVarDecl(arena, visib_token, mut_token, comptime_token, extern_token, lib_name); |
| 1031 | 1050 | try list.append(&node.base); |
| 1032 | 1051 | return node; |
| 1033 | 1052 | } |
| 1034 | 1053 | |
| 1035 | 1054 | fn createAttachTestDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node), |
| 1036 | | test_token: &const Token, name_token: &const Token, block: &ast.NodeBlock) !&ast.NodeTestDecl |
| 1055 | test_token: &const Token, name: &ast.Node, block: &ast.NodeBlock) !&ast.NodeTestDecl |
| 1037 | 1056 | { |
| 1038 | | const node = try self.createTestDecl(arena, test_token, name_token, block); |
| 1057 | const node = try self.createTestDecl(arena, test_token, name, block); |
| 1039 | 1058 | try list.append(&node.base); |
| 1040 | 1059 | return node; |
| 1041 | 1060 | } |
| ... | ... | @@ -1169,23 +1188,6 @@ pub const Parser = struct { |
| 1169 | 1188 | switch (decl.id) { |
| 1170 | 1189 | ast.Node.Id.FnProto => { |
| 1171 | 1190 | const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl); |
| 1172 | | if (fn_proto.visib_token) |visib_token| { |
| 1173 | | switch (visib_token.id) { |
| 1174 | | Token.Id.Keyword_pub => try stream.print("pub "), |
| 1175 | | Token.Id.Keyword_export => try stream.print("export "), |
| 1176 | | else => unreachable, |
| 1177 | | } |
| 1178 | | } |
| 1179 | | if (fn_proto.extern_token) |extern_token| { |
| 1180 | | try stream.print("{} ", self.tokenizer.getTokenSlice(extern_token)); |
| 1181 | | } |
| 1182 | | try stream.print("fn"); |
| 1183 | | |
| 1184 | | if (fn_proto.name_token) |name_token| { |
| 1185 | | try stream.print(" {}", self.tokenizer.getTokenSlice(name_token)); |
| 1186 | | } |
| 1187 | | |
| 1188 | | try stream.print("("); |
| 1189 | 1191 | |
| 1190 | 1192 | if (fn_proto.body_node == null) { |
| 1191 | 1193 | try stack.append(RenderState { .Text = ";" }); |
| ... | ... | @@ -1201,6 +1203,27 @@ pub const Parser = struct { |
| 1201 | 1203 | try stack.append(RenderState { .Text = ", " }); |
| 1202 | 1204 | } |
| 1203 | 1205 | } |
| 1206 | |
| 1207 | try stack.append(RenderState { .Text = "(" }); |
| 1208 | if (fn_proto.name_token) |name_token| { |
| 1209 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(name_token) }); |
| 1210 | } |
| 1211 | |
| 1212 | try stack.append(RenderState { .Text = "fn " }); |
| 1213 | if (fn_proto.lib_name) |lib_name| { |
| 1214 | try stack.append(RenderState { .Text = " " }); |
| 1215 | try stack.append(RenderState { .Expression = lib_name }); |
| 1216 | } |
| 1217 | if (fn_proto.extern_token) |extern_token| { |
| 1218 | try stack.append(RenderState { .Text = " " }); |
| 1219 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(extern_token) }); |
| 1220 | } |
| 1221 | |
| 1222 | if (fn_proto.visib_token) |visib_token| { |
| 1223 | assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export); |
| 1224 | try stack.append(RenderState { .Text = " " }); |
| 1225 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) }); |
| 1226 | } |
| 1204 | 1227 | }, |
| 1205 | 1228 | ast.Node.Id.VarDecl => { |
| 1206 | 1229 | const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl); |
| ... | ... | @@ -1208,29 +1231,16 @@ pub const Parser = struct { |
| 1208 | 1231 | }, |
| 1209 | 1232 | ast.Node.Id.TestDecl => { |
| 1210 | 1233 | const test_decl = @fieldParentPtr(ast.NodeTestDecl, "base", decl); |
| 1211 | | try stream.print("test {} ", self.tokenizer.getTokenSlice(test_decl.name_token)); |
| 1234 | try stream.print("test "); |
| 1212 | 1235 | try stack.append(RenderState { .Expression = test_decl.body_node }); |
| 1236 | try stack.append(RenderState { .Text = " " }); |
| 1237 | try stack.append(RenderState { .Expression = test_decl.name }); |
| 1213 | 1238 | }, |
| 1214 | 1239 | else => unreachable, |
| 1215 | 1240 | } |
| 1216 | 1241 | }, |
| 1217 | 1242 | |
| 1218 | 1243 | RenderState.VarDecl => |var_decl| { |
| 1219 | | if (var_decl.visib_token) |visib_token| { |
| 1220 | | try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token)); |
| 1221 | | } |
| 1222 | | if (var_decl.extern_token) |extern_token| { |
| 1223 | | try stream.print("{} ", self.tokenizer.getTokenSlice(extern_token)); |
| 1224 | | if (var_decl.lib_name != null) { |
| 1225 | | @panic("TODO"); |
| 1226 | | } |
| 1227 | | } |
| 1228 | | if (var_decl.comptime_token) |comptime_token| { |
| 1229 | | try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token)); |
| 1230 | | } |
| 1231 | | try stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token)); |
| 1232 | | try stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token)); |
| 1233 | | |
| 1234 | 1244 | try stack.append(RenderState { .Text = ";" }); |
| 1235 | 1245 | if (var_decl.init_node) |init_node| { |
| 1236 | 1246 | try stack.append(RenderState { .Expression = init_node }); |
| ... | ... | @@ -1242,8 +1252,30 @@ pub const Parser = struct { |
| 1242 | 1252 | try stack.append(RenderState { .Text = " align(" }); |
| 1243 | 1253 | } |
| 1244 | 1254 | if (var_decl.type_node) |type_node| { |
| 1245 | | try stream.print(": "); |
| 1246 | 1255 | try stack.append(RenderState { .Expression = type_node }); |
| 1256 | try stack.append(RenderState { .Text = ": " }); |
| 1257 | } |
| 1258 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(var_decl.name_token) }); |
| 1259 | try stack.append(RenderState { .Text = " " }); |
| 1260 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(var_decl.mut_token) }); |
| 1261 | |
| 1262 | if (var_decl.comptime_token) |comptime_token| { |
| 1263 | try stack.append(RenderState { .Text = " " }); |
| 1264 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(comptime_token) }); |
| 1265 | } |
| 1266 | |
| 1267 | if (var_decl.extern_token) |extern_token| { |
| 1268 | if (var_decl.lib_name != null) { |
| 1269 | try stack.append(RenderState { .Text = " " }); |
| 1270 | try stack.append(RenderState { .Expression = ??var_decl.lib_name }); |
| 1271 | } |
| 1272 | try stack.append(RenderState { .Text = " " }); |
| 1273 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(extern_token) }); |
| 1274 | } |
| 1275 | |
| 1276 | if (var_decl.visib_token) |visib_token| { |
| 1277 | try stack.append(RenderState { .Text = " " }); |
| 1278 | try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) }); |
| 1247 | 1279 | } |
| 1248 | 1280 | }, |
| 1249 | 1281 | |
| ... | ... | @@ -1612,6 +1644,14 @@ test "zig fmt: global declarations" { |
| 1612 | 1644 | \\pub const a: i32 = b; |
| 1613 | 1645 | \\var a: i32 = b; |
| 1614 | 1646 | \\pub var a: i32 = b; |
| 1647 | \\extern const a: i32 = b; |
| 1648 | \\pub extern const a: i32 = b; |
| 1649 | \\extern var a: i32 = b; |
| 1650 | \\pub extern var a: i32 = b; |
| 1651 | \\extern "a" const a: i32 = b; |
| 1652 | \\pub extern "a" const a: i32 = b; |
| 1653 | \\extern "a" var a: i32 = b; |
| 1654 | \\pub extern "a" var a: i32 = b; |
| 1615 | 1655 | \\ |
| 1616 | 1656 | ); |
| 1617 | 1657 | } |
| ... | ... | @@ -2232,7 +2272,7 @@ test "zig fmt: coroutines" { |
| 2232 | 2272 | \\ x += 1; |
| 2233 | 2273 | \\ suspend |p| { |
| 2234 | 2274 | \\ } |
| 2235 | | \\ const p = async simpleAsyncFn() cache unreachable; |
| 2275 | \\ const p = async simpleAsyncFn() catch unreachable; |
| 2236 | 2276 | \\ await p; |
| 2237 | 2277 | \\} |
| 2238 | 2278 | \\ |