| ... | @@ -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 | }; |
| 524 | | 525 | |
| 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 | } |
| 535 | | 537 | |
| ... | @@ -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 { |
| 551 | | 554 | |
| 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 declaration | 619 | lib_name: ?&AstNode, // populated if this is an extern declaration |
| 617 | align_expr: ?&AstNode, // populated if align(A) is present | 620 | align_expr: ?&AstNode, // populated if align(A) is present |
| 618 | | 621 | |
| 619 | fn iterate(self: &AstNodeFnProto, index: usize) -> ?&AstNode { | 622 | fn iterate(self: &AstNodeFnProto, index: usize) -> ?&AstNode { |
| 620 | var i = index; | 623 | var i = index; |
| 621 | | 624 | |
| 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 | } |
| 624 | | 629 | |
| 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 | } |
| 629 | | 634 | |
| 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 | } |
| 634 | | 639 | |
| | 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 | } |
| 639 | | 647 | |
| 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 | }; |
| 691 | | 694 | |
| | 695 | const 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 | |
| 692 | error ParseError; | 711 | error ParseError; |
| 693 | | 712 | |
| 694 | const Parser = struct { | 713 | const 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 | }; |
| 736 | | 755 | |
| | 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 | }; |
| 767 | | 803 | |
| 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); |
| 798 | | 834 | |
| 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 fail | 848 | // This gives us 1 free append that can't fail |
| 801 | const state = stack.pop(); | 849 | const state = stack.pop(); |
| 802 | | 850 | |
| ... | @@ -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 casts | 901 | // 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 cast | 914 | // 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 { |
| 879 | | 927 | |
| 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 | } |
| 885 | | 933 | |
| ... | @@ -891,7 +939,11 @@ const Parser = struct { | ... | @@ -891,7 +939,11 @@ const Parser = struct { |
| 891 | | 939 | |
| 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 | } |
| 897 | | 949 | |
| ... | @@ -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 | }, |
| 924 | | 976 | |
| 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 | }, |
| 929 | | 981 | |
| 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 | }, |
| 934 | | 986 | |
| 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 | }, |
| 939 | | 991 | |
| 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 | }, |
| 944 | | 996 | |
| 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 | }, |
| 949 | | 1001 | |
| 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 | }, |
| 954 | | 1006 | |
| 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 | }, |
| 959 | | 1011 | |
| 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 | }, |
| 964 | | 1016 | |
| 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 | }, |
| 969 | | 1021 | |
| 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 | }, |
| 974 | | 1026 | |
| 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 | }, |
| 979 | | 1031 | |
| 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 | } |
| 1000 | | 1054 | |
| 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 | }, |
| 1005 | | 1059 | |
| 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 | }, |
| 1010 | | 1064 | |
| 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 | }, |
| 1022 | | 1076 | |
| 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); |
| 1029 | | 1083 | |
| 1030 | stack.append(State { .PrefixOpExpression = result_ptr }) %% unreachable; | 1084 | stack.append(State { .PrefixOpExpression = dest_ptr }) %% unreachable; |
| 1031 | continue; | 1085 | continue; |
| 1032 | }, | 1086 | }, |
| 1033 | | 1087 | |
| ... | @@ -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 { |
| 1091 | | 1147 | |
| 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 | }, |
| 1097 | | 1155 | |
| ... | @@ -1107,6 +1165,70 @@ const Parser = struct { | ... | @@ -1107,6 +1165,70 @@ const Parser = struct { |
| 1107 | } | 1165 | } |
| 1108 | }, | 1166 | }, |
| 1109 | | 1167 | |
| | 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 | }, |
| 1110 | | 1232 | |
| 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 | } |
| 1217 | | 1339 | |
| 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 | } |
| 1224 | | 1359 | |
| ... | @@ -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 | }; |
| 1342 | | 1481 | |
| 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 | } |
| 1355 | | 1494 | |
| | 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("("); |
| 1379 | | 1520 | |
| 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 | } |
| 1384 | | 1525 | |
| ... | @@ -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)); | | |
| 1412 | | 1541 | |
| 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 | }, |
| 1422 | | 1546 | |
| | 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 | } |
| 1557 | | 1736 | |
| 1558 | fn 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 | | | |
| 1567 | | 1737 | |
| 1568 | fn testCanonical(source: []const u8) { | 1738 | fn 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 | } |