authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-09 20:01:13-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-09 20:01:13-05:00
loge9efa74333b4890b2598c96dc7df4761965e6819
tree578fe751aa813d41469440bc0a53063a46d61ec6
parentf466e539ef27d1cf90e2b163d5afbcf0bffc0aa5

partial parameter decl parsing


2 files changed, 433 insertions(+), 33 deletions(-)

src-self-hosted/main.zig+432-32
...@@ -86,6 +86,8 @@ const Token = struct {...@@ -86,6 +86,8 @@ const Token = struct {
86 LBrace,86 LBrace,
87 RBrace,87 RBrace,
88 Period,88 Period,
89 Ellipsis2,
90 Ellipsis3,
89 Minus,91 Minus,
90 Arrow,92 Arrow,
91 Colon,93 Colon,
...@@ -200,6 +202,8 @@ const Tokenizer = struct {...@@ -200,6 +202,8 @@ const Tokenizer = struct {
200 FloatExponentUnsigned,202 FloatExponentUnsigned,
201 FloatExponentNumber,203 FloatExponentNumber,
202 Ampersand,204 Ampersand,
205 Period,
206 Period2,
203 };207 };
204208
205 pub fn next(self: &Tokenizer) -> Token {209 pub fn next(self: &Tokenizer) -> Token {
...@@ -278,9 +282,7 @@ const Tokenizer = struct {...@@ -278,9 +282,7 @@ const Tokenizer = struct {
278 break;282 break;
279 },283 },
280 '.' => {284 '.' => {
281 result.id = Token.Id.Period;285 state = State.Period;
282 self.index += 1;
283 break;
284 },286 },
285 '-' => {287 '-' => {
286 state = State.Minus;288 state = State.Minus;
...@@ -370,6 +372,29 @@ const Tokenizer = struct {...@@ -370,6 +372,29 @@ const Tokenizer = struct {
370 break;372 break;
371 },373 },
372 },374 },
375
376 State.Period => switch (c) {
377 '.' => {
378 state = State.Period2;
379 },
380 else => {
381 result.id = Token.Id.Period;
382 break;
383 },
384 },
385
386 State.Period2 => switch (c) {
387 '.' => {
388 result.id = Token.Id.Ellipsis3;
389 self.index += 1;
390 break;
391 },
392 else => {
393 result.id = Token.Id.Ellipsis2;
394 break;
395 },
396 },
397
373 State.Slash => switch (c) {398 State.Slash => switch (c) {
374 '/' => {399 '/' => {
375 result.id = undefined;400 result.id = undefined;
...@@ -451,15 +476,30 @@ const Tokenizer = struct {...@@ -451,15 +476,30 @@ const Tokenizer = struct {
451 }476 }
452};477};
453478
479const Comptime = enum { No, Yes };
480const NoAlias = enum { No, Yes };
481const Extern = enum { No, Yes };
482const VarArgs = enum { No, Yes };
483const Mutability = enum { Const, Var };
484
485const Inline = enum {
486 Auto,
487 Always,
488 Never,
489};
490
454const Visibility = enum {491const Visibility = enum {
455 Private,492 Private,
456 Pub,493 Pub,
457 Export,494 Export,
458};495};
459496
460const Mutability = enum {497const CallingConvention = enum {
461 Const,498 Auto,
462 Var,499 C,
500 Cold,
501 Naked,
502 Stdcall,
463};503};
464504
465const AstNode = struct {505const AstNode = struct {
...@@ -469,6 +509,8 @@ const AstNode = struct {...@@ -469,6 +509,8 @@ const AstNode = struct {
469 Root,509 Root,
470 VarDecl,510 VarDecl,
471 Identifier,511 Identifier,
512 FnProto,
513 ParamDecl,
472 };514 };
473515
474 fn iterate(base: &AstNode, index: usize) -> ?&AstNode {516 fn iterate(base: &AstNode, index: usize) -> ?&AstNode {
...@@ -476,6 +518,8 @@ const AstNode = struct {...@@ -476,6 +518,8 @@ const AstNode = struct {
476 Id.Root => @fieldParentPtr(AstNodeRoot, "base", base).iterate(index),518 Id.Root => @fieldParentPtr(AstNodeRoot, "base", base).iterate(index),
477 Id.VarDecl => @fieldParentPtr(AstNodeVarDecl, "base", base).iterate(index),519 Id.VarDecl => @fieldParentPtr(AstNodeVarDecl, "base", base).iterate(index),
478 Id.Identifier => @fieldParentPtr(AstNodeIdentifier, "base", base).iterate(index),520 Id.Identifier => @fieldParentPtr(AstNodeIdentifier, "base", base).iterate(index),
521 Id.FnProto => @fieldParentPtr(AstNodeFnProto, "base", base).iterate(index),
522 Id.ParamDecl => @fieldParentPtr(AstNodeParamDecl, "base", base).iterate(index),
479 };523 };
480 }524 }
481};525};
...@@ -498,7 +542,9 @@ const AstNodeVarDecl = struct {...@@ -498,7 +542,9 @@ const AstNodeVarDecl = struct {
498 name_token: Token,542 name_token: Token,
499 eq_token: Token,543 eq_token: Token,
500 mut: Mutability,544 mut: Mutability,
501 is_comptime: bool,545 is_comptime: Comptime,
546 is_extern: Extern,
547 lib_name: ?&AstNode,
502 type_node: ?&AstNode,548 type_node: ?&AstNode,
503 align_node: ?&AstNode,549 align_node: ?&AstNode,
504 init_node: ?&AstNode,550 init_node: ?&AstNode,
...@@ -534,12 +580,75 @@ const AstNodeIdentifier = struct {...@@ -534,12 +580,75 @@ const AstNodeIdentifier = struct {
534 }580 }
535};581};
536582
583const AstNodeFnProto = struct {
584 base: AstNode,
585 visib: Visibility,
586 fn_token: Token,
587 name_token: ?Token,
588 params: ArrayList(&AstNode),
589 return_type: ?&AstNode,
590 var_args: VarArgs,
591 is_extern: Extern,
592 is_inline: Inline,
593 cc: CallingConvention,
594 fn_def_node: ?&AstNode,
595 lib_name: ?&AstNode, // populated if this is an extern declaration
596 align_expr: ?&AstNode, // populated if align(A) is present
597
598 fn iterate(self: &AstNodeFnProto, index: usize) -> ?&AstNode {
599 var i = index;
600
601 if (i < self.params.len) return self.params.items[i];
602 i -= self.params.len;
603
604 if (self.return_type) |return_type| {
605 if (i < 1) return return_type;
606 i -= 1;
607 }
608
609 if (self.fn_def_node) |fn_def_node| {
610 if (i < 1) return fn_def_node;
611 i -= 1;
612 }
613
614 if (self.lib_name) |lib_name| {
615 if (i < 1) return lib_name;
616 i -= 1;
617 }
618
619 if (self.align_expr) |align_expr| {
620 if (i < 1) return align_expr;
621 i -= 1;
622 }
623
624 return null;
625 }
626};
627
628const AstNodeParamDecl = struct {
629 base: AstNode,
630 comptime_token: ?Token,
631 noalias_token: ?Token,
632 name_token: ?Token,
633 type_node: &AstNode,
634 var_args_token: ?Token,
635
636 fn iterate(self: &AstNodeParamDecl, index: usize) -> ?&AstNode {
637 var i = index;
638
639 if (i < 1) return self.type_node;
640 i -= 1;
641
642 return null;
643 }
644};
645
537error ParseError;646error ParseError;
538647
539const Parser = struct {648const Parser = struct {
540 tokenizer: &Tokenizer,649 tokenizer: &Tokenizer,
541 allocator: &mem.Allocator,650 allocator: &mem.Allocator,
542 put_back_tokens: [1]Token,651 put_back_tokens: [2]Token,
543 put_back_count: usize,652 put_back_count: usize,
544 source_file_name: []const u8,653 source_file_name: []const u8,
545654
...@@ -556,14 +665,32 @@ const Parser = struct {...@@ -556,14 +665,32 @@ const Parser = struct {
556 const State = union(enum) {665 const State = union(enum) {
557 TopLevel, 666 TopLevel,
558 TopLevelModifier: Visibility, 667 TopLevelModifier: Visibility,
559 Expression: &?&AstNode,668 TopLevelExtern: Visibility,
560 GroupedExpression: &?&AstNode,669 Expression: &&AstNode,
561 PrimaryExpression: &?&AstNode,670 GroupedExpression: &&AstNode,
562 TypeExpr: &?&AstNode,671 UnwrapExpression: &&AstNode,
672 BoolOrExpression: &&AstNode,
673 BoolAndExpression: &&AstNode,
674 ComparisonExpression: &&AstNode,
675 BinaryOrExpression: &&AstNode,
676 BinaryXorExpression: &&AstNode,
677 BinaryAndExpression: &&AstNode,
678 BitShiftExpression: &&AstNode,
679 AdditionExpression: &&AstNode,
680 MultiplyExpression: &&AstNode,
681 BraceSuffixExpression: &&AstNode,
682 PrefixOpExpression: &&AstNode,
683 SuffixOpExpression: &&AstNode,
684 PrimaryExpression: &&AstNode,
685 TypeExpr: &&AstNode,
563 VarDecl: &AstNodeVarDecl,686 VarDecl: &AstNodeVarDecl,
564 VarDeclAlign: &AstNodeVarDecl,687 VarDeclAlign: &AstNodeVarDecl,
565 VarDeclEq: &AstNodeVarDecl,688 VarDeclEq: &AstNodeVarDecl,
566 ExpectSemicolon,689 ExpectToken: @TagType(Token.Id),
690 FnProto: &AstNodeFnProto,
691 FnProtoAlign: &AstNodeFnProto,
692 ParamDecl: &AstNodeFnProto,
693 ParamDeclComma,
567 };694 };
568695
569 pub fn parse(self: &Parser) -> %&AstNode {696 pub fn parse(self: &Parser) -> %&AstNode {
...@@ -593,19 +720,31 @@ const Parser = struct {...@@ -593,19 +720,31 @@ const Parser = struct {
593 },720 },
594 Token.Id.Keyword_const => {721 Token.Id.Keyword_const => {
595 stack.append(State.TopLevel) %% unreachable;722 stack.append(State.TopLevel) %% unreachable;
596 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Const, false);723 const var_decl_node = {
597 %return root_node.decls.append(&var_decl_node.base);724 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Const, Comptime.No, Extern.No);
725 %defer self.allocator.destroy(var_decl_node);
726 %return root_node.decls.append(&var_decl_node.base);
727 var_decl_node
728 };
598 %return stack.append(State { .VarDecl = var_decl_node });729 %return stack.append(State { .VarDecl = var_decl_node });
599 continue;730 continue;
600 },731 },
601 Token.Id.Keyword_var => {732 Token.Id.Keyword_var => {
602 stack.append(State.TopLevel) %% unreachable;733 stack.append(State.TopLevel) %% unreachable;
603 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Var, false);734 const var_decl_node = {
604 %return root_node.decls.append(&var_decl_node.base);735 const var_decl_node = %return self.createVarDecl(Visibility.Private, Mutability.Var, Comptime.No, Extern.No);
736 %defer self.allocator.destroy(var_decl_node);
737 %return root_node.decls.append(&var_decl_node.base);
738 var_decl_node
739 };
605 %return stack.append(State { .VarDecl = var_decl_node });740 %return stack.append(State { .VarDecl = var_decl_node });
606 continue;741 continue;
607 },742 },
608 Token.Id.Eof => return &root_node.base,743 Token.Id.Eof => return &root_node.base,
744 Token.Id.Keyword_extern => {
745 stack.append(State { .TopLevelExtern = Visibility.Private }) %% unreachable;
746 continue;
747 },
609 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),748 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
610 }749 }
611 },750 },
...@@ -614,28 +753,81 @@ const Parser = struct {...@@ -614,28 +753,81 @@ const Parser = struct {
614 switch (token.id) {753 switch (token.id) {
615 Token.Id.Keyword_const => {754 Token.Id.Keyword_const => {
616 stack.append(State.TopLevel) %% unreachable;755 stack.append(State.TopLevel) %% unreachable;
617 const var_decl_node = %return self.createVarDecl(visib, Mutability.Const, false);756 const var_decl_node = {
618 %return root_node.decls.append(&var_decl_node.base);757 const var_decl_node = %return self.createVarDecl(visib, Mutability.Const, Comptime.No, Extern.No);
758 %defer self.allocator.destroy(var_decl_node);
759 %return root_node.decls.append(&var_decl_node.base);
760 var_decl_node
761 };
619 %return stack.append(State { .VarDecl = var_decl_node });762 %return stack.append(State { .VarDecl = var_decl_node });
620 continue;763 continue;
621 },764 },
622 Token.Id.Keyword_var => {765 Token.Id.Keyword_var => {
623 stack.append(State.TopLevel) %% unreachable;766 stack.append(State.TopLevel) %% unreachable;
624 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, false);767 const var_decl_node = {
625 %return root_node.decls.append(&var_decl_node.base);768 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, Comptime.No, Extern.No);
769 %defer self.allocator.destroy(var_decl_node);
770 %return root_node.decls.append(&var_decl_node.base);
771 var_decl_node
772 };
626 %return stack.append(State { .VarDecl = var_decl_node });773 %return stack.append(State { .VarDecl = var_decl_node });
627 continue;774 continue;
628 },775 },
776 Token.Id.Keyword_extern => {
777 stack.append(State { .TopLevelExtern = visib }) %% unreachable;
778 continue;
779 },
629 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),780 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
630 }781 }
631 },782 },
783 State.TopLevelExtern => |visib| {
784 const token = self.getNextToken();
785 switch (token.id) {
786 Token.Id.Keyword_var => {
787 stack.append(State.TopLevel) %% unreachable;
788 const var_decl_node = {
789 const var_decl_node = %return self.createVarDecl(visib, Mutability.Var, Comptime.No, Extern.Yes);
790 %defer self.allocator.destroy(var_decl_node);
791 %return root_node.decls.append(&var_decl_node.base);
792 var_decl_node
793 };
794 %return stack.append(State { .VarDecl = var_decl_node });
795 continue;
796 },
797 Token.Id.Keyword_fn => {
798 stack.append(State.TopLevel) %% unreachable;
799 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,
800 Extern.Yes, CallingConvention.Auto, visib, Inline.Auto);
801 %return stack.append(State { .FnProto = fn_proto_node });
802 continue;
803 },
804 Token.Id.StringLiteral => {
805 @panic("TODO extern with string literal");
806 },
807 Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
808 stack.append(State.TopLevel) %% unreachable;
809 const cc = switch (token.id) {
810 Token.Id.Keyword_coldcc => CallingConvention.Cold,
811 Token.Id.Keyword_nakedcc => CallingConvention.Naked,
812 Token.Id.Keyword_stdcallcc => CallingConvention.Stdcall,
813 else => unreachable,
814 };
815 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);
816 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,
817 Extern.Yes, cc, visib, Inline.Auto);
818 %return stack.append(State { .FnProto = fn_proto_node });
819 continue;
820 },
821 else => return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id)),
822 }
823 },
632 State.VarDecl => |var_decl| {824 State.VarDecl => |var_decl| {
633 var_decl.name_token = %return self.eatToken(Token.Id.Identifier);825 var_decl.name_token = %return self.eatToken(Token.Id.Identifier);
634 stack.append(State { .VarDeclAlign = var_decl }) %% unreachable;826 stack.append(State { .VarDeclAlign = var_decl }) %% unreachable;
635827
636 const next_token = self.getNextToken();828 const next_token = self.getNextToken();
637 if (next_token.id == Token.Id.Colon) {829 if (next_token.id == Token.Id.Colon) {
638 %return stack.append(State { .TypeExpr = &var_decl.type_node });830 %return stack.append(State { .TypeExpr = removeNullCast(&var_decl.type_node) });
639 continue;831 continue;
640 }832 }
641833
...@@ -647,7 +839,7 @@ const Parser = struct {...@@ -647,7 +839,7 @@ const Parser = struct {
647839
648 const next_token = self.getNextToken();840 const next_token = self.getNextToken();
649 if (next_token.id == Token.Id.Keyword_align) {841 if (next_token.id == Token.Id.Keyword_align) {
650 %return stack.append(State { .GroupedExpression = &var_decl.align_node });842 %return stack.append(State { .GroupedExpression = removeNullCast(&var_decl.align_node) });
651 continue;843 continue;
652 }844 }
653845
...@@ -656,21 +848,86 @@ const Parser = struct {...@@ -656,21 +848,86 @@ const Parser = struct {
656 },848 },
657 State.VarDeclEq => |var_decl| {849 State.VarDeclEq => |var_decl| {
658 var_decl.eq_token = %return self.eatToken(Token.Id.Equal);850 var_decl.eq_token = %return self.eatToken(Token.Id.Equal);
659 stack.append(State.ExpectSemicolon) %% unreachable;851 stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;
660 %return stack.append(State {852 %return stack.append(State {
661 .Expression = &var_decl.init_node,853 .Expression = removeNullCast(&var_decl.init_node),
662 });854 });
663 continue;855 continue;
664 },856 },
665 State.ExpectSemicolon => {857 State.ExpectToken => |token_id| {
666 _ = %return self.eatToken(Token.Id.Semicolon);858 _ = %return self.eatToken(token_id);
667 continue;859 continue;
668 },860 },
669 State.Expression => |result_ptr| {861 State.Expression => |result_ptr| {
670 // TODO this should not jump straight to primary expression862 stack.append(State {.UnwrapExpression = result_ptr}) %% unreachable;
671 stack.append(State {.PrimaryExpression = result_ptr}) %% unreachable;863 continue;
864 },
865
866 State.UnwrapExpression => |result_ptr| {
867 stack.append(State {.BoolOrExpression = result_ptr}) %% unreachable;
868 continue;
869 },
870
871 State.BoolOrExpression => |result_ptr| {
872 stack.append(State {.BoolAndExpression = result_ptr}) %% unreachable;
873 continue;
874 },
875
876 State.BoolAndExpression => |result_ptr| {
877 stack.append(State {.ComparisonExpression = result_ptr}) %% unreachable;
878 continue;
879 },
880
881 State.ComparisonExpression => |result_ptr| {
882 stack.append(State {.BinaryOrExpression = result_ptr}) %% unreachable;
883 continue;
884 },
885
886 State.BinaryOrExpression => |result_ptr| {
887 stack.append(State {.BinaryXorExpression = result_ptr}) %% unreachable;
888 continue;
889 },
890
891 State.BinaryXorExpression => |result_ptr| {
892 stack.append(State {.BinaryAndExpression = result_ptr}) %% unreachable;
893 continue;
894 },
895
896 State.BinaryAndExpression => |result_ptr| {
897 stack.append(State {.BitShiftExpression = result_ptr}) %% unreachable;
898 continue;
899 },
900
901 State.BitShiftExpression => |result_ptr| {
902 stack.append(State {.AdditionExpression = result_ptr}) %% unreachable;
903 continue;
904 },
905
906 State.AdditionExpression => |result_ptr| {
907 stack.append(State {.AdditionExpression = result_ptr}) %% unreachable;
908 continue;
909 },
910
911 State.MultiplyExpression => |result_ptr| {
912 stack.append(State {.BraceSuffixExpression = result_ptr}) %% unreachable;
913 continue;
914 },
915
916 State.BraceSuffixExpression => |result_ptr| {
917 stack.append(State {.PrefixOpExpression = result_ptr}) %% unreachable;
918 continue;
919 },
920
921 State.PrefixOpExpression => |result_ptr| {
922 stack.append(State { .SuffixOpExpression = result_ptr }) %% unreachable;
923 continue;
924 },
925
926 State.SuffixOpExpression => |result_ptr| {
927 stack.append(State { .PrimaryExpression = result_ptr }) %% unreachable;
672 continue;928 continue;
673 },929 },
930
674 State.PrimaryExpression => |result_ptr| {931 State.PrimaryExpression => |result_ptr| {
675 const token = self.getNextToken();932 const token = self.getNextToken();
676 switch (token.id) {933 switch (token.id) {
...@@ -682,7 +939,84 @@ const Parser = struct {...@@ -682,7 +939,84 @@ const Parser = struct {
682 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),939 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),
683 }940 }
684 },941 },
685 State.TypeExpr => @panic("TODO"),942
943 State.TypeExpr => |result_ptr| {
944 const token = self.getNextToken();
945 if (token.id == Token.Id.Keyword_var) {
946 @panic("TODO param with type var");
947 }
948 self.putBackToken(token);
949
950 stack.append(State { .PrefixOpExpression = result_ptr }) %% unreachable;
951 continue;
952 },
953
954 State.FnProto => |fn_proto| {
955 stack.append(State { .FnProtoAlign = fn_proto }) %% unreachable;
956 %return stack.append(State { .ParamDecl = fn_proto });
957 %return stack.append(State { .ExpectToken = Token.Id.LParen });
958
959 const next_token = self.getNextToken();
960 if (next_token.id == Token.Id.Identifier) {
961 fn_proto.name_token = next_token;
962 continue;
963 }
964 self.putBackToken(next_token);
965 continue;
966 },
967
968 State.FnProtoAlign => |fn_proto| {
969 @panic("TODO fn proto align");
970 //continue;
971 },
972
973 State.ParamDecl => |fn_proto| {
974 var token = self.getNextToken();
975 if (token.id == Token.Id.RParen) {
976 continue;
977 }
978 const param_decl = %return self.createAttachParamDecl(&fn_proto.params);
979 if (token.id == Token.Id.Keyword_comptime) {
980 param_decl.comptime_token = token;
981 token = self.getNextToken();
982 } else if (token.id == Token.Id.Keyword_noalias) {
983 param_decl.noalias_token = token;
984 token = self.getNextToken();
985 };
986 if (token.id == Token.Id.Identifier) {
987 const next_token = self.getNextToken();
988 if (next_token.id == Token.Id.Colon) {
989 param_decl.name_token = token;
990 token = self.getNextToken();
991 } else {
992 self.putBackToken(next_token);
993 }
994 }
995 if (token.id == Token.Id.Ellipsis3) {
996 param_decl.var_args_token = token;
997 } else {
998 self.putBackToken(token);
999 }
1000
1001 stack.append(State { .ParamDecl = fn_proto }) %% unreachable;
1002 %return stack.append(State.ParamDeclComma);
1003 %return stack.append(State { .TypeExpr = &param_decl.type_node });
1004 continue;
1005 },
1006
1007 State.ParamDeclComma => {
1008 const token = self.getNextToken();
1009 switch (token.id) {
1010 Token.Id.RParen => {
1011 _ = stack.pop(); // pop off the ParamDecl
1012 continue;
1013 },
1014 Token.Id.Comma => continue,
1015 else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)),
1016 }
1017 },
1018
1019
686 State.GroupedExpression => @panic("TODO"),1020 State.GroupedExpression => @panic("TODO"),
687 }1021 }
688 unreachable;1022 unreachable;
...@@ -700,7 +1034,9 @@ const Parser = struct {...@@ -700,7 +1034,9 @@ const Parser = struct {
700 return node;1034 return node;
701 }1035 }
7021036
703 fn createVarDecl(self: &Parser, visib: Visibility, mut: Mutability, is_comptime: bool) -> %&AstNodeVarDecl {1037 fn createVarDecl(self: &Parser, visib: Visibility, mut: Mutability, is_comptime: Comptime,
1038 is_extern: Extern) -> %&AstNodeVarDecl
1039 {
704 const node = %return self.allocator.create(AstNodeVarDecl);1040 const node = %return self.allocator.create(AstNodeVarDecl);
705 %defer self.allocator.destroy(node);1041 %defer self.allocator.destroy(node);
7061042
...@@ -709,9 +1045,11 @@ const Parser = struct {...@@ -709,9 +1045,11 @@ const Parser = struct {
709 .visib = visib,1045 .visib = visib,
710 .mut = mut,1046 .mut = mut,
711 .is_comptime = is_comptime,1047 .is_comptime = is_comptime,
1048 .is_extern = is_extern,
712 .type_node = null,1049 .type_node = null,
713 .align_node = null,1050 .align_node = null,
714 .init_node = null,1051 .init_node = null,
1052 .lib_name = null,
715 // initialized later1053 // initialized later
716 .name_token = undefined,1054 .name_token = undefined,
717 .eq_token = undefined,1055 .eq_token = undefined,
...@@ -730,6 +1068,61 @@ const Parser = struct {...@@ -730,6 +1068,61 @@ const Parser = struct {
730 return node;1068 return node;
731 }1069 }
7321070
1071 fn createFnProto(self: &Parser, fn_token: &const Token, is_extern: Extern,
1072 cc: CallingConvention, visib: Visibility, is_inline: Inline) -> %&AstNodeFnProto
1073 {
1074 const node = %return self.allocator.create(AstNodeFnProto);
1075 %defer self.allocator.destroy(node);
1076
1077 *node = AstNodeFnProto {
1078 .base = AstNode {.id = AstNode.Id.FnProto},
1079 .visib = visib,
1080 .name_token = null,
1081 .fn_token = *fn_token,
1082 .params = ArrayList(&AstNode).init(self.allocator),
1083 .return_type = null,
1084 .var_args = VarArgs.No,
1085 .is_extern = is_extern,
1086 .is_inline = is_inline,
1087 .cc = cc,
1088 .fn_def_node = null,
1089 .lib_name = null,
1090 .align_expr = null,
1091 };
1092 return node;
1093 }
1094
1095 fn createParamDecl(self: &Parser) -> %&AstNodeParamDecl {
1096 const node = %return self.allocator.create(AstNodeParamDecl);
1097 %defer self.allocator.destroy(node);
1098
1099 *node = AstNodeParamDecl {
1100 .base = AstNode {.id = AstNode.Id.ParamDecl},
1101 .comptime_token = null,
1102 .noalias_token = null,
1103 .name_token = null,
1104 .type_node = undefined,
1105 .var_args_token = null,
1106 };
1107 return node;
1108 }
1109
1110 fn createAttachParamDecl(self: &Parser, list: &ArrayList(&AstNode)) -> %&AstNodeParamDecl {
1111 const node = %return self.createParamDecl();
1112 %defer self.allocator.destroy(node);
1113 %return list.append(&node.base);
1114 return node;
1115 }
1116
1117 fn createAttachFnProto(self: &Parser, list: &ArrayList(&AstNode), fn_token: &const Token,
1118 is_extern: Extern, cc: CallingConvention, visib: Visibility, is_inline: Inline) -> %&AstNodeFnProto
1119 {
1120 const node = %return self.createFnProto(fn_token, is_extern, cc, visib, is_inline);
1121 %defer self.allocator.destroy(node);
1122 %return list.append(&node.base);
1123 return node;
1124 }
1125
733 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) -> error {1126 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) -> error {
734 const loc = self.tokenizer.getTokenLocation(token);1127 const loc = self.tokenizer.getTokenLocation(token);
735 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);1128 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
...@@ -778,7 +1171,6 @@ const Parser = struct {...@@ -778,7 +1171,6 @@ const Parser = struct {
778 self.tokenizer.next()1171 self.tokenizer.next()
779 };1172 };
780 }1173 }
781
782};1174};
7831175
7841176
...@@ -841,3 +1233,11 @@ fn render(node: &AstNode, indent: usize) {...@@ -841,3 +1233,11 @@ fn render(node: &AstNode, indent: usize) {
841 render(child, indent + 2);1233 render(child, indent + 2);
842 }1234 }
843}1235}
1236
1237fn removeNullCast(x: var) -> {const InnerPtr = @typeOf(x).Child.Child; &InnerPtr} {
1238 comptime assert(@typeId(@typeOf(x)) == builtin.TypeId.Pointer);
1239 comptime assert(@typeId(@typeOf(x).Child) == builtin.TypeId.Nullable);
1240 comptime assert(@typeId(@typeOf(x).Child.Child) == builtin.TypeId.Pointer);
1241 const InnerPtr = @typeOf(x).Child.Child;
1242 return @ptrCast(&InnerPtr, x);
1243}
src/analyze.cpp+1-1
...@@ -2227,7 +2227,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {...@@ -2227,7 +2227,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
22272227
2228 tag_type = new_type_table_entry(TypeTableEntryIdEnum);2228 tag_type = new_type_table_entry(TypeTableEntryIdEnum);
2229 buf_resize(&tag_type->name, 0);2229 buf_resize(&tag_type->name, 0);
2230 buf_appendf(&tag_type->name, "@EnumTagType(%s)", buf_ptr(&union_type->name));2230 buf_appendf(&tag_type->name, "@TagType(%s)", buf_ptr(&union_type->name));
2231 tag_type->is_copyable = true;2231 tag_type->is_copyable = true;
2232 tag_type->type_ref = tag_int_type->type_ref;2232 tag_type->type_ref = tag_int_type->type_ref;
2233 tag_type->zero_bits = tag_int_type->zero_bits;2233 tag_type->zero_bits = tag_int_type->zero_bits;