authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-11 09:21:06-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-11 09:21:06-05:00
logfd6a36a23509fb956e05f0052b8ab5a80ead3380
tree3d4467eae7a82b33d7684255e63b6df8cea3dd51
parent9a51091a5c3d7547989d705e3feebad6252019a6

self-hosted: parsing and rendering blocks


2 files changed, 292 insertions(+), 107 deletions(-)

src-self-hosted/main.zig+284-107
...@@ -169,7 +169,7 @@ const Tokenizer = struct {...@@ -169,7 +169,7 @@ const Tokenizer = struct {
169 if (c == '\n') {169 if (c == '\n') {
170 loc.line += 1;170 loc.line += 1;
171 loc.column = 0;171 loc.column = 0;
172 loc.line_start = i;172 loc.line_start = i + 1;
173 } else {173 } else {
174 loc.column += 1;174 loc.column += 1;
175 }175 }
...@@ -520,6 +520,7 @@ const AstNode = struct {...@@ -520,6 +520,7 @@ const AstNode = struct {
520 FnProto,520 FnProto,
521 ParamDecl,521 ParamDecl,
522 AddrOfExpr,522 AddrOfExpr,
523 Block,
523 };524 };
524525
525 fn iterate(base: &AstNode, index: usize) -> ?&AstNode {526 fn iterate(base: &AstNode, index: usize) -> ?&AstNode {
...@@ -530,6 +531,7 @@ const AstNode = struct {...@@ -530,6 +531,7 @@ const AstNode = struct {
530 Id.FnProto => @fieldParentPtr(AstNodeFnProto, "base", base).iterate(index),531 Id.FnProto => @fieldParentPtr(AstNodeFnProto, "base", base).iterate(index),
531 Id.ParamDecl => @fieldParentPtr(AstNodeParamDecl, "base", base).iterate(index),532 Id.ParamDecl => @fieldParentPtr(AstNodeParamDecl, "base", base).iterate(index),
532 Id.AddrOfExpr => @fieldParentPtr(AstNodeAddrOfExpr, "base", base).iterate(index),533 Id.AddrOfExpr => @fieldParentPtr(AstNodeAddrOfExpr, "base", base).iterate(index),
534 Id.Block => @fieldParentPtr(AstNodeBlock, "base", base).iterate(index),
533 };535 };
534 }536 }
535537
...@@ -541,6 +543,7 @@ const AstNode = struct {...@@ -541,6 +543,7 @@ const AstNode = struct {
541 Id.FnProto => allocator.destroy(@fieldParentPtr(AstNodeFnProto, "base", base)),543 Id.FnProto => allocator.destroy(@fieldParentPtr(AstNodeFnProto, "base", base)),
542 Id.ParamDecl => allocator.destroy(@fieldParentPtr(AstNodeParamDecl, "base", base)),544 Id.ParamDecl => allocator.destroy(@fieldParentPtr(AstNodeParamDecl, "base", base)),
543 Id.AddrOfExpr => allocator.destroy(@fieldParentPtr(AstNodeAddrOfExpr, "base", base)),545 Id.AddrOfExpr => allocator.destroy(@fieldParentPtr(AstNodeAddrOfExpr, "base", base)),
546 Id.Block => allocator.destroy(@fieldParentPtr(AstNodeBlock, "base", base)),
544 };547 };
545 }548 }
546};549};
...@@ -551,7 +554,7 @@ const AstNodeRoot = struct {...@@ -551,7 +554,7 @@ const AstNodeRoot = struct {
551554
552 fn iterate(self: &AstNodeRoot, index: usize) -> ?&AstNode {555 fn iterate(self: &AstNodeRoot, index: usize) -> ?&AstNode {
553 if (index < self.decls.len) {556 if (index < self.decls.len) {
554 return self.decls.items[index];557 return self.decls.items[self.decls.len - index - 1];
555 }558 }
556 return null;559 return null;
557 }560 }
...@@ -612,36 +615,36 @@ const AstNodeFnProto = struct {...@@ -612,36 +615,36 @@ const AstNodeFnProto = struct {
612 extern_token: ?Token,615 extern_token: ?Token,
613 inline_token: ?Token,616 inline_token: ?Token,
614 cc_token: ?Token,617 cc_token: ?Token,
615 fn_def_node: ?&AstNode,618 body_node: ?&AstNode,
616 lib_name: ?&AstNode, // populated if this is an extern declaration619 lib_name: ?&AstNode, // populated if this is an extern declaration
617 align_expr: ?&AstNode, // populated if align(A) is present620 align_expr: ?&AstNode, // populated if align(A) is present
618621
619 fn iterate(self: &AstNodeFnProto, index: usize) -> ?&AstNode {622 fn iterate(self: &AstNodeFnProto, index: usize) -> ?&AstNode {
620 var i = index;623 var i = index;
621624
622 if (i < self.params.len) return self.params.items[i];625 if (self.body_node) |body_node| {
623 i -= self.params.len;626 if (i < 1) return body_node;
627 i -= 1;
628 }
624629
625 if (self.return_type) |return_type| {630 if (self.return_type) |return_type| {
626 if (i < 1) return return_type;631 if (i < 1) return return_type;
627 i -= 1;632 i -= 1;
628 }633 }
629634
630 if (self.fn_def_node) |fn_def_node| {635 if (self.align_expr) |align_expr| {
631 if (i < 1) return fn_def_node;636 if (i < 1) return align_expr;
632 i -= 1;637 i -= 1;
633 }638 }
634639
640 if (i < self.params.len) return self.params.items[self.params.len - i - 1];
641 i -= self.params.len;
642
635 if (self.lib_name) |lib_name| {643 if (self.lib_name) |lib_name| {
636 if (i < 1) return lib_name;644 if (i < 1) return lib_name;
637 i -= 1;645 i -= 1;
638 }646 }
639647
640 if (self.align_expr) |align_expr| {
641 if (i < 1) return align_expr;
642 i -= 1;
643 }
644
645 return null;648 return null;
646 }649 }
647};650};
...@@ -689,6 +692,22 @@ const AstNodeAddrOfExpr = struct {...@@ -689,6 +692,22 @@ const AstNodeAddrOfExpr = struct {
689 }692 }
690};693};
691694
695const AstNodeBlock = struct {
696 base: AstNode,
697 begin_token: Token,
698 end_token: Token,
699 statements: ArrayList(&AstNode),
700
701 fn iterate(self: &AstNodeBlock, index: usize) -> ?&AstNode {
702 var i = index;
703
704 if (i < self.statements.len) return self.statements.items[i];
705 i -= self.statements.len;
706
707 return null;
708 }
709};
710
692error ParseError;711error ParseError;
693712
694const Parser = struct {713const Parser = struct {
...@@ -734,27 +753,41 @@ const Parser = struct {...@@ -734,27 +753,41 @@ const Parser = struct {
734 extern_token: ?Token,753 extern_token: ?Token,
735 };754 };
736755
756 const DestPtr = union(enum) {
757 Field: &&AstNode,
758 NullableField: &?&AstNode,
759 List: &ArrayList(&AstNode),
760
761 pub fn store(self: &const DestPtr, value: &AstNode) -> %void {
762 switch (*self) {
763 DestPtr.Field => |ptr| *ptr = value,
764 DestPtr.NullableField => |ptr| *ptr = value,
765 DestPtr.List => |list| %return list.append(value),
766 }
767 }
768 };
769
737 const State = union(enum) {770 const State = union(enum) {
738 TopLevel,771 TopLevel,
739 TopLevelExtern: ?Token,772 TopLevelExtern: ?Token,
740 TopLevelDecl: TopLevelDeclCtx,773 TopLevelDecl: TopLevelDeclCtx,
741 Expression: &&AstNode,774 Expression: DestPtr,
742 GroupedExpression: &&AstNode,775 GroupedExpression: DestPtr,
743 UnwrapExpression: &&AstNode,776 UnwrapExpression: DestPtr,
744 BoolOrExpression: &&AstNode,777 BoolOrExpression: DestPtr,
745 BoolAndExpression: &&AstNode,778 BoolAndExpression: DestPtr,
746 ComparisonExpression: &&AstNode,779 ComparisonExpression: DestPtr,
747 BinaryOrExpression: &&AstNode,780 BinaryOrExpression: DestPtr,
748 BinaryXorExpression: &&AstNode,781 BinaryXorExpression: DestPtr,
749 BinaryAndExpression: &&AstNode,782 BinaryAndExpression: DestPtr,
750 BitShiftExpression: &&AstNode,783 BitShiftExpression: DestPtr,
751 AdditionExpression: &&AstNode,784 AdditionExpression: DestPtr,
752 MultiplyExpression: &&AstNode,785 MultiplyExpression: DestPtr,
753 BraceSuffixExpression: &&AstNode,786 BraceSuffixExpression: DestPtr,
754 PrefixOpExpression: &&AstNode,787 PrefixOpExpression: DestPtr,
755 SuffixOpExpression: &&AstNode,788 SuffixOpExpression: DestPtr,
756 PrimaryExpression: &&AstNode,789 PrimaryExpression: DestPtr,
757 TypeExpr: &&AstNode,790 TypeExpr: DestPtr,
758 VarDecl: &AstNodeVarDecl,791 VarDecl: &AstNodeVarDecl,
759 VarDeclAlign: &AstNodeVarDecl,792 VarDeclAlign: &AstNodeVarDecl,
760 VarDeclEq: &AstNodeVarDecl,793 VarDeclEq: &AstNodeVarDecl,
...@@ -763,6 +796,9 @@ const Parser = struct {...@@ -763,6 +796,9 @@ const Parser = struct {
763 FnProtoAlign: &AstNodeFnProto,796 FnProtoAlign: &AstNodeFnProto,
764 ParamDecl: &AstNodeFnProto,797 ParamDecl: &AstNodeFnProto,
765 ParamDeclComma,798 ParamDeclComma,
799 FnDef: &AstNodeFnProto,
800 Block: &AstNodeBlock,
801 Statement: &AstNodeBlock,
766 };802 };
767803
768 pub fn freeAst(self: &Parser, root_node: &AstNodeRoot) {804 pub fn freeAst(self: &Parser, root_node: &AstNodeRoot) {
...@@ -797,6 +833,18 @@ const Parser = struct {...@@ -797,6 +833,18 @@ const Parser = struct {
797 %defer self.freeAst(root_node);833 %defer self.freeAst(root_node);
798834
799 while (true) {835 while (true) {
836 //{
837 // const token = self.getNextToken();
838 // warn("{} ", @tagName(token.id));
839 // self.putBackToken(token);
840 // var i: usize = stack.len;
841 // while (i != 0) {
842 // i -= 1;
843 // warn("{} ", @tagName(stack.items[i]));
844 // }
845 // warn("\n");
846 //}
847
800 // This gives us 1 free append that can't fail848 // This gives us 1 free append that can't fail
801 const state = stack.pop();849 const state = stack.pop();
802850
...@@ -850,11 +898,11 @@ const Parser = struct {...@@ -850,11 +898,11 @@ const Parser = struct {
850 },898 },
851 Token.Id.Keyword_fn => {899 Token.Id.Keyword_fn => {
852 stack.append(State.TopLevel) %% unreachable;900 stack.append(State.TopLevel) %% unreachable;
853 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
854 // TODO shouldn't need these casts901 // TODO shouldn't need these casts
855 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,902 const fn_proto = %return self.createAttachFnProto(&root_node.decls, token,
856 ctx.extern_token, (?Token)(null), (?Token)(null), (?Token)(null));903 ctx.extern_token, (?Token)(null), (?Token)(null), (?Token)(null));
857 %return stack.append(State { .FnProto = fn_proto_node });904 %return stack.append(State { .FnDef = fn_proto });
905 %return stack.append(State { .FnProto = fn_proto });
858 continue;906 continue;
859 },907 },
860 Token.Id.StringLiteral => {908 Token.Id.StringLiteral => {
...@@ -862,12 +910,12 @@ const Parser = struct {...@@ -862,12 +910,12 @@ const Parser = struct {
862 },910 },
863 Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {911 Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
864 stack.append(State.TopLevel) %% unreachable;912 stack.append(State.TopLevel) %% unreachable;
865 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
866 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);913 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);
867 // TODO shouldn't need this cast914 // TODO shouldn't need this cast
868 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,915 const fn_proto = %return self.createAttachFnProto(&root_node.decls, fn_token,
869 ctx.extern_token, (?Token)(token), (?Token)(null), (?Token)(null));916 ctx.extern_token, (?Token)(token), (?Token)(null), (?Token)(null));
870 %return stack.append(State { .FnProto = fn_proto_node });917 %return stack.append(State { .FnDef = fn_proto });
918 %return stack.append(State { .FnProto = fn_proto });
871 continue;919 continue;
872 },920 },
873 else => return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id)),921 else => return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id)),
...@@ -879,7 +927,7 @@ const Parser = struct {...@@ -879,7 +927,7 @@ const Parser = struct {
879927
880 const next_token = self.getNextToken();928 const next_token = self.getNextToken();
881 if (next_token.id == Token.Id.Colon) {929 if (next_token.id == Token.Id.Colon) {
882 %return stack.append(State { .TypeExpr = removeNullCast(&var_decl.type_node) });930 %return stack.append(State { .TypeExpr = DestPtr {.NullableField = &var_decl.type_node} });
883 continue;931 continue;
884 }932 }
885933
...@@ -891,7 +939,11 @@ const Parser = struct {...@@ -891,7 +939,11 @@ const Parser = struct {
891939
892 const next_token = self.getNextToken();940 const next_token = self.getNextToken();
893 if (next_token.id == Token.Id.Keyword_align) {941 if (next_token.id == Token.Id.Keyword_align) {
894 %return stack.append(State { .GroupedExpression = removeNullCast(&var_decl.align_node) });942 %return stack.append(State {
943 .GroupedExpression = DestPtr {
944 .NullableField = &var_decl.align_node
945 }
946 });
895 continue;947 continue;
896 }948 }
897949
...@@ -904,7 +956,7 @@ const Parser = struct {...@@ -904,7 +956,7 @@ const Parser = struct {
904 var_decl.eq_token = token;956 var_decl.eq_token = token;
905 stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;957 stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;
906 %return stack.append(State {958 %return stack.append(State {
907 .Expression = removeNullCast(&var_decl.init_node),959 .Expression = DestPtr {.NullableField = &var_decl.init_node},
908 });960 });
909 continue;961 continue;
910 }962 }
...@@ -917,70 +969,70 @@ const Parser = struct {...@@ -917,70 +969,70 @@ const Parser = struct {
917 _ = %return self.eatToken(token_id);969 _ = %return self.eatToken(token_id);
918 continue;970 continue;
919 },971 },
920 State.Expression => |result_ptr| {972 State.Expression => |dest_ptr| {
921 stack.append(State {.UnwrapExpression = result_ptr}) %% unreachable;973 stack.append(State {.UnwrapExpression = dest_ptr}) %% unreachable;
922 continue;974 continue;
923 },975 },
924976
925 State.UnwrapExpression => |result_ptr| {977 State.UnwrapExpression => |dest_ptr| {
926 stack.append(State {.BoolOrExpression = result_ptr}) %% unreachable;978 stack.append(State {.BoolOrExpression = dest_ptr}) %% unreachable;
927 continue;979 continue;
928 },980 },
929981
930 State.BoolOrExpression => |result_ptr| {982 State.BoolOrExpression => |dest_ptr| {
931 stack.append(State {.BoolAndExpression = result_ptr}) %% unreachable;983 stack.append(State {.BoolAndExpression = dest_ptr}) %% unreachable;
932 continue;984 continue;
933 },985 },
934986
935 State.BoolAndExpression => |result_ptr| {987 State.BoolAndExpression => |dest_ptr| {
936 stack.append(State {.ComparisonExpression = result_ptr}) %% unreachable;988 stack.append(State {.ComparisonExpression = dest_ptr}) %% unreachable;
937 continue;989 continue;
938 },990 },
939991
940 State.ComparisonExpression => |result_ptr| {992 State.ComparisonExpression => |dest_ptr| {
941 stack.append(State {.BinaryOrExpression = result_ptr}) %% unreachable;993 stack.append(State {.BinaryOrExpression = dest_ptr}) %% unreachable;
942 continue;994 continue;
943 },995 },
944996
945 State.BinaryOrExpression => |result_ptr| {997 State.BinaryOrExpression => |dest_ptr| {
946 stack.append(State {.BinaryXorExpression = result_ptr}) %% unreachable;998 stack.append(State {.BinaryXorExpression = dest_ptr}) %% unreachable;
947 continue;999 continue;
948 },1000 },
9491001
950 State.BinaryXorExpression => |result_ptr| {1002 State.BinaryXorExpression => |dest_ptr| {
951 stack.append(State {.BinaryAndExpression = result_ptr}) %% unreachable;1003 stack.append(State {.BinaryAndExpression = dest_ptr}) %% unreachable;
952 continue;1004 continue;
953 },1005 },
9541006
955 State.BinaryAndExpression => |result_ptr| {1007 State.BinaryAndExpression => |dest_ptr| {
956 stack.append(State {.BitShiftExpression = result_ptr}) %% unreachable;1008 stack.append(State {.BitShiftExpression = dest_ptr}) %% unreachable;
957 continue;1009 continue;
958 },1010 },
9591011
960 State.BitShiftExpression => |result_ptr| {1012 State.BitShiftExpression => |dest_ptr| {
961 stack.append(State {.AdditionExpression = result_ptr}) %% unreachable;1013 stack.append(State {.AdditionExpression = dest_ptr}) %% unreachable;
962 continue;1014 continue;
963 },1015 },
9641016
965 State.AdditionExpression => |result_ptr| {1017 State.AdditionExpression => |dest_ptr| {
966 stack.append(State {.MultiplyExpression = result_ptr}) %% unreachable;1018 stack.append(State {.MultiplyExpression = dest_ptr}) %% unreachable;
967 continue;1019 continue;
968 },1020 },
9691021
970 State.MultiplyExpression => |result_ptr| {1022 State.MultiplyExpression => |dest_ptr| {
971 stack.append(State {.BraceSuffixExpression = result_ptr}) %% unreachable;1023 stack.append(State {.BraceSuffixExpression = dest_ptr}) %% unreachable;
972 continue;1024 continue;
973 },1025 },
9741026
975 State.BraceSuffixExpression => |result_ptr| {1027 State.BraceSuffixExpression => |dest_ptr| {
976 stack.append(State {.PrefixOpExpression = result_ptr}) %% unreachable;1028 stack.append(State {.PrefixOpExpression = dest_ptr}) %% unreachable;
977 continue;1029 continue;
978 },1030 },
9791031
980 State.PrefixOpExpression => |result_ptr| {1032 State.PrefixOpExpression => |dest_ptr| {
981 const first_token = self.getNextToken();1033 const first_token = self.getNextToken();
982 if (first_token.id == Token.Id.Ampersand) {1034 if (first_token.id == Token.Id.Ampersand) {
983 const addr_of_expr = %return self.createAttachAddrOfExpr(result_ptr, first_token);1035 const addr_of_expr = %return self.createAttachAddrOfExpr(dest_ptr, first_token);
984 var token = self.getNextToken();1036 var token = self.getNextToken();
985 if (token.id == Token.Id.Keyword_align) {1037 if (token.id == Token.Id.Keyword_align) {
986 @panic("TODO align");1038 @panic("TODO align");
...@@ -994,40 +1046,42 @@ const Parser = struct {...@@ -994,40 +1046,42 @@ const Parser = struct {
994 token = self.getNextToken();1046 token = self.getNextToken();
995 }1047 }
996 self.putBackToken(token);1048 self.putBackToken(token);
997 stack.append(State { .PrefixOpExpression = &addr_of_expr.op_expr }) %% unreachable;1049 stack.append(State {
1050 .PrefixOpExpression = DestPtr { .Field = &addr_of_expr.op_expr},
1051 }) %% unreachable;
998 continue;1052 continue;
999 }1053 }
10001054
1001 self.putBackToken(first_token);1055 self.putBackToken(first_token);
1002 stack.append(State { .SuffixOpExpression = result_ptr }) %% unreachable;1056 stack.append(State { .SuffixOpExpression = dest_ptr }) %% unreachable;
1003 continue;1057 continue;
1004 },1058 },
10051059
1006 State.SuffixOpExpression => |result_ptr| {1060 State.SuffixOpExpression => |dest_ptr| {
1007 stack.append(State { .PrimaryExpression = result_ptr }) %% unreachable;1061 stack.append(State { .PrimaryExpression = dest_ptr }) %% unreachable;
1008 continue;1062 continue;
1009 },1063 },
10101064
1011 State.PrimaryExpression => |result_ptr| {1065 State.PrimaryExpression => |dest_ptr| {
1012 const token = self.getNextToken();1066 const token = self.getNextToken();
1013 switch (token.id) {1067 switch (token.id) {
1014 Token.Id.Identifier => {1068 Token.Id.Identifier => {
1015 const identifier = %return self.createIdentifier(token);1069 const identifier = %return self.createIdentifier(token);
1016 *result_ptr = &identifier.base;1070 %return dest_ptr.store(&identifier.base);
1017 continue;1071 continue;
1018 },1072 },
1019 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),1073 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),
1020 }1074 }
1021 },1075 },
10221076
1023 State.TypeExpr => |result_ptr| {1077 State.TypeExpr => |dest_ptr| {
1024 const token = self.getNextToken();1078 const token = self.getNextToken();
1025 if (token.id == Token.Id.Keyword_var) {1079 if (token.id == Token.Id.Keyword_var) {
1026 @panic("TODO param with type var");1080 @panic("TODO param with type var");
1027 }1081 }
1028 self.putBackToken(token);1082 self.putBackToken(token);
10291083
1030 stack.append(State { .PrefixOpExpression = result_ptr }) %% unreachable;1084 stack.append(State { .PrefixOpExpression = dest_ptr }) %% unreachable;
1031 continue;1085 continue;
1032 },1086 },
10331087
...@@ -1051,7 +1105,9 @@ const Parser = struct {...@@ -1051,7 +1105,9 @@ const Parser = struct {
1051 @panic("TODO fn proto align");1105 @panic("TODO fn proto align");
1052 }1106 }
1053 if (token.id == Token.Id.Arrow) {1107 if (token.id == Token.Id.Arrow) {
1054 stack.append(State { .TypeExpr = removeNullCast(&fn_proto.return_type) }) %% unreachable;1108 stack.append(State {
1109 .TypeExpr = DestPtr {.NullableField = &fn_proto.return_type},
1110 }) %% unreachable;
1055 continue;1111 continue;
1056 } else {1112 } else {
1057 self.putBackToken(token);1113 self.putBackToken(token);
...@@ -1091,7 +1147,9 @@ const Parser = struct {...@@ -1091,7 +1147,9 @@ const Parser = struct {
10911147
1092 stack.append(State { .ParamDecl = fn_proto }) %% unreachable;1148 stack.append(State { .ParamDecl = fn_proto }) %% unreachable;
1093 %return stack.append(State.ParamDeclComma);1149 %return stack.append(State.ParamDeclComma);
1094 %return stack.append(State { .TypeExpr = &param_decl.type_node });1150 %return stack.append(State {
1151 .TypeExpr = DestPtr {.Field = &param_decl.type_node}
1152 });
1095 continue;1153 continue;
1096 },1154 },
10971155
...@@ -1107,6 +1165,70 @@ const Parser = struct {...@@ -1107,6 +1165,70 @@ const Parser = struct {
1107 }1165 }
1108 },1166 },
11091167
1168 State.FnDef => |fn_proto| {
1169 const token = self.getNextToken();
1170 switch(token.id) {
1171 Token.Id.LBrace => {
1172 const block = %return self.createBlock(token);
1173 fn_proto.body_node = &block.base;
1174 stack.append(State { .Block = block }) %% unreachable;
1175 continue;
1176 },
1177 Token.Id.Semicolon => continue,
1178 else => return self.parseError(token, "expected ';' or '{{', found {}", @tagName(token.id)),
1179 }
1180 },
1181
1182 State.Block => |block| {
1183 const token = self.getNextToken();
1184 switch (token.id) {
1185 Token.Id.RBrace => {
1186 block.end_token = token;
1187 continue;
1188 },
1189 else => {
1190 self.putBackToken(token);
1191 stack.append(State { .Block = block }) %% unreachable;
1192 %return stack.append(State { .Statement = block });
1193 continue;
1194 },
1195 }
1196 },
1197
1198 State.Statement => |block| {
1199 {
1200 // Look for comptime var, comptime const
1201 const comptime_token = self.getNextToken();
1202 if (comptime_token.id == Token.Id.Keyword_comptime) {
1203 const mut_token = self.getNextToken();
1204 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
1205 // TODO shouldn't need these casts
1206 const var_decl = %return self.createAttachVarDecl(&block.statements, (?Token)(null),
1207 mut_token, (?Token)(comptime_token), (?Token)(null));
1208 %return stack.append(State { .VarDecl = var_decl });
1209 continue;
1210 }
1211 self.putBackToken(mut_token);
1212 }
1213 self.putBackToken(comptime_token);
1214 }
1215 {
1216 // Look for const, var
1217 const mut_token = self.getNextToken();
1218 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
1219 // TODO shouldn't need these casts
1220 const var_decl = %return self.createAttachVarDecl(&block.statements, (?Token)(null),
1221 mut_token, (?Token)(null), (?Token)(null));
1222 %return stack.append(State { .VarDecl = var_decl });
1223 continue;
1224 }
1225 self.putBackToken(mut_token);
1226 }
1227
1228 stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;
1229 %return stack.append(State { .Expression = DestPtr{.List = &block.statements} });
1230 continue;
1231 },
11101232
1111 State.GroupedExpression => @panic("TODO"),1233 State.GroupedExpression => @panic("TODO"),
1112 }1234 }
...@@ -1176,7 +1298,7 @@ const Parser = struct {...@@ -1176,7 +1298,7 @@ const Parser = struct {
1176 .extern_token = *extern_token,1298 .extern_token = *extern_token,
1177 .inline_token = *inline_token,1299 .inline_token = *inline_token,
1178 .cc_token = *cc_token,1300 .cc_token = *cc_token,
1179 .fn_def_node = null,1301 .body_node = null,
1180 .lib_name = null,1302 .lib_name = null,
1181 .align_expr = null,1303 .align_expr = null,
1182 };1304 };
...@@ -1215,10 +1337,23 @@ const Parser = struct {...@@ -1215,10 +1337,23 @@ const Parser = struct {
1215 return node;1337 return node;
1216 }1338 }
12171339
1218 fn createAttachAddrOfExpr(self: &Parser, result_ptr: &&AstNode, op_token: &const Token) -> %&AstNodeAddrOfExpr {1340 fn createBlock(self: &Parser, begin_token: &const Token) -> %&AstNodeBlock {
1341 const node = %return self.allocator.create(AstNodeBlock);
1342 %defer self.allocator.destroy(node);
1343
1344 *node = AstNodeBlock {
1345 .base = AstNode {.id = AstNode.Id.Block},
1346 .begin_token = *begin_token,
1347 .end_token = undefined,
1348 .statements = ArrayList(&AstNode).init(self.allocator),
1349 };
1350 return node;
1351 }
1352
1353 fn createAttachAddrOfExpr(self: &Parser, dest_ptr: &const DestPtr, op_token: &const Token) -> %&AstNodeAddrOfExpr {
1219 const node = %return self.createAddrOfExpr(op_token);1354 const node = %return self.createAddrOfExpr(op_token);
1220 %defer self.allocator.destroy(node);1355 %defer self.allocator.destroy(node);
1221 *result_ptr = &node.base;1356 %return dest_ptr.store(&node.base);
1222 return node;1357 return node;
1223 }1358 }
12241359
...@@ -1337,7 +1472,11 @@ const Parser = struct {...@@ -1337,7 +1472,11 @@ const Parser = struct {
1337 Text: []const u8,1472 Text: []const u8,
1338 Expression: &AstNode,1473 Expression: &AstNode,
1339 AddrOfExprBit: &AstNodeAddrOfExpr,1474 AddrOfExprBit: &AstNodeAddrOfExpr,
1475 VarDecl: &AstNodeVarDecl,
1340 VarDeclAlign: &AstNodeVarDecl,1476 VarDeclAlign: &AstNodeVarDecl,
1477 Statement: &AstNode,
1478 PrintIndent,
1479 Indent: usize,
1341 };1480 };
13421481
1343 pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &AstNodeRoot) -> %void {1482 pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &AstNodeRoot) -> %void {
...@@ -1353,6 +1492,8 @@ const Parser = struct {...@@ -1353,6 +1492,8 @@ const Parser = struct {
1353 }1492 }
1354 }1493 }
13551494
1495 const indent_delta = 4;
1496 var indent: usize = 0;
1356 while (stack.popOrNull()) |state| {1497 while (stack.popOrNull()) |state| {
1357 switch (state) {1498 switch (state) {
1358 RenderState.TopLevelDecl => |decl| {1499 RenderState.TopLevelDecl => |decl| {
...@@ -1378,7 +1519,7 @@ const Parser = struct {...@@ -1378,7 +1519,7 @@ const Parser = struct {
1378 %return stream.print("(");1519 %return stream.print("(");
13791520
1380 %return stack.append(RenderState { .Text = "\n" });1521 %return stack.append(RenderState { .Text = "\n" });
1381 if (fn_proto.fn_def_node == null) {1522 if (fn_proto.body_node == null) {
1382 %return stack.append(RenderState { .Text = ";" });1523 %return stack.append(RenderState { .Text = ";" });
1383 }1524 }
13841525
...@@ -1395,36 +1536,42 @@ const Parser = struct {...@@ -1395,36 +1536,42 @@ const Parser = struct {
1395 },1536 },
1396 AstNode.Id.VarDecl => {1537 AstNode.Id.VarDecl => {
1397 const var_decl = @fieldParentPtr(AstNodeVarDecl, "base", decl);1538 const var_decl = @fieldParentPtr(AstNodeVarDecl, "base", decl);
1398 if (var_decl.visib_token) |visib_token| {1539 %return stack.append(RenderState { .Text = "\n"});
1399 %return stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));1540 %return stack.append(RenderState { .VarDecl = var_decl});
1400 }
1401 if (var_decl.extern_token) |extern_token| {
1402 %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
1403 if (var_decl.lib_name != null) {
1404 @panic("TODO");
1405 }
1406 }
1407 if (var_decl.comptime_token) |comptime_token| {
1408 %return stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
1409 }
1410 %return stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token));
1411 %return stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token));
14121541
1413 %return stack.append(RenderState { .VarDeclAlign = var_decl });
1414 if (var_decl.type_node) |type_node| {
1415 %return stream.print(": ");
1416 %return stack.append(RenderState { .Expression = type_node });
1417 }
1418 },1542 },
1419 else => unreachable,1543 else => unreachable,
1420 }1544 }
1421 },1545 },
14221546
1547 RenderState.VarDecl => |var_decl| {
1548 if (var_decl.visib_token) |visib_token| {
1549 %return stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
1550 }
1551 if (var_decl.extern_token) |extern_token| {
1552 %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
1553 if (var_decl.lib_name != null) {
1554 @panic("TODO");
1555 }
1556 }
1557 if (var_decl.comptime_token) |comptime_token| {
1558 %return stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
1559 }
1560 %return stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token));
1561 %return stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token));
1562
1563 %return stack.append(RenderState { .VarDeclAlign = var_decl });
1564 if (var_decl.type_node) |type_node| {
1565 %return stream.print(": ");
1566 %return stack.append(RenderState { .Expression = type_node });
1567 }
1568 },
1569
1423 RenderState.VarDeclAlign => |var_decl| {1570 RenderState.VarDeclAlign => |var_decl| {
1424 if (var_decl.align_node != null) {1571 if (var_decl.align_node != null) {
1425 @panic("TODO");1572 @panic("TODO");
1426 }1573 }
1427 %return stack.append(RenderState { .Text = ";\n" });1574 %return stack.append(RenderState { .Text = ";" });
1428 if (var_decl.init_node) |init_node| {1575 if (var_decl.init_node) |init_node| {
1429 %return stream.print(" = ");1576 %return stream.print(" = ");
1430 %return stack.append(RenderState { .Expression = init_node });1577 %return stack.append(RenderState { .Expression = init_node });
...@@ -1467,6 +1614,23 @@ const Parser = struct {...@@ -1467,6 +1614,23 @@ const Parser = struct {
1467 %return stack.append(RenderState { .Expression = align_expr});1614 %return stack.append(RenderState { .Expression = align_expr});
1468 }1615 }
1469 },1616 },
1617 AstNode.Id.Block => {
1618 const block = @fieldParentPtr(AstNodeBlock, "base", base);
1619 %return stream.write("{");
1620 %return stack.append(RenderState { .Text = "}"});
1621 %return stack.append(RenderState.PrintIndent);
1622 %return stack.append(RenderState { .Indent = indent});
1623 %return stack.append(RenderState { .Text = "\n"});
1624 var i = block.statements.len;
1625 while (i != 0) {
1626 i -= 1;
1627 const statement_node = block.statements.items[i];
1628 %return stack.append(RenderState { .Statement = statement_node});
1629 %return stack.append(RenderState.PrintIndent);
1630 %return stack.append(RenderState { .Indent = indent + indent_delta});
1631 %return stack.append(RenderState { .Text = "\n" });
1632 }
1633 },
1470 else => unreachable,1634 else => unreachable,
1471 },1635 },
1472 RenderState.AddrOfExprBit => |addr_of_expr| {1636 RenderState.AddrOfExprBit => |addr_of_expr| {
...@@ -1491,9 +1655,24 @@ const Parser = struct {...@@ -1491,9 +1655,24 @@ const Parser = struct {
1491 }1655 }
1492 if (fn_proto.return_type) |return_type| {1656 if (fn_proto.return_type) |return_type| {
1493 %return stream.print(" -> ");1657 %return stream.print(" -> ");
1658 if (fn_proto.body_node) |body_node| {
1659 %return stack.append(RenderState { .Expression = body_node});
1660 %return stack.append(RenderState { .Text = " "});
1661 }
1494 %return stack.append(RenderState { .Expression = return_type});1662 %return stack.append(RenderState { .Expression = return_type});
1495 }1663 }
1496 },1664 },
1665 RenderState.Statement => |base| {
1666 switch (base.id) {
1667 AstNode.Id.VarDecl => {
1668 const var_decl = @fieldParentPtr(AstNodeVarDecl, "base", base);
1669 %return stack.append(RenderState { .VarDecl = var_decl});
1670 },
1671 else => unreachable,
1672 }
1673 },
1674 RenderState.Indent => |new_indent| indent = new_indent,
1675 RenderState.PrintIndent => %return stream.writeByteNTimes(' ', indent),
1497 }1676 }
1498 }1677 }
1499 }1678 }
...@@ -1555,15 +1734,6 @@ pub fn main2() -> %void {...@@ -1555,15 +1734,6 @@ pub fn main2() -> %void {
1555 %return parser.renderSource(out_stream, root_node);1734 %return parser.renderSource(out_stream, root_node);
1556}1735}
15571736
1558fn removeNullCast(x: var) -> {const InnerPtr = @typeOf(x).Child.Child; &InnerPtr} {
1559 comptime assert(@typeId(@typeOf(x)) == builtin.TypeId.Pointer);
1560 comptime assert(@typeId(@typeOf(x).Child) == builtin.TypeId.Nullable);
1561 comptime assert(@typeId(@typeOf(x).Child.Child) == builtin.TypeId.Pointer);
1562 const InnerPtr = @typeOf(x).Child.Child;
1563 return @ptrCast(&InnerPtr, x);
1564}
1565
1566
15671737
1568fn testCanonical(source: []const u8) {1738fn testCanonical(source: []const u8) {
1569 const allocator = std.debug.global_allocator;1739 const allocator = std.debug.global_allocator;
...@@ -1612,4 +1782,11 @@ test "zig fmt" {...@@ -1612,4 +1782,11 @@ test "zig fmt" {
1612 \\extern var foo: c_int;1782 \\extern var foo: c_int;
1613 \\1783 \\
1614 );1784 );
1785
1786 testCanonical(
1787 \\fn main(argc: c_int, argv: &&u8) -> c_int {
1788 \\ const a = b;
1789 \\}
1790 \\
1791 );
1615}1792}
std/io.zig+8
...@@ -481,6 +481,14 @@ pub const OutStream = struct {...@@ -481,6 +481,14 @@ pub const OutStream = struct {
481 const slice = (&byte)[0..1];481 const slice = (&byte)[0..1];
482 return self.writeFn(self, slice);482 return self.writeFn(self, slice);
483 }483 }
484
485 pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) -> %void {
486 const slice = (&byte)[0..1];
487 var i: usize = 0;
488 while (i < n) : (i += 1) {
489 %return self.writeFn(self, slice);
490 }
491 }
484};492};
485493
486/// `path` may need to be copied in memory to add a null terminating byte. In this case494/// `path` may need to be copied in memory to add a null terminating byte. In this case