authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-10 19:40:46-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-10 19:40:46-05:00
logdc2e3465c78411c67eb6d1efd4944b19b0b279f2
tree95b220593b870509420344e064a5658b850836ba
parent62ead3a2ee3670e2eba8a8e8fe5b2cb32630d787

rendering source code without recursion


5 files changed, 326 insertions(+), 115 deletions(-)

src-self-hosted/main.zig+297-86
......@@ -1,11 +1,14 @@
1const std = @import("std");
12const builtin = @import("builtin");
2const io = @import("std").io;
3const os = @import("std").os;
4const heap = @import("std").heap;
5const warn = @import("std").debug.warn;
6const assert = @import("std").debug.assert;
7const mem = @import("std").mem;
8const ArrayList = @import("std").ArrayList;
3const io = std.io;
4const os = std.os;
5const heap = std.heap;
6const warn = std.debug.warn;
7const assert = std.debug.assert;
8const mem = std.mem;
9const ArrayList = std.ArrayList;
10const AlignedArrayList = std.AlignedArrayList;
11const math = std.math;
912
1013
1114const Token = struct {
......@@ -474,6 +477,10 @@ const Tokenizer = struct {
474477 // TODO check state when returning EOF
475478 return result;
476479 }
480
481 pub fn getTokenSlice(self: &const Tokenizer, token: &const Token) -> []const u8 {
482 return self.buffer[token.start..token.end];
483 }
477484};
478485
479486const Comptime = enum { No, Yes };
......@@ -525,6 +532,17 @@ const AstNode = struct {
525532 Id.AddrOfExpr => @fieldParentPtr(AstNodeAddrOfExpr, "base", base).iterate(index),
526533 };
527534 }
535
536 fn destroy(base: &AstNode, allocator: &mem.Allocator) {
537 return switch (base.id) {
538 Id.Root => allocator.destroy(@fieldParentPtr(AstNodeRoot, "base", base)),
539 Id.VarDecl => allocator.destroy(@fieldParentPtr(AstNodeVarDecl, "base", base)),
540 Id.Identifier => allocator.destroy(@fieldParentPtr(AstNodeIdentifier, "base", base)),
541 Id.FnProto => allocator.destroy(@fieldParentPtr(AstNodeFnProto, "base", base)),
542 Id.ParamDecl => allocator.destroy(@fieldParentPtr(AstNodeParamDecl, "base", base)),
543 Id.AddrOfExpr => allocator.destroy(@fieldParentPtr(AstNodeAddrOfExpr, "base", base)),
544 };
545 }
528546};
529547
530548const AstNodeRoot = struct {
......@@ -541,7 +559,7 @@ const AstNodeRoot = struct {
541559
542560const AstNodeVarDecl = struct {
543561 base: AstNode,
544 visib: Visibility,
562 visib_token: ?Token,
545563 name_token: Token,
546564 eq_token: Token,
547565 mut: Mutability,
......@@ -585,7 +603,7 @@ const AstNodeIdentifier = struct {
585603
586604const AstNodeFnProto = struct {
587605 base: AstNode,
588 visib: Visibility,
606 visib_token: ?Token,
589607 fn_token: Token,
590608 name_token: ?Token,
591609 params: ArrayList(&AstNode),
......@@ -648,8 +666,8 @@ const AstNodeParamDecl = struct {
648666
649667const AstNodeAddrOfExpr = struct {
650668 base: AstNode,
651 align_expr: ?&AstNode,
652669 op_token: Token,
670 align_expr: ?&AstNode,
653671 bit_offset_start_token: ?Token,
654672 bit_offset_end_token: ?Token,
655673 const_token: ?Token,
......@@ -674,26 +692,47 @@ const AstNodeAddrOfExpr = struct {
674692error ParseError;
675693
676694const Parser = struct {
677 tokenizer: &Tokenizer,
678695 allocator: &mem.Allocator,
696 tokenizer: &Tokenizer,
679697 put_back_tokens: [2]Token,
680698 put_back_count: usize,
681699 source_file_name: []const u8,
682700
683 fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator, source_file_name: []const u8) -> Parser {
701 // This memory contents are used only during a function call. It's used to repurpose memory;
702 // specifically so that freeAst can be guaranteed to succeed.
703 const utility_bytes_align = @alignOf( union { a: RenderAstFrame, b: State, c: RenderState } );
704 utility_bytes: []align(utility_bytes_align) u8,
705
706 fn initUtilityArrayList(self: &Parser, comptime T: type) -> ArrayList(T) {
707 const new_byte_count = self.utility_bytes.len - self.utility_bytes.len % @sizeOf(T);
708 self.utility_bytes = self.allocator.alignedShrink(u8, utility_bytes_align, self.utility_bytes, new_byte_count);
709 const typed_slice = ([]T)(self.utility_bytes);
710 return ArrayList(T).fromOwnedSlice(self.allocator, typed_slice);
711 }
712
713 fn deinitUtilityArrayList(self: &Parser, list: var) {
714 self.utility_bytes = ([]align(utility_bytes_align) u8)(list.toOwnedSlice());
715 }
716
717 pub fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator, source_file_name: []const u8) -> Parser {
684718 return Parser {
685 .tokenizer = tokenizer,
686719 .allocator = allocator,
720 .tokenizer = tokenizer,
687721 .put_back_tokens = undefined,
688722 .put_back_count = 0,
689723 .source_file_name = source_file_name,
724 .utility_bytes = []align(utility_bytes_align) u8{},
690725 };
691726 }
692727
728 pub fn deinit(self: &Parser) {
729 self.allocator.free(self.utility_bytes);
730 }
731
693732 const State = union(enum) {
694 TopLevel,
695 TopLevelModifier: Visibility,
696 TopLevelExtern: Visibility,
733 TopLevel,
734 TopLevelModifier: ?Token,
735 TopLevelExtern: ?Token,
697736 Expression: &&AstNode,
698737 GroupedExpression: &&AstNode,
699738 UnwrapExpression: &&AstNode,
......@@ -721,14 +760,36 @@ const Parser = struct {
721760 ParamDeclComma,
722761 };
723762
724 pub fn parse(self: &Parser) -> %&AstNode {
725 var stack = ArrayList(State).init(self.allocator);
726 defer stack.deinit();
763 pub fn freeAst(self: &Parser, root_node: &AstNodeRoot) {
764 // utility_bytes is big enough to do this iteration since we were able to do
765 // the parsing in the first place
766 comptime assert(@sizeOf(State) >= @sizeOf(&AstNode));
727767
728 %return stack.append(State.TopLevel);
768 var stack = self.initUtilityArrayList(&AstNode);
769 defer self.deinitUtilityArrayList(stack);
770
771 stack.append(&root_node.base) %% unreachable;
772 while (stack.popOrNull()) |node| {
773 var i: usize = 0;
774 while (node.iterate(i)) |child| : (i += 1) {
775 if (child.iterate(0) != null) {
776 stack.append(child) %% unreachable;
777 } else {
778 child.destroy(self.allocator);
779 }
780 }
781 node.destroy(self.allocator);
782 }
783 }
784
785 pub fn parse(self: &Parser) -> %&AstNodeRoot {
786 var stack = self.initUtilityArrayList(State);
787 defer self.deinitUtilityArrayList(stack);
729788
730789 const root_node = %return self.createRoot();
731 // TODO %defer self.freeAst();
790 %defer self.allocator.destroy(root_node);
791 %return stack.append(State.TopLevel);
792 %defer self.freeAst(root_node);
732793
733794 while (true) {
734795 // This gives us 1 free append that can't fail
......@@ -738,95 +799,74 @@ const Parser = struct {
738799 State.TopLevel => {
739800 const token = self.getNextToken();
740801 switch (token.id) {
741 Token.Id.Keyword_pub => {
742 stack.append(State {.TopLevelModifier = Visibility.Pub }) %% unreachable;
743 continue;
744 },
745 Token.Id.Keyword_export => {
746 stack.append(State {.TopLevelModifier = Visibility.Export }) %% unreachable;
802 Token.Id.Keyword_pub, Token.Id.Keyword_export => {
803 stack.append(State { .TopLevelModifier = token }) %% unreachable;
747804 continue;
748805 },
749806 Token.Id.Keyword_const => {
750807 stack.append(State.TopLevel) %% unreachable;
751 const var_decl_node = {
752 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Const, Comptime.No, Extern.No);
753 %defer self.allocator.destroy(var_decl_node);
754 %return root_node.decls.append(&var_decl_node.base);
755 var_decl_node
756 };
808 // TODO shouldn't need this cast
809 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),
810 Mutability.Const, Comptime.No, Extern.No);
757811 %return stack.append(State { .VarDecl = var_decl_node });
758812 continue;
759813 },
760814 Token.Id.Keyword_var => {
761815 stack.append(State.TopLevel) %% unreachable;
762 const var_decl_node = {
763 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Var, Comptime.No, Extern.No);
764 %defer self.allocator.destroy(var_decl_node);
765 %return root_node.decls.append(&var_decl_node.base);
766 var_decl_node
767 };
816 // TODO shouldn't need this cast
817 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),
818 Mutability.Var, Comptime.No, Extern.No);
768819 %return stack.append(State { .VarDecl = var_decl_node });
769820 continue;
770821 },
771 Token.Id.Eof => return &root_node.base,
822 Token.Id.Eof => return root_node,
772823 Token.Id.Keyword_extern => {
773 stack.append(State { .TopLevelExtern = Visibility.Private }) %% unreachable;
824 stack.append(State { .TopLevelExtern = null }) %% unreachable;
774825 continue;
775826 },
776827 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
777828 }
778829 },
779 State.TopLevelModifier => |visib| {
830 State.TopLevelModifier => |visib_token| {
780831 const token = self.getNextToken();
781832 switch (token.id) {
782833 Token.Id.Keyword_const => {
783834 stack.append(State.TopLevel) %% unreachable;
784 const var_decl_node = {
785 const var_decl_node = %return self.createVarDecl(visib, Mutability.Const, Comptime.No, Extern.No);
786 %defer self.allocator.destroy(var_decl_node);
787 %return root_node.decls.append(&var_decl_node.base);
788 var_decl_node
789 };
835 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
836 Mutability.Const, Comptime.No, Extern.No);
790837 %return stack.append(State { .VarDecl = var_decl_node });
791838 continue;
792839 },
793840 Token.Id.Keyword_var => {
794841 stack.append(State.TopLevel) %% unreachable;
795 const var_decl_node = {
796 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, Comptime.No, Extern.No);
797 %defer self.allocator.destroy(var_decl_node);
798 %return root_node.decls.append(&var_decl_node.base);
799 var_decl_node
800 };
842 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
843 Mutability.Var, Comptime.No, Extern.No);
801844 %return stack.append(State { .VarDecl = var_decl_node });
802845 continue;
803846 },
804847 Token.Id.Keyword_extern => {
805 stack.append(State { .TopLevelExtern = visib }) %% unreachable;
848 stack.append(State { .TopLevelExtern = visib_token }) %% unreachable;
806849 continue;
807850 },
808851 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
809852 }
810853 },
811 State.TopLevelExtern => |visib| {
854 State.TopLevelExtern => |visib_token| {
812855 const token = self.getNextToken();
813856 switch (token.id) {
814857 Token.Id.Keyword_var => {
815858 stack.append(State.TopLevel) %% unreachable;
816 const var_decl_node = {
817 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, Comptime.No, Extern.Yes);
818 %defer self.allocator.destroy(var_decl_node);
819 %return root_node.decls.append(&var_decl_node.base);
820 var_decl_node
821 };
859 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
860 Mutability.Var, Comptime.No, Extern.Yes);
822861 %return stack.append(State { .VarDecl = var_decl_node });
823862 continue;
824863 },
825864 Token.Id.Keyword_fn => {
826865 stack.append(State.TopLevel) %% unreachable;
827866 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
867 // TODO shouldn't need this cast
828868 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,
829 Extern.Yes, CallingConvention.Auto, visib, Inline.Auto);
869 Extern.Yes, CallingConvention.Auto, (?Token)(null), Inline.Auto);
830870 %return stack.append(State { .FnProto = fn_proto_node });
831871 continue;
832872 },
......@@ -843,8 +883,9 @@ const Parser = struct {
843883 else => unreachable,
844884 };
845885 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);
886 // TODO shouldn't need this cast
846887 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,
847 Extern.Yes, cc, visib, Inline.Auto);
888 Extern.Yes, cc, (?Token)(null), Inline.Auto);
848889 %return stack.append(State { .FnProto = fn_proto_node });
849890 continue;
850891 },
......@@ -1054,6 +1095,8 @@ const Parser = struct {
10541095 }
10551096 if (token.id == Token.Id.Ellipsis3) {
10561097 param_decl.var_args_token = token;
1098 stack.append(State { .ExpectToken = Token.Id.RParen }) %% unreachable;
1099 continue;
10571100 } else {
10581101 self.putBackToken(token);
10591102 }
......@@ -1094,7 +1137,7 @@ const Parser = struct {
10941137 return node;
10951138 }
10961139
1097 fn createVarDecl(self: &Parser, visib: Visibility, mut: Mutability, is_comptime: Comptime,
1140 fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut: Mutability, is_comptime: Comptime,
10981141 is_extern: Extern) -> %&AstNodeVarDecl
10991142 {
11001143 const node = %return self.allocator.create(AstNodeVarDecl);
......@@ -1102,7 +1145,7 @@ const Parser = struct {
11021145
11031146 *node = AstNodeVarDecl {
11041147 .base = AstNode {.id = AstNode.Id.VarDecl},
1105 .visib = visib,
1148 .visib_token = *visib_token,
11061149 .mut = mut,
11071150 .is_comptime = is_comptime,
11081151 .is_extern = is_extern,
......@@ -1129,14 +1172,14 @@ const Parser = struct {
11291172 }
11301173
11311174 fn createFnProto(self: &Parser, fn_token: &const Token, is_extern: Extern,
1132 cc: CallingConvention, visib: Visibility, is_inline: Inline) -> %&AstNodeFnProto
1175 cc: CallingConvention, visib_token: &const ?Token, is_inline: Inline) -> %&AstNodeFnProto
11331176 {
11341177 const node = %return self.allocator.create(AstNodeFnProto);
11351178 %defer self.allocator.destroy(node);
11361179
11371180 *node = AstNodeFnProto {
11381181 .base = AstNode {.id = AstNode.Id.FnProto},
1139 .visib = visib,
1182 .visib_token = *visib_token,
11401183 .name_token = null,
11411184 .fn_token = *fn_token,
11421185 .params = ArrayList(&AstNode).init(self.allocator),
......@@ -1199,9 +1242,18 @@ const Parser = struct {
11991242 }
12001243
12011244 fn createAttachFnProto(self: &Parser, list: &ArrayList(&AstNode), fn_token: &const Token,
1202 is_extern: Extern, cc: CallingConvention, visib: Visibility, is_inline: Inline) -> %&AstNodeFnProto
1245 is_extern: Extern, cc: CallingConvention, visib_token: &const ?Token, is_inline: Inline) -> %&AstNodeFnProto
12031246 {
1204 const node = %return self.createFnProto(fn_token, is_extern, cc, visib, is_inline);
1247 const node = %return self.createFnProto(fn_token, is_extern, cc, visib_token, is_inline);
1248 %defer self.allocator.destroy(node);
1249 %return list.append(&node.base);
1250 return node;
1251 }
1252
1253 fn createAttachVarDecl(self: &Parser, list: &ArrayList(&AstNode), visib_token: &const ?Token, mut: Mutability,
1254 is_comptime: Comptime, is_extern: Extern) -> %&AstNodeVarDecl
1255 {
1256 const node = %return self.createVarDecl(visib_token, mut, is_comptime, is_extern);
12051257 %defer self.allocator.destroy(node);
12061258 %return list.append(&node.base);
12071259 return node;
......@@ -1255,8 +1307,171 @@ const Parser = struct {
12551307 self.tokenizer.next()
12561308 };
12571309 }
1258};
12591310
1311 const RenderAstFrame = struct {
1312 node: &AstNode,
1313 indent: usize,
1314 };
1315
1316 pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &AstNodeRoot) -> %void {
1317 var stack = self.initUtilityArrayList(RenderAstFrame);
1318 defer self.deinitUtilityArrayList(stack);
1319
1320 %return stack.append(RenderAstFrame {
1321 .node = &root_node.base,
1322 .indent = 0,
1323 });
1324
1325 while (stack.popOrNull()) |frame| {
1326 {
1327 var i: usize = 0;
1328 while (i < frame.indent) : (i += 1) {
1329 %return stream.print(" ");
1330 }
1331 }
1332 %return stream.print("{}\n", @tagName(frame.node.id));
1333 var child_i: usize = 0;
1334 while (frame.node.iterate(child_i)) |child| : (child_i += 1) {
1335 %return stack.append(RenderAstFrame {
1336 .node = child,
1337 .indent = frame.indent + 2,
1338 });
1339 }
1340 }
1341 }
1342
1343
1344 pub const RenderState = union(enum) {
1345 TopLevelDecl: &AstNode,
1346 FnProtoRParen: &AstNodeFnProto,
1347 ParamDecl: &AstNode,
1348 Text: []const u8,
1349 Expression: &AstNode,
1350 AddrOfExprBit: &AstNodeAddrOfExpr,
1351 };
1352
1353 pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &AstNodeRoot) -> %void {
1354 var stack = self.initUtilityArrayList(RenderState);
1355 defer self.deinitUtilityArrayList(stack);
1356
1357 {
1358 var i = root_node.decls.len;
1359 while (i != 0) {
1360 i -= 1;
1361 const decl = root_node.decls.items[i];
1362 %return stack.append(RenderState {.TopLevelDecl = decl});
1363 }
1364 }
1365
1366 while (stack.popOrNull()) |state| {
1367 switch (state) {
1368 RenderState.TopLevelDecl => |decl| {
1369 switch (decl.id) {
1370 AstNode.Id.FnProto => {
1371 const fn_proto = @fieldParentPtr(AstNodeFnProto, "base", decl);
1372 if (fn_proto.visib_token) |visib_token| {
1373 switch (visib_token.id) {
1374 Token.Id.Keyword_pub => %return stream.print("pub "),
1375 Token.Id.Keyword_export => %return stream.print("export "),
1376 else => unreachable,
1377 };
1378 }
1379 if (fn_proto.is_extern == Extern.Yes) {
1380 %return stream.print("extern ");
1381 }
1382 %return stream.print("fn");
1383
1384 if (fn_proto.name_token) |name_token| {
1385 %return stream.print(" {}", self.tokenizer.getTokenSlice(name_token));
1386 }
1387
1388 %return stream.print("(");
1389
1390 if (fn_proto.fn_def_node == null) {
1391 %return stack.append(RenderState { .Text = ";" });
1392 }
1393
1394 %return stack.append(RenderState { .FnProtoRParen = fn_proto});
1395 var i = fn_proto.params.len;
1396 while (i != 0) {
1397 i -= 1;
1398 const param_decl_node = fn_proto.params.items[i];
1399 %return stack.append(RenderState { .ParamDecl = param_decl_node});
1400 if (i != 0) {
1401 %return stack.append(RenderState { .Text = ", " });
1402 }
1403 }
1404 },
1405 else => unreachable,
1406 }
1407 },
1408 RenderState.ParamDecl => |base| {
1409 const param_decl = @fieldParentPtr(AstNodeParamDecl, "base", base);
1410 if (param_decl.comptime_token) |comptime_token| {
1411 %return stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
1412 }
1413 if (param_decl.noalias_token) |noalias_token| {
1414 %return stream.print("{} ", self.tokenizer.getTokenSlice(noalias_token));
1415 }
1416 if (param_decl.name_token) |name_token| {
1417 %return stream.print("{}: ", self.tokenizer.getTokenSlice(name_token));
1418 }
1419 if (param_decl.var_args_token) |var_args_token| {
1420 %return stream.print("{}", self.tokenizer.getTokenSlice(var_args_token));
1421 } else {
1422 %return stack.append(RenderState { .Expression = param_decl.type_node});
1423 }
1424 },
1425 RenderState.Text => |bytes| {
1426 %return stream.write(bytes);
1427 },
1428 RenderState.Expression => |base| switch (base.id) {
1429 AstNode.Id.Identifier => {
1430 const identifier = @fieldParentPtr(AstNodeIdentifier, "base", base);
1431 %return stream.print("{}", self.tokenizer.getTokenSlice(identifier.name_token));
1432 },
1433 AstNode.Id.AddrOfExpr => {
1434 const addr_of_expr = @fieldParentPtr(AstNodeAddrOfExpr, "base", base);
1435 %return stream.print("{}", self.tokenizer.getTokenSlice(addr_of_expr.op_token));
1436 %return stack.append(RenderState { .AddrOfExprBit = addr_of_expr});
1437
1438 if (addr_of_expr.align_expr) |align_expr| {
1439 %return stream.print("align(");
1440 %return stack.append(RenderState { .Text = ")"});
1441 %return stack.append(RenderState { .Expression = align_expr});
1442 }
1443 },
1444 else => unreachable,
1445 },
1446 RenderState.AddrOfExprBit => |addr_of_expr| {
1447 if (addr_of_expr.bit_offset_start_token) |bit_offset_start_token| {
1448 %return stream.print("{} ", self.tokenizer.getTokenSlice(bit_offset_start_token));
1449 }
1450 if (addr_of_expr.bit_offset_end_token) |bit_offset_end_token| {
1451 %return stream.print("{} ", self.tokenizer.getTokenSlice(bit_offset_end_token));
1452 }
1453 if (addr_of_expr.const_token) |const_token| {
1454 %return stream.print("{} ", self.tokenizer.getTokenSlice(const_token));
1455 }
1456 if (addr_of_expr.volatile_token) |volatile_token| {
1457 %return stream.print("{} ", self.tokenizer.getTokenSlice(volatile_token));
1458 }
1459 %return stack.append(RenderState { .Expression = addr_of_expr.op_expr});
1460 },
1461 RenderState.FnProtoRParen => |fn_proto| {
1462 %return stream.print(")");
1463 if (fn_proto.align_expr != null) {
1464 @panic("TODO");
1465 }
1466 if (fn_proto.return_type) |return_type| {
1467 %return stream.print(" -> ");
1468 %return stack.append(RenderState { .Expression = return_type});
1469 }
1470 },
1471 }
1472 }
1473 }
1474};
12601475
12611476pub fn main() -> %void {
12621477 main2() %% |err| {
......@@ -1277,6 +1492,11 @@ pub fn main2() -> %void {
12771492 const target_file = args[1];
12781493
12791494 const target_file_buf = %return io.readFileAlloc(target_file, allocator);
1495 defer allocator.free(target_file_buf);
1496
1497 var stderr_file = %return std.io.getStdErr();
1498 var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
1499 const out_stream = &stderr_file_out_stream.stream;
12801500
12811501 warn("====input:====\n");
12821502
......@@ -1298,24 +1518,15 @@ pub fn main2() -> %void {
12981518
12991519 var tokenizer = Tokenizer.init(target_file_buf);
13001520 var parser = Parser.init(&tokenizer, allocator, target_file);
1301 const node = %return parser.parse();
1521 defer parser.deinit();
13021522
1523 const root_node = %return parser.parse();
1524 defer parser.freeAst(root_node);
13031525
1304 render(node, 0);
1305}
1526 %return parser.renderAst(out_stream, root_node);
13061527
1307fn render(node: &AstNode, indent: usize) {
1308 {
1309 var i: usize = 0;
1310 while (i < indent) : (i += 1) {
1311 warn(" ");
1312 }
1313 }
1314 warn("{}\n", @tagName(node.id));
1315 var i: usize = 0;
1316 while (node.iterate(i)) |child| : (i += 1) {
1317 render(child, indent + 2);
1318 }
1528 warn("====fmt:====\n");
1529 %return parser.renderSource(out_stream, root_node);
13191530}
13201531
13211532fn removeNullCast(x: var) -> {const InnerPtr = @typeOf(x).Child.Child; &InnerPtr} {
src/analyze.cpp+1-1
......@@ -2227,7 +2227,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
22272227
22282228 tag_type = new_type_table_entry(TypeTableEntryIdEnum);
22292229 buf_resize(&tag_type->name, 0);
2230 buf_appendf(&tag_type->name, "@TagType(%s)", buf_ptr(&union_type->name));
2230 buf_appendf(&tag_type->name, "@EnumTagType(%s)", buf_ptr(&union_type->name));
22312231 tag_type->is_copyable = true;
22322232 tag_type->type_ref = tag_int_type->type_ref;
22332233 tag_type->zero_bits = tag_int_type->zero_bits;
std/array_list.zig+20-10
......@@ -3,21 +3,25 @@ const assert = debug.assert;
33const mem = @import("mem.zig");
44const Allocator = mem.Allocator;
55
6pub fn ArrayList(comptime T: type) -> type{
6pub fn ArrayList(comptime T: type) -> type {
7 return AlignedArrayList(T, @alignOf(T));
8}
9
10pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{
711 struct {
812 const Self = this;
913
1014 /// Use toSlice instead of slicing this directly, because if you don't
1115 /// specify the end position of the slice, this will potentially give
1216 /// you uninitialized memory.
13 items: []T,
17 items: []align(A) T,
1418 len: usize,
1519 allocator: &Allocator,
1620
1721 /// Deinitialize with `deinit` or use `toOwnedSlice`.
1822 pub fn init(allocator: &Allocator) -> Self {
1923 Self {
20 .items = []T{},
24 .items = []align(A) T{},
2125 .len = 0,
2226 .allocator = allocator,
2327 }
......@@ -27,18 +31,18 @@ pub fn ArrayList(comptime T: type) -> type{
2731 l.allocator.free(l.items);
2832 }
2933
30 pub fn toSlice(l: &Self) -> []T {
34 pub fn toSlice(l: &Self) -> []align(A) T {
3135 return l.items[0..l.len];
3236 }
3337
34 pub fn toSliceConst(l: &const Self) -> []const T {
38 pub fn toSliceConst(l: &const Self) -> []align(A) const T {
3539 return l.items[0..l.len];
3640 }
3741
3842 /// ArrayList takes ownership of the passed in slice. The slice must have been
3943 /// allocated with `allocator`.
4044 /// Deinitialize with `deinit` or use `toOwnedSlice`.
41 pub fn fromOwnedSlice(allocator: &Allocator, slice: []T) -> Self {
45 pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) -> Self {
4246 return Self {
4347 .items = slice,
4448 .len = slice.len,
......@@ -47,9 +51,9 @@ pub fn ArrayList(comptime T: type) -> type{
4751 }
4852
4953 /// The caller owns the returned memory. ArrayList becomes empty.
50 pub fn toOwnedSlice(self: &Self) -> []T {
54 pub fn toOwnedSlice(self: &Self) -> []align(A) T {
5155 const allocator = self.allocator;
52 const result = allocator.shrink(T, self.items, self.len);
56 const result = allocator.alignedShrink(T, A, self.items, self.len);
5357 *self = init(allocator);
5458 return result;
5559 }
......@@ -59,7 +63,7 @@ pub fn ArrayList(comptime T: type) -> type{
5963 *new_item_ptr = *item;
6064 }
6165
62 pub fn appendSlice(l: &Self, items: []const T) -> %void {
66 pub fn appendSlice(l: &Self, items: []align(A) const T) -> %void {
6367 %return l.ensureCapacity(l.len + items.len);
6468 mem.copy(T, l.items[l.len..], items);
6569 l.len += items.len;
......@@ -82,7 +86,7 @@ pub fn ArrayList(comptime T: type) -> type{
8286 better_capacity += better_capacity / 2 + 8;
8387 if (better_capacity >= new_capacity) break;
8488 }
85 l.items = %return l.allocator.realloc(T, l.items, better_capacity);
89 l.items = %return l.allocator.alignedRealloc(T, A, l.items, better_capacity);
8690 }
8791
8892 pub fn addOne(l: &Self) -> %&T {
......@@ -97,6 +101,12 @@ pub fn ArrayList(comptime T: type) -> type{
97101 self.len -= 1;
98102 return self.items[self.len];
99103 }
104
105 pub fn popOrNull(self: &Self) -> ?T {
106 if (self.len == 0)
107 return null;
108 return self.pop();
109 }
100110 }
101111}
102112
std/index.zig+7-6
......@@ -1,4 +1,5 @@
11pub const ArrayList = @import("array_list.zig").ArrayList;
2pub const AlignedArrayList = @import("array_list.zig").AlignedArrayList;
23pub const BufMap = @import("buf_map.zig").BufMap;
34pub const BufSet = @import("buf_set.zig").BufSet;
45pub const Buffer = @import("buffer.zig").Buffer;
......@@ -26,12 +27,12 @@ pub const sort = @import("sort.zig");
2627
2728test "std" {
2829 // run tests from these
29 _ = @import("array_list.zig").ArrayList;
30 _ = @import("buf_map.zig").BufMap;
31 _ = @import("buf_set.zig").BufSet;
32 _ = @import("buffer.zig").Buffer;
33 _ = @import("hash_map.zig").HashMap;
34 _ = @import("linked_list.zig").LinkedList;
30 _ = @import("array_list.zig");
31 _ = @import("buf_map.zig");
32 _ = @import("buf_set.zig");
33 _ = @import("buffer.zig");
34 _ = @import("hash_map.zig");
35 _ = @import("linked_list.zig");
3536
3637 _ = @import("base64.zig");
3738 _ = @import("build.zig");
std/mem.zig+1-12
......@@ -8,7 +8,6 @@ pub const Cmp = math.Cmp;
88pub const Allocator = struct {
99 /// Allocate byte_count bytes and return them in a slice, with the
1010 /// slice's pointer aligned at least to alignment bytes.
11 /// The returned newly allocated memory is undefined.
1211 allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) -> %[]u8,
1312
1413 /// If `new_byte_count > old_mem.len`:
......@@ -18,8 +17,6 @@ pub const Allocator = struct {
1817 /// If `new_byte_count <= old_mem.len`:
1918 /// * this function must return successfully.
2019 /// * alignment <= alignment of old_mem.ptr
21 ///
22 /// The returned newly allocated memory is undefined.
2320 reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) -> %[]u8,
2421
2522 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
......@@ -43,10 +40,6 @@ pub const Allocator = struct {
4340 {
4441 const byte_count = %return math.mul(usize, @sizeOf(T), n);
4542 const byte_slice = %return self.allocFn(self, byte_count, alignment);
46 // This loop should get optimized out in ReleaseFast mode
47 for (byte_slice) |*byte| {
48 *byte = undefined;
49 }
5043 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
5144 }
5245
......@@ -63,10 +56,6 @@ pub const Allocator = struct {
6356
6457 const byte_count = %return math.mul(usize, @sizeOf(T), n);
6558 const byte_slice = %return self.reallocFn(self, ([]u8)(old_mem), byte_count, alignment);
66 // This loop should get optimized out in ReleaseFast mode
67 for (byte_slice[old_mem.len..]) |*byte| {
68 *byte = undefined;
69 }
7059 return ([]T)(@alignCast(alignment, byte_slice));
7160 }
7261
......@@ -92,7 +81,7 @@ pub const Allocator = struct {
9281 const byte_count = @sizeOf(T) * n;
9382
9483 const byte_slice = %%self.reallocFn(self, ([]u8)(old_mem), byte_count, alignment);
95 return ([]T)(@alignCast(alignment, byte_slice));
84 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
9685 }
9786
9887 fn free(self: &Allocator, memory: var) {