| author | |
| committer | |
| log | b1d8a0a5a6680383bad09b904dba231204a430bd |
| tree | 8d65ad20ecdc5550380f786f58a9891fb6c4fdba |
| parent | d869133a9fb96fb27a07c1e42c12c5270eae5940 |
4 files changed, 403 insertions(+), 260 deletions(-)
lib/std/zig/ast.zig+173-67| ... | ... | @@ -419,13 +419,16 @@ pub const Tree = struct { |
| 419 | 419 | n = extra.start; |
| 420 | 420 | }, |
| 421 | 421 | |
| 422 | .AsmOutput, .AsmInput => { | |
| 423 | assert(token_tags[main_tokens[n] - 1] == .LBracket); | |
| 424 | return main_tokens[n] - 1; | |
| 425 | }, | |
| 426 | ||
| 422 | 427 | .WhileSimple => unreachable, // TODO |
| 423 | 428 | .WhileCont => unreachable, // TODO |
| 424 | 429 | .While => unreachable, // TODO |
| 425 | 430 | .ForSimple => unreachable, // TODO |
| 426 | 431 | .For => unreachable, // TODO |
| 427 | .AsmOutput => unreachable, // TODO | |
| 428 | .AsmInput => unreachable, // TODO | |
| 429 | 432 | .ErrorValue => unreachable, // TODO |
| 430 | 433 | }; |
| 431 | 434 | } |
| ... | ... | @@ -515,6 +518,9 @@ pub const Tree = struct { |
| 515 | 518 | .GroupedExpression, |
| 516 | 519 | .StringLiteral, |
| 517 | 520 | .ErrorSetDecl, |
| 521 | .AsmSimple, | |
| 522 | .AsmOutput, | |
| 523 | .AsmInput, | |
| 518 | 524 | => return datas[n].rhs + end_offset, |
| 519 | 525 | |
| 520 | 526 | .AnyType, |
| ... | ... | @@ -566,6 +572,10 @@ pub const Tree = struct { |
| 566 | 572 | n = tree.extra_data[members.end - 1]; // last parameter |
| 567 | 573 | } |
| 568 | 574 | }, |
| 575 | .Asm => { | |
| 576 | const extra = tree.extraData(datas[n].rhs, Node.Asm); | |
| 577 | return extra.rparen + end_offset; | |
| 578 | }, | |
| 569 | 579 | .ContainerDeclArgComma, |
| 570 | 580 | .SwitchComma, |
| 571 | 581 | => { |
| ... | ... | @@ -765,8 +775,6 @@ pub const Tree = struct { |
| 765 | 775 | .TaggedUnionEnumTagComma => unreachable, // TODO |
| 766 | 776 | .If => unreachable, // TODO |
| 767 | 777 | .Continue => unreachable, // TODO |
| 768 | .AsmSimple => unreachable, // TODO | |
| 769 | .Asm => unreachable, // TODO | |
| 770 | 778 | .SwitchRange => unreachable, // TODO |
| 771 | 779 | .ArrayType => unreachable, // TODO |
| 772 | 780 | .ArrayTypeSentinel => unreachable, // TODO |
| ... | ... | @@ -778,8 +786,6 @@ pub const Tree = struct { |
| 778 | 786 | .FnProtoMulti => unreachable, // TODO |
| 779 | 787 | .FnProtoOne => unreachable, // TODO |
| 780 | 788 | .FnProto => unreachable, // TODO |
| 781 | .AsmOutput => unreachable, // TODO | |
| 782 | .AsmInput => unreachable, // TODO | |
| 783 | 789 | .ErrorValue => unreachable, // TODO |
| 784 | 790 | }; |
| 785 | 791 | } |
| ... | ... | @@ -790,7 +796,7 @@ pub const Tree = struct { |
| 790 | 796 | return mem.indexOfScalar(u8, source, '\n') == null; |
| 791 | 797 | } |
| 792 | 798 | |
| 793 | pub fn globalVarDecl(tree: Tree, node: Node.Index) Full.VarDecl { | |
| 799 | pub fn globalVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | |
| 794 | 800 | assert(tree.nodes.items(.tag)[node] == .GlobalVarDecl); |
| 795 | 801 | const data = tree.nodes.items(.data)[node]; |
| 796 | 802 | const extra = tree.extraData(data.lhs, Node.GlobalVarDecl); |
| ... | ... | @@ -803,7 +809,7 @@ pub const Tree = struct { |
| 803 | 809 | }); |
| 804 | 810 | } |
| 805 | 811 | |
| 806 | pub fn localVarDecl(tree: Tree, node: Node.Index) Full.VarDecl { | |
| 812 | pub fn localVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | |
| 807 | 813 | assert(tree.nodes.items(.tag)[node] == .LocalVarDecl); |
| 808 | 814 | const data = tree.nodes.items(.data)[node]; |
| 809 | 815 | const extra = tree.extraData(data.lhs, Node.LocalVarDecl); |
| ... | ... | @@ -816,7 +822,7 @@ pub const Tree = struct { |
| 816 | 822 | }); |
| 817 | 823 | } |
| 818 | 824 | |
| 819 | pub fn simpleVarDecl(tree: Tree, node: Node.Index) Full.VarDecl { | |
| 825 | pub fn simpleVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | |
| 820 | 826 | assert(tree.nodes.items(.tag)[node] == .SimpleVarDecl); |
| 821 | 827 | const data = tree.nodes.items(.data)[node]; |
| 822 | 828 | return tree.fullVarDecl(.{ |
| ... | ... | @@ -828,7 +834,7 @@ pub const Tree = struct { |
| 828 | 834 | }); |
| 829 | 835 | } |
| 830 | 836 | |
| 831 | pub fn alignedVarDecl(tree: Tree, node: Node.Index) Full.VarDecl { | |
| 837 | pub fn alignedVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | |
| 832 | 838 | assert(tree.nodes.items(.tag)[node] == .AlignedVarDecl); |
| 833 | 839 | const data = tree.nodes.items(.data)[node]; |
| 834 | 840 | return tree.fullVarDecl(.{ |
| ... | ... | @@ -840,7 +846,7 @@ pub const Tree = struct { |
| 840 | 846 | }); |
| 841 | 847 | } |
| 842 | 848 | |
| 843 | pub fn ifSimple(tree: Tree, node: Node.Index) Full.If { | |
| 849 | pub fn ifSimple(tree: Tree, node: Node.Index) full.If { | |
| 844 | 850 | assert(tree.nodes.items(.tag)[node] == .IfSimple); |
| 845 | 851 | const data = tree.nodes.items(.data)[node]; |
| 846 | 852 | return tree.fullIf(.{ |
| ... | ... | @@ -851,7 +857,7 @@ pub const Tree = struct { |
| 851 | 857 | }); |
| 852 | 858 | } |
| 853 | 859 | |
| 854 | pub fn ifFull(tree: Tree, node: Node.Index) Full.If { | |
| 860 | pub fn ifFull(tree: Tree, node: Node.Index) full.If { | |
| 855 | 861 | assert(tree.nodes.items(.tag)[node] == .If); |
| 856 | 862 | const data = tree.nodes.items(.data)[node]; |
| 857 | 863 | const extra = tree.extraData(data.rhs, Node.If); |
| ... | ... | @@ -863,7 +869,7 @@ pub const Tree = struct { |
| 863 | 869 | }); |
| 864 | 870 | } |
| 865 | 871 | |
| 866 | pub fn containerField(tree: Tree, node: Node.Index) Full.ContainerField { | |
| 872 | pub fn containerField(tree: Tree, node: Node.Index) full.ContainerField { | |
| 867 | 873 | assert(tree.nodes.items(.tag)[node] == .ContainerField); |
| 868 | 874 | const data = tree.nodes.items(.data)[node]; |
| 869 | 875 | const extra = tree.extraData(data.rhs, Node.ContainerField); |
| ... | ... | @@ -875,7 +881,7 @@ pub const Tree = struct { |
| 875 | 881 | }); |
| 876 | 882 | } |
| 877 | 883 | |
| 878 | pub fn containerFieldInit(tree: Tree, node: Node.Index) Full.ContainerField { | |
| 884 | pub fn containerFieldInit(tree: Tree, node: Node.Index) full.ContainerField { | |
| 879 | 885 | assert(tree.nodes.items(.tag)[node] == .ContainerFieldInit); |
| 880 | 886 | const data = tree.nodes.items(.data)[node]; |
| 881 | 887 | return tree.fullContainerField(.{ |
| ... | ... | @@ -886,7 +892,7 @@ pub const Tree = struct { |
| 886 | 892 | }); |
| 887 | 893 | } |
| 888 | 894 | |
| 889 | pub fn containerFieldAlign(tree: Tree, node: Node.Index) Full.ContainerField { | |
| 895 | pub fn containerFieldAlign(tree: Tree, node: Node.Index) full.ContainerField { | |
| 890 | 896 | assert(tree.nodes.items(.tag)[node] == .ContainerFieldAlign); |
| 891 | 897 | const data = tree.nodes.items(.data)[node]; |
| 892 | 898 | return tree.fullContainerField(.{ |
| ... | ... | @@ -897,7 +903,7 @@ pub const Tree = struct { |
| 897 | 903 | }); |
| 898 | 904 | } |
| 899 | 905 | |
| 900 | pub fn fnProtoSimple(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) Full.FnProto { | |
| 906 | pub fn fnProtoSimple(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.FnProto { | |
| 901 | 907 | assert(tree.nodes.items(.tag)[node] == .FnProtoSimple); |
| 902 | 908 | const data = tree.nodes.items(.data)[node]; |
| 903 | 909 | buffer[0] = data.lhs; |
| ... | ... | @@ -912,7 +918,7 @@ pub const Tree = struct { |
| 912 | 918 | }); |
| 913 | 919 | } |
| 914 | 920 | |
| 915 | pub fn fnProtoMulti(tree: Tree, node: Node.Index) Full.FnProto { | |
| 921 | pub fn fnProtoMulti(tree: Tree, node: Node.Index) full.FnProto { | |
| 916 | 922 | assert(tree.nodes.items(.tag)[node] == .FnProtoMulti); |
| 917 | 923 | const data = tree.nodes.items(.data)[node]; |
| 918 | 924 | const params_range = tree.extraData(data.lhs, Node.SubRange); |
| ... | ... | @@ -927,7 +933,7 @@ pub const Tree = struct { |
| 927 | 933 | }); |
| 928 | 934 | } |
| 929 | 935 | |
| 930 | pub fn fnProtoOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) Full.FnProto { | |
| 936 | pub fn fnProtoOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.FnProto { | |
| 931 | 937 | assert(tree.nodes.items(.tag)[node] == .FnProtoOne); |
| 932 | 938 | const data = tree.nodes.items(.data)[node]; |
| 933 | 939 | const extra = tree.extraData(data.lhs, Node.FnProtoOne); |
| ... | ... | @@ -943,7 +949,7 @@ pub const Tree = struct { |
| 943 | 949 | }); |
| 944 | 950 | } |
| 945 | 951 | |
| 946 | pub fn fnProto(tree: Tree, node: Node.Index) Full.FnProto { | |
| 952 | pub fn fnProto(tree: Tree, node: Node.Index) full.FnProto { | |
| 947 | 953 | assert(tree.nodes.items(.tag)[node] == .FnProto); |
| 948 | 954 | const data = tree.nodes.items(.data)[node]; |
| 949 | 955 | const extra = tree.extraData(data.lhs, Node.FnProto); |
| ... | ... | @@ -958,7 +964,7 @@ pub const Tree = struct { |
| 958 | 964 | }); |
| 959 | 965 | } |
| 960 | 966 | |
| 961 | pub fn structInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) Full.StructInit { | |
| 967 | pub fn structInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.StructInit { | |
| 962 | 968 | assert(tree.nodes.items(.tag)[node] == .StructInitOne); |
| 963 | 969 | const data = tree.nodes.items(.data)[node]; |
| 964 | 970 | buffer[0] = data.rhs; |
| ... | ... | @@ -970,7 +976,7 @@ pub const Tree = struct { |
| 970 | 976 | }); |
| 971 | 977 | } |
| 972 | 978 | |
| 973 | pub fn structInitDotTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.StructInit { | |
| 979 | pub fn structInitDotTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) full.StructInit { | |
| 974 | 980 | assert(tree.nodes.items(.tag)[node] == .StructInitDotTwo or |
| 975 | 981 | tree.nodes.items(.tag)[node] == .StructInitDotTwoComma); |
| 976 | 982 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -988,7 +994,7 @@ pub const Tree = struct { |
| 988 | 994 | }); |
| 989 | 995 | } |
| 990 | 996 | |
| 991 | pub fn structInitDot(tree: Tree, node: Node.Index) Full.StructInit { | |
| 997 | pub fn structInitDot(tree: Tree, node: Node.Index) full.StructInit { | |
| 992 | 998 | assert(tree.nodes.items(.tag)[node] == .StructInitDot); |
| 993 | 999 | const data = tree.nodes.items(.data)[node]; |
| 994 | 1000 | return tree.fullStructInit(.{ |
| ... | ... | @@ -998,7 +1004,7 @@ pub const Tree = struct { |
| 998 | 1004 | }); |
| 999 | 1005 | } |
| 1000 | 1006 | |
| 1001 | pub fn structInit(tree: Tree, node: Node.Index) Full.StructInit { | |
| 1007 | pub fn structInit(tree: Tree, node: Node.Index) full.StructInit { | |
| 1002 | 1008 | assert(tree.nodes.items(.tag)[node] == .StructInit); |
| 1003 | 1009 | const data = tree.nodes.items(.data)[node]; |
| 1004 | 1010 | const fields_range = tree.extraData(data.rhs, Node.SubRange); |
| ... | ... | @@ -1009,7 +1015,7 @@ pub const Tree = struct { |
| 1009 | 1015 | }); |
| 1010 | 1016 | } |
| 1011 | 1017 | |
| 1012 | pub fn arrayInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) Full.ArrayInit { | |
| 1018 | pub fn arrayInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit { | |
| 1013 | 1019 | assert(tree.nodes.items(.tag)[node] == .ArrayInitOne); |
| 1014 | 1020 | const data = tree.nodes.items(.data)[node]; |
| 1015 | 1021 | buffer[0] = data.rhs; |
| ... | ... | @@ -1023,7 +1029,7 @@ pub const Tree = struct { |
| 1023 | 1029 | }; |
| 1024 | 1030 | } |
| 1025 | 1031 | |
| 1026 | pub fn arrayInitDotTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ArrayInit { | |
| 1032 | pub fn arrayInitDotTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit { | |
| 1027 | 1033 | assert(tree.nodes.items(.tag)[node] == .ArrayInitDotTwo or |
| 1028 | 1034 | tree.nodes.items(.tag)[node] == .ArrayInitDotTwoComma); |
| 1029 | 1035 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1043,7 +1049,7 @@ pub const Tree = struct { |
| 1043 | 1049 | }; |
| 1044 | 1050 | } |
| 1045 | 1051 | |
| 1046 | pub fn arrayInitDot(tree: Tree, node: Node.Index) Full.ArrayInit { | |
| 1052 | pub fn arrayInitDot(tree: Tree, node: Node.Index) full.ArrayInit { | |
| 1047 | 1053 | assert(tree.nodes.items(.tag)[node] == .ArrayInitDot); |
| 1048 | 1054 | const data = tree.nodes.items(.data)[node]; |
| 1049 | 1055 | return .{ |
| ... | ... | @@ -1055,7 +1061,7 @@ pub const Tree = struct { |
| 1055 | 1061 | }; |
| 1056 | 1062 | } |
| 1057 | 1063 | |
| 1058 | pub fn arrayInit(tree: Tree, node: Node.Index) Full.ArrayInit { | |
| 1064 | pub fn arrayInit(tree: Tree, node: Node.Index) full.ArrayInit { | |
| 1059 | 1065 | assert(tree.nodes.items(.tag)[node] == .ArrayInit); |
| 1060 | 1066 | const data = tree.nodes.items(.data)[node]; |
| 1061 | 1067 | const elem_range = tree.extraData(data.rhs, Node.SubRange); |
| ... | ... | @@ -1068,7 +1074,7 @@ pub const Tree = struct { |
| 1068 | 1074 | }; |
| 1069 | 1075 | } |
| 1070 | 1076 | |
| 1071 | pub fn arrayType(tree: Tree, node: Node.Index) Full.ArrayType { | |
| 1077 | pub fn arrayType(tree: Tree, node: Node.Index) full.ArrayType { | |
| 1072 | 1078 | assert(tree.nodes.items(.tag)[node] == .ArrayType); |
| 1073 | 1079 | const data = tree.nodes.items(.data)[node]; |
| 1074 | 1080 | return .{ |
| ... | ... | @@ -1081,7 +1087,7 @@ pub const Tree = struct { |
| 1081 | 1087 | }; |
| 1082 | 1088 | } |
| 1083 | 1089 | |
| 1084 | pub fn arrayTypeSentinel(tree: Tree, node: Node.Index) Full.ArrayType { | |
| 1090 | pub fn arrayTypeSentinel(tree: Tree, node: Node.Index) full.ArrayType { | |
| 1085 | 1091 | assert(tree.nodes.items(.tag)[node] == .ArrayTypeSentinel); |
| 1086 | 1092 | const data = tree.nodes.items(.data)[node]; |
| 1087 | 1093 | const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel); |
| ... | ... | @@ -1095,7 +1101,7 @@ pub const Tree = struct { |
| 1095 | 1101 | }; |
| 1096 | 1102 | } |
| 1097 | 1103 | |
| 1098 | pub fn ptrTypeAligned(tree: Tree, node: Node.Index) Full.PtrType { | |
| 1104 | pub fn ptrTypeAligned(tree: Tree, node: Node.Index) full.PtrType { | |
| 1099 | 1105 | assert(tree.nodes.items(.tag)[node] == .PtrTypeAligned); |
| 1100 | 1106 | const data = tree.nodes.items(.data)[node]; |
| 1101 | 1107 | return tree.fullPtrType(.{ |
| ... | ... | @@ -1108,7 +1114,7 @@ pub const Tree = struct { |
| 1108 | 1114 | }); |
| 1109 | 1115 | } |
| 1110 | 1116 | |
| 1111 | pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) Full.PtrType { | |
| 1117 | pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) full.PtrType { | |
| 1112 | 1118 | assert(tree.nodes.items(.tag)[node] == .PtrTypeSentinel); |
| 1113 | 1119 | const data = tree.nodes.items(.data)[node]; |
| 1114 | 1120 | return tree.fullPtrType(.{ |
| ... | ... | @@ -1121,7 +1127,7 @@ pub const Tree = struct { |
| 1121 | 1127 | }); |
| 1122 | 1128 | } |
| 1123 | 1129 | |
| 1124 | pub fn ptrType(tree: Tree, node: Node.Index) Full.PtrType { | |
| 1130 | pub fn ptrType(tree: Tree, node: Node.Index) full.PtrType { | |
| 1125 | 1131 | assert(tree.nodes.items(.tag)[node] == .PtrType); |
| 1126 | 1132 | const data = tree.nodes.items(.data)[node]; |
| 1127 | 1133 | const extra = tree.extraData(data.lhs, Node.PtrType); |
| ... | ... | @@ -1135,7 +1141,7 @@ pub const Tree = struct { |
| 1135 | 1141 | }); |
| 1136 | 1142 | } |
| 1137 | 1143 | |
| 1138 | pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) Full.PtrType { | |
| 1144 | pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType { | |
| 1139 | 1145 | assert(tree.nodes.items(.tag)[node] == .PtrTypeBitRange); |
| 1140 | 1146 | const data = tree.nodes.items(.data)[node]; |
| 1141 | 1147 | const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange); |
| ... | ... | @@ -1149,7 +1155,7 @@ pub const Tree = struct { |
| 1149 | 1155 | }); |
| 1150 | 1156 | } |
| 1151 | 1157 | |
| 1152 | pub fn sliceOpen(tree: Tree, node: Node.Index) Full.Slice { | |
| 1158 | pub fn sliceOpen(tree: Tree, node: Node.Index) full.Slice { | |
| 1153 | 1159 | assert(tree.nodes.items(.tag)[node] == .SliceOpen); |
| 1154 | 1160 | const data = tree.nodes.items(.data)[node]; |
| 1155 | 1161 | return .{ |
| ... | ... | @@ -1163,7 +1169,7 @@ pub const Tree = struct { |
| 1163 | 1169 | }; |
| 1164 | 1170 | } |
| 1165 | 1171 | |
| 1166 | pub fn slice(tree: Tree, node: Node.Index) Full.Slice { | |
| 1172 | pub fn slice(tree: Tree, node: Node.Index) full.Slice { | |
| 1167 | 1173 | assert(tree.nodes.items(.tag)[node] == .Slice); |
| 1168 | 1174 | const data = tree.nodes.items(.data)[node]; |
| 1169 | 1175 | const extra = tree.extraData(data.rhs, Node.Slice); |
| ... | ... | @@ -1178,7 +1184,7 @@ pub const Tree = struct { |
| 1178 | 1184 | }; |
| 1179 | 1185 | } |
| 1180 | 1186 | |
| 1181 | pub fn sliceSentinel(tree: Tree, node: Node.Index) Full.Slice { | |
| 1187 | pub fn sliceSentinel(tree: Tree, node: Node.Index) full.Slice { | |
| 1182 | 1188 | assert(tree.nodes.items(.tag)[node] == .SliceSentinel); |
| 1183 | 1189 | const data = tree.nodes.items(.data)[node]; |
| 1184 | 1190 | const extra = tree.extraData(data.rhs, Node.SliceSentinel); |
| ... | ... | @@ -1193,7 +1199,7 @@ pub const Tree = struct { |
| 1193 | 1199 | }; |
| 1194 | 1200 | } |
| 1195 | 1201 | |
| 1196 | pub fn containerDeclTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ContainerDecl { | |
| 1202 | pub fn containerDeclTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl { | |
| 1197 | 1203 | assert(tree.nodes.items(.tag)[node] == .ContainerDeclTwo or |
| 1198 | 1204 | tree.nodes.items(.tag)[node] == .ContainerDeclTwoComma); |
| 1199 | 1205 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1212,7 +1218,7 @@ pub const Tree = struct { |
| 1212 | 1218 | }); |
| 1213 | 1219 | } |
| 1214 | 1220 | |
| 1215 | pub fn containerDecl(tree: Tree, node: Node.Index) Full.ContainerDecl { | |
| 1221 | pub fn containerDecl(tree: Tree, node: Node.Index) full.ContainerDecl { | |
| 1216 | 1222 | assert(tree.nodes.items(.tag)[node] == .ContainerDecl or |
| 1217 | 1223 | tree.nodes.items(.tag)[node] == .ContainerDeclComma); |
| 1218 | 1224 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1224,7 +1230,7 @@ pub const Tree = struct { |
| 1224 | 1230 | }); |
| 1225 | 1231 | } |
| 1226 | 1232 | |
| 1227 | pub fn containerDeclArg(tree: Tree, node: Node.Index) Full.ContainerDecl { | |
| 1233 | pub fn containerDeclArg(tree: Tree, node: Node.Index) full.ContainerDecl { | |
| 1228 | 1234 | assert(tree.nodes.items(.tag)[node] == .ContainerDeclArg or |
| 1229 | 1235 | tree.nodes.items(.tag)[node] == .ContainerDeclArgComma); |
| 1230 | 1236 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1237,7 +1243,7 @@ pub const Tree = struct { |
| 1237 | 1243 | }); |
| 1238 | 1244 | } |
| 1239 | 1245 | |
| 1240 | pub fn taggedUnionTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ContainerDecl { | |
| 1246 | pub fn taggedUnionTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl { | |
| 1241 | 1247 | assert(tree.nodes.items(.tag)[node] == .TaggedUnionTwo or |
| 1242 | 1248 | tree.nodes.items(.tag)[node] == .TaggedUnionTwoComma); |
| 1243 | 1249 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1257,7 +1263,7 @@ pub const Tree = struct { |
| 1257 | 1263 | }); |
| 1258 | 1264 | } |
| 1259 | 1265 | |
| 1260 | pub fn taggedUnion(tree: Tree, node: Node.Index) Full.ContainerDecl { | |
| 1266 | pub fn taggedUnion(tree: Tree, node: Node.Index) full.ContainerDecl { | |
| 1261 | 1267 | assert(tree.nodes.items(.tag)[node] == .TaggedUnion or |
| 1262 | 1268 | tree.nodes.items(.tag)[node] == .TaggedUnionComma); |
| 1263 | 1269 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1270,7 +1276,7 @@ pub const Tree = struct { |
| 1270 | 1276 | }); |
| 1271 | 1277 | } |
| 1272 | 1278 | |
| 1273 | pub fn taggedUnionEnumTag(tree: Tree, node: Node.Index) Full.ContainerDecl { | |
| 1279 | pub fn taggedUnionEnumTag(tree: Tree, node: Node.Index) full.ContainerDecl { | |
| 1274 | 1280 | assert(tree.nodes.items(.tag)[node] == .TaggedUnionEnumTag or |
| 1275 | 1281 | tree.nodes.items(.tag)[node] == .TaggedUnionEnumTagComma); |
| 1276 | 1282 | const data = tree.nodes.items(.data)[node]; |
| ... | ... | @@ -1284,7 +1290,7 @@ pub const Tree = struct { |
| 1284 | 1290 | }); |
| 1285 | 1291 | } |
| 1286 | 1292 | |
| 1287 | pub fn switchCaseOne(tree: Tree, node: Node.Index) Full.SwitchCase { | |
| 1293 | pub fn switchCaseOne(tree: Tree, node: Node.Index) full.SwitchCase { | |
| 1288 | 1294 | const data = &tree.nodes.items(.data)[node]; |
| 1289 | 1295 | return tree.fullSwitchCase(.{ |
| 1290 | 1296 | .values = if (data.lhs == 0) &.{} else @ptrCast([*]Node.Index, &data.lhs)[0..1], |
| ... | ... | @@ -1293,7 +1299,7 @@ pub const Tree = struct { |
| 1293 | 1299 | }); |
| 1294 | 1300 | } |
| 1295 | 1301 | |
| 1296 | pub fn switchCase(tree: Tree, node: Node.Index) Full.SwitchCase { | |
| 1302 | pub fn switchCase(tree: Tree, node: Node.Index) full.SwitchCase { | |
| 1297 | 1303 | const data = tree.nodes.items(.data)[node]; |
| 1298 | 1304 | const extra = tree.extraData(data.lhs, Node.SubRange); |
| 1299 | 1305 | return tree.fullSwitchCase(.{ |
| ... | ... | @@ -1303,9 +1309,30 @@ pub const Tree = struct { |
| 1303 | 1309 | }); |
| 1304 | 1310 | } |
| 1305 | 1311 | |
| 1306 | fn fullVarDecl(tree: Tree, info: Full.VarDecl.Ast) Full.VarDecl { | |
| 1312 | pub fn asmSimple(tree: Tree, node: Node.Index) full.Asm { | |
| 1313 | const data = tree.nodes.items(.data)[node]; | |
| 1314 | return tree.fullAsm(.{ | |
| 1315 | .asm_token = tree.nodes.items(.main_token)[node], | |
| 1316 | .template = data.lhs, | |
| 1317 | .items = &.{}, | |
| 1318 | .rparen = data.rhs, | |
| 1319 | }); | |
| 1320 | } | |
| 1321 | ||
| 1322 | pub fn asmFull(tree: Tree, node: Node.Index) full.Asm { | |
| 1323 | const data = tree.nodes.items(.data)[node]; | |
| 1324 | const extra = tree.extraData(data.rhs, Node.Asm); | |
| 1325 | return tree.fullAsm(.{ | |
| 1326 | .asm_token = tree.nodes.items(.main_token)[node], | |
| 1327 | .template = data.lhs, | |
| 1328 | .items = tree.extra_data[extra.items_start..extra.items_end], | |
| 1329 | .rparen = extra.rparen, | |
| 1330 | }); | |
| 1331 | } | |
| 1332 | ||
| 1333 | fn fullVarDecl(tree: Tree, info: full.VarDecl.Ast) full.VarDecl { | |
| 1307 | 1334 | const token_tags = tree.tokens.items(.tag); |
| 1308 | var result: Full.VarDecl = .{ | |
| 1335 | var result: full.VarDecl = .{ | |
| 1309 | 1336 | .ast = info, |
| 1310 | 1337 | .visib_token = null, |
| 1311 | 1338 | .extern_export_token = null, |
| ... | ... | @@ -1328,9 +1355,9 @@ pub const Tree = struct { |
| 1328 | 1355 | return result; |
| 1329 | 1356 | } |
| 1330 | 1357 | |
| 1331 | fn fullIf(tree: Tree, info: Full.If.Ast) Full.If { | |
| 1358 | fn fullIf(tree: Tree, info: full.If.Ast) full.If { | |
| 1332 | 1359 | const token_tags = tree.tokens.items(.tag); |
| 1333 | var result: Full.If = .{ | |
| 1360 | var result: full.If = .{ | |
| 1334 | 1361 | .ast = info, |
| 1335 | 1362 | .payload_token = null, |
| 1336 | 1363 | .error_token = null, |
| ... | ... | @@ -1353,9 +1380,9 @@ pub const Tree = struct { |
| 1353 | 1380 | return result; |
| 1354 | 1381 | } |
| 1355 | 1382 | |
| 1356 | fn fullContainerField(tree: Tree, info: Full.ContainerField.Ast) Full.ContainerField { | |
| 1383 | fn fullContainerField(tree: Tree, info: full.ContainerField.Ast) full.ContainerField { | |
| 1357 | 1384 | const token_tags = tree.tokens.items(.tag); |
| 1358 | var result: Full.ContainerField = .{ | |
| 1385 | var result: full.ContainerField = .{ | |
| 1359 | 1386 | .ast = info, |
| 1360 | 1387 | .comptime_token = null, |
| 1361 | 1388 | }; |
| ... | ... | @@ -1367,27 +1394,27 @@ pub const Tree = struct { |
| 1367 | 1394 | return result; |
| 1368 | 1395 | } |
| 1369 | 1396 | |
| 1370 | fn fullFnProto(tree: Tree, info: Full.FnProto.Ast) Full.FnProto { | |
| 1397 | fn fullFnProto(tree: Tree, info: full.FnProto.Ast) full.FnProto { | |
| 1371 | 1398 | const token_tags = tree.tokens.items(.tag); |
| 1372 | var result: Full.FnProto = .{ | |
| 1399 | var result: full.FnProto = .{ | |
| 1373 | 1400 | .ast = info, |
| 1374 | 1401 | }; |
| 1375 | 1402 | return result; |
| 1376 | 1403 | } |
| 1377 | 1404 | |
| 1378 | fn fullStructInit(tree: Tree, info: Full.StructInit.Ast) Full.StructInit { | |
| 1405 | fn fullStructInit(tree: Tree, info: full.StructInit.Ast) full.StructInit { | |
| 1379 | 1406 | const token_tags = tree.tokens.items(.tag); |
| 1380 | var result: Full.StructInit = .{ | |
| 1407 | var result: full.StructInit = .{ | |
| 1381 | 1408 | .ast = info, |
| 1382 | 1409 | }; |
| 1383 | 1410 | return result; |
| 1384 | 1411 | } |
| 1385 | 1412 | |
| 1386 | fn fullPtrType(tree: Tree, info: Full.PtrType.Ast) Full.PtrType { | |
| 1413 | fn fullPtrType(tree: Tree, info: full.PtrType.Ast) full.PtrType { | |
| 1387 | 1414 | const token_tags = tree.tokens.items(.tag); |
| 1388 | 1415 | // TODO: looks like stage1 isn't quite smart enough to handle enum |
| 1389 | 1416 | // literals in some places here |
| 1390 | const Kind = Full.PtrType.Kind; | |
| 1417 | const Kind = full.PtrType.Kind; | |
| 1391 | 1418 | const kind: Kind = switch (token_tags[info.main_token]) { |
| 1392 | 1419 | .Asterisk => switch (token_tags[info.main_token + 1]) { |
| 1393 | 1420 | .RBracket => .many, |
| ... | ... | @@ -1402,7 +1429,7 @@ pub const Tree = struct { |
| 1402 | 1429 | }, |
| 1403 | 1430 | else => unreachable, |
| 1404 | 1431 | }; |
| 1405 | var result: Full.PtrType = .{ | |
| 1432 | var result: full.PtrType = .{ | |
| 1406 | 1433 | .kind = kind, |
| 1407 | 1434 | .allowzero_token = null, |
| 1408 | 1435 | .const_token = null, |
| ... | ... | @@ -1441,9 +1468,9 @@ pub const Tree = struct { |
| 1441 | 1468 | return result; |
| 1442 | 1469 | } |
| 1443 | 1470 | |
| 1444 | fn fullContainerDecl(tree: Tree, info: Full.ContainerDecl.Ast) Full.ContainerDecl { | |
| 1471 | fn fullContainerDecl(tree: Tree, info: full.ContainerDecl.Ast) full.ContainerDecl { | |
| 1445 | 1472 | const token_tags = tree.tokens.items(.tag); |
| 1446 | var result: Full.ContainerDecl = .{ | |
| 1473 | var result: full.ContainerDecl = .{ | |
| 1447 | 1474 | .ast = info, |
| 1448 | 1475 | .layout_token = null, |
| 1449 | 1476 | }; |
| ... | ... | @@ -1454,9 +1481,9 @@ pub const Tree = struct { |
| 1454 | 1481 | return result; |
| 1455 | 1482 | } |
| 1456 | 1483 | |
| 1457 | fn fullSwitchCase(tree: Tree, info: Full.SwitchCase.Ast) Full.SwitchCase { | |
| 1484 | fn fullSwitchCase(tree: Tree, info: full.SwitchCase.Ast) full.SwitchCase { | |
| 1458 | 1485 | const token_tags = tree.tokens.items(.tag); |
| 1459 | var result: Full.SwitchCase = .{ | |
| 1486 | var result: full.SwitchCase = .{ | |
| 1460 | 1487 | .ast = info, |
| 1461 | 1488 | .payload_token = null, |
| 1462 | 1489 | }; |
| ... | ... | @@ -1465,10 +1492,67 @@ pub const Tree = struct { |
| 1465 | 1492 | } |
| 1466 | 1493 | return result; |
| 1467 | 1494 | } |
| 1495 | ||
| 1496 | fn fullAsm(tree: Tree, info: full.Asm.Ast) full.Asm { | |
| 1497 | const token_tags = tree.tokens.items(.tag); | |
| 1498 | const node_tags = tree.nodes.items(.tag); | |
| 1499 | var result: full.Asm = .{ | |
| 1500 | .ast = info, | |
| 1501 | .volatile_token = null, | |
| 1502 | .inputs = &.{}, | |
| 1503 | .outputs = &.{}, | |
| 1504 | .first_clobber = null, | |
| 1505 | }; | |
| 1506 | if (token_tags[info.asm_token + 1] == .Keyword_volatile) { | |
| 1507 | result.volatile_token = info.asm_token + 1; | |
| 1508 | } | |
| 1509 | const outputs_end: usize = for (info.items) |item, i| { | |
| 1510 | switch (node_tags[item]) { | |
| 1511 | .AsmOutput => continue, | |
| 1512 | else => break i, | |
| 1513 | } | |
| 1514 | } else info.items.len; | |
| 1515 | ||
| 1516 | result.outputs = info.items[0..outputs_end]; | |
| 1517 | result.inputs = info.items[outputs_end..]; | |
| 1518 | ||
| 1519 | if (info.items.len == 0) { | |
| 1520 | // asm ("foo" ::: "a", "b"); | |
| 1521 | const template_token = tree.lastToken(info.template); | |
| 1522 | if (token_tags[template_token + 1] == .Colon and | |
| 1523 | token_tags[template_token + 2] == .Colon and | |
| 1524 | token_tags[template_token + 3] == .Colon and | |
| 1525 | token_tags[template_token + 4] == .StringLiteral) | |
| 1526 | { | |
| 1527 | result.first_clobber = template_token + 4; | |
| 1528 | } | |
| 1529 | } else if (result.inputs.len != 0) { | |
| 1530 | // asm ("foo" :: [_] "" (y) : "a", "b"); | |
| 1531 | const last_input = result.inputs[result.inputs.len - 1]; | |
| 1532 | const rparen = tree.lastToken(last_input); | |
| 1533 | if (token_tags[rparen + 1] == .Colon and | |
| 1534 | token_tags[rparen + 2] == .StringLiteral) | |
| 1535 | { | |
| 1536 | result.first_clobber = rparen + 2; | |
| 1537 | } | |
| 1538 | } else { | |
| 1539 | // asm ("foo" : [_] "" (x) :: "a", "b"); | |
| 1540 | const last_output = result.outputs[result.outputs.len - 1]; | |
| 1541 | const rparen = tree.lastToken(last_output); | |
| 1542 | if (token_tags[rparen + 1] == .Colon and | |
| 1543 | token_tags[rparen + 2] == .Colon and | |
| 1544 | token_tags[rparen + 3] == .StringLiteral) | |
| 1545 | { | |
| 1546 | result.first_clobber = rparen + 3; | |
| 1547 | } | |
| 1548 | } | |
| 1549 | ||
| 1550 | return result; | |
| 1551 | } | |
| 1468 | 1552 | }; |
| 1469 | 1553 | |
| 1470 | 1554 | /// Fully assembled AST node information. |
| 1471 | pub const Full = struct { | |
| 1555 | pub const full = struct { | |
| 1472 | 1556 | pub const VarDecl = struct { |
| 1473 | 1557 | visib_token: ?TokenIndex, |
| 1474 | 1558 | extern_export_token: ?TokenIndex, |
| ... | ... | @@ -1624,6 +1708,21 @@ pub const Full = struct { |
| 1624 | 1708 | target_expr: Node.Index, |
| 1625 | 1709 | }; |
| 1626 | 1710 | }; |
| 1711 | ||
| 1712 | pub const Asm = struct { | |
| 1713 | ast: Ast, | |
| 1714 | volatile_token: ?TokenIndex, | |
| 1715 | first_clobber: ?TokenIndex, | |
| 1716 | outputs: []const Node.Index, | |
| 1717 | inputs: []const Node.Index, | |
| 1718 | ||
| 1719 | pub const Ast = struct { | |
| 1720 | asm_token: TokenIndex, | |
| 1721 | template: Node.Index, | |
| 1722 | items: []const Node.Index, | |
| 1723 | rparen: TokenIndex, | |
| 1724 | }; | |
| 1725 | }; | |
| 1627 | 1726 | }; |
| 1628 | 1727 | |
| 1629 | 1728 | pub const Error = union(enum) { |
| ... | ... | @@ -2234,15 +2333,15 @@ pub const Node = struct { |
| 2234 | 2333 | Block, |
| 2235 | 2334 | /// Same as BlockTwo but there is known to be a semicolon before the rbrace. |
| 2236 | 2335 | BlockSemicolon, |
| 2237 | /// `asm(lhs)`. rhs unused. | |
| 2336 | /// `asm(lhs)`. rhs is the token index of the rparen. | |
| 2238 | 2337 | AsmSimple, |
| 2239 | /// `asm(lhs, a)`. `sub_range_list[rhs]`. | |
| 2338 | /// `asm(lhs, a)`. `Asm[rhs]`. | |
| 2240 | 2339 | Asm, |
| 2241 | /// `[a] "b" (c)`. lhs is string literal token index, rhs is 0. | |
| 2242 | /// `[a] "b" (-> rhs)`. lhs is the string literal token index, rhs is type expr. | |
| 2340 | /// `[a] "b" (c)`. lhs is 0, rhs is token index of the rparen. | |
| 2341 | /// `[a] "b" (-> lhs)`. rhs is token index of the rparen. | |
| 2243 | 2342 | /// main_token is `a`. |
| 2244 | 2343 | AsmOutput, |
| 2245 | /// `[a] "b" (rhs)`. lhs is string literal token index. | |
| 2344 | /// `[a] "b" (lhs)`. rhs is token index of the rparen. | |
| 2246 | 2345 | /// main_token is `a`. |
| 2247 | 2346 | AsmInput, |
| 2248 | 2347 | /// `error.a`. lhs is token index of `.`. rhs is token index of `a`. |
| ... | ... | @@ -2355,4 +2454,11 @@ pub const Node = struct { |
| 2355 | 2454 | /// Populated if callconv(A) is present. |
| 2356 | 2455 | callconv_expr: Index, |
| 2357 | 2456 | }; |
| 2457 | ||
| 2458 | pub const Asm = struct { | |
| 2459 | items_start: Index, | |
| 2460 | items_end: Index, | |
| 2461 | /// Needed to make lastToken() work. | |
| 2462 | rparen: TokenIndex, | |
| 2463 | }; | |
| 2358 | 2464 | }; |
lib/std/zig/parse.zig+27-19| ... | ... | @@ -472,7 +472,7 @@ const Parser = struct { |
| 472 | 472 | |
| 473 | 473 | /// TestDecl <- KEYWORD_test STRINGLITERALSINGLE? Block |
| 474 | 474 | fn expectTestDecl(p: *Parser) !Node.Index { |
| 475 | const test_token = try p.expectToken(.Keyword_test); | |
| 475 | const test_token = p.assertToken(.Keyword_test); | |
| 476 | 476 | const name_token = p.eatToken(.StringLiteral); |
| 477 | 477 | const block_node = try p.parseBlock(); |
| 478 | 478 | if (block_node == 0) return p.fail(.{ .ExpectedLBrace = .{ .token = p.tok_i } }); |
| ... | ... | @@ -739,7 +739,7 @@ const Parser = struct { |
| 739 | 739 | /// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? |
| 740 | 740 | fn expectContainerField(p: *Parser) !Node.Index { |
| 741 | 741 | const comptime_token = p.eatToken(.Keyword_comptime); |
| 742 | const name_token = try p.expectToken(.Identifier); | |
| 742 | const name_token = p.assertToken(.Identifier); | |
| 743 | 743 | |
| 744 | 744 | var align_expr: Node.Index = 0; |
| 745 | 745 | var type_expr: Node.Index = 0; |
| ... | ... | @@ -1846,7 +1846,7 @@ const Parser = struct { |
| 1846 | 1846 | /// / CurlySuffixExpr |
| 1847 | 1847 | fn parsePrimaryExpr(p: *Parser) !Node.Index { |
| 1848 | 1848 | switch (p.token_tags[p.tok_i]) { |
| 1849 | .Keyword_asm => return p.parseAsmExpr(), | |
| 1849 | .Keyword_asm => return p.expectAsmExpr(), | |
| 1850 | 1850 | .Keyword_if => return p.parseIfExpr(), |
| 1851 | 1851 | .Keyword_break => { |
| 1852 | 1852 | p.tok_i += 1; |
| ... | ... | @@ -2910,19 +2910,19 @@ const Parser = struct { |
| 2910 | 2910 | /// StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? |
| 2911 | 2911 | /// AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem? |
| 2912 | 2912 | /// AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? |
| 2913 | fn parseAsmExpr(p: *Parser) !Node.Index { | |
| 2913 | fn expectAsmExpr(p: *Parser) !Node.Index { | |
| 2914 | 2914 | const asm_token = p.assertToken(.Keyword_asm); |
| 2915 | 2915 | _ = p.eatToken(.Keyword_volatile); |
| 2916 | 2916 | _ = try p.expectToken(.LParen); |
| 2917 | 2917 | const template = try p.expectExpr(); |
| 2918 | 2918 | |
| 2919 | if (p.eatToken(.RParen)) |_| { | |
| 2919 | if (p.eatToken(.RParen)) |rparen| { | |
| 2920 | 2920 | return p.addNode(.{ |
| 2921 | 2921 | .tag = .AsmSimple, |
| 2922 | 2922 | .main_token = asm_token, |
| 2923 | 2923 | .data = .{ |
| 2924 | 2924 | .lhs = template, |
| 2925 | .rhs = undefined, | |
| 2925 | .rhs = rparen, | |
| 2926 | 2926 | }, |
| 2927 | 2927 | }); |
| 2928 | 2928 | } |
| ... | ... | @@ -2981,16 +2981,17 @@ const Parser = struct { |
| 2981 | 2981 | } |
| 2982 | 2982 | } |
| 2983 | 2983 | } |
| 2984 | _ = try p.expectToken(.RParen); | |
| 2984 | const rparen = try p.expectToken(.RParen); | |
| 2985 | 2985 | const span = try p.listToSpan(list.items); |
| 2986 | 2986 | return p.addNode(.{ |
| 2987 | 2987 | .tag = .Asm, |
| 2988 | 2988 | .main_token = asm_token, |
| 2989 | 2989 | .data = .{ |
| 2990 | 2990 | .lhs = template, |
| 2991 | .rhs = try p.addExtra(Node.SubRange{ | |
| 2992 | .start = span.start, | |
| 2993 | .end = span.end, | |
| 2991 | .rhs = try p.addExtra(Node.Asm{ | |
| 2992 | .items_start = span.start, | |
| 2993 | .items_end = span.end, | |
| 2994 | .rparen = rparen, | |
| 2994 | 2995 | }), |
| 2995 | 2996 | }, |
| 2996 | 2997 | }); |
| ... | ... | @@ -3001,16 +3002,23 @@ const Parser = struct { |
| 3001 | 3002 | _ = p.eatToken(.LBracket) orelse return null_node; |
| 3002 | 3003 | const identifier = try p.expectToken(.Identifier); |
| 3003 | 3004 | _ = try p.expectToken(.RBracket); |
| 3004 | const constraint = try p.expectToken(.StringLiteral); | |
| 3005 | _ = try p.expectToken(.StringLiteral); | |
| 3005 | 3006 | _ = try p.expectToken(.LParen); |
| 3006 | const rhs: Node.Index = if (p.eatToken(.Arrow)) |_| try p.expectTypeExpr() else null_node; | |
| 3007 | _ = try p.expectToken(.RParen); | |
| 3007 | const type_expr: Node.Index = blk: { | |
| 3008 | if (p.eatToken(.Arrow)) |_| { | |
| 3009 | break :blk try p.expectTypeExpr(); | |
| 3010 | } else { | |
| 3011 | _ = try p.expectToken(.Identifier); | |
| 3012 | break :blk null_node; | |
| 3013 | } | |
| 3014 | }; | |
| 3015 | const rparen = try p.expectToken(.RParen); | |
| 3008 | 3016 | return p.addNode(.{ |
| 3009 | 3017 | .tag = .AsmOutput, |
| 3010 | 3018 | .main_token = identifier, |
| 3011 | 3019 | .data = .{ |
| 3012 | .lhs = constraint, | |
| 3013 | .rhs = rhs, | |
| 3020 | .lhs = type_expr, | |
| 3021 | .rhs = rparen, | |
| 3014 | 3022 | }, |
| 3015 | 3023 | }); |
| 3016 | 3024 | } |
| ... | ... | @@ -3020,16 +3028,16 @@ const Parser = struct { |
| 3020 | 3028 | _ = p.eatToken(.LBracket) orelse return null_node; |
| 3021 | 3029 | const identifier = try p.expectToken(.Identifier); |
| 3022 | 3030 | _ = try p.expectToken(.RBracket); |
| 3023 | const constraint = try p.expectToken(.StringLiteral); | |
| 3031 | _ = try p.expectToken(.StringLiteral); | |
| 3024 | 3032 | _ = try p.expectToken(.LParen); |
| 3025 | 3033 | const expr = try p.expectExpr(); |
| 3026 | _ = try p.expectToken(.RParen); | |
| 3034 | const rparen = try p.expectToken(.RParen); | |
| 3027 | 3035 | return p.addNode(.{ |
| 3028 | 3036 | .tag = .AsmInput, |
| 3029 | 3037 | .main_token = identifier, |
| 3030 | 3038 | .data = .{ |
| 3031 | .lhs = constraint, | |
| 3032 | .rhs = expr, | |
| 3039 | .lhs = expr, | |
| 3040 | .rhs = rparen, | |
| 3033 | 3041 | }, |
| 3034 | 3042 | }); |
| 3035 | 3043 | } |
lib/std/zig/parser_test.zig+24-24| ... | ... | @@ -313,30 +313,30 @@ test "zig fmt: builtin call with trailing comma" { |
| 313 | 313 | ); |
| 314 | 314 | } |
| 315 | 315 | |
| 316 | //test "zig fmt: asm expression with comptime content" { | |
| 317 | // try testCanonical( | |
| 318 | // \\comptime { | |
| 319 | // \\ asm ("foo" ++ "bar"); | |
| 320 | // \\} | |
| 321 | // \\pub fn main() void { | |
| 322 | // \\ asm volatile ("foo" ++ "bar"); | |
| 323 | // \\ asm volatile ("foo" ++ "bar" | |
| 324 | // \\ : [_] "" (x) | |
| 325 | // \\ ); | |
| 326 | // \\ asm volatile ("foo" ++ "bar" | |
| 327 | // \\ : [_] "" (x) | |
| 328 | // \\ : [_] "" (y) | |
| 329 | // \\ ); | |
| 330 | // \\ asm volatile ("foo" ++ "bar" | |
| 331 | // \\ : [_] "" (x) | |
| 332 | // \\ : [_] "" (y) | |
| 333 | // \\ : "h", "e", "l", "l", "o" | |
| 334 | // \\ ); | |
| 335 | // \\} | |
| 336 | // \\ | |
| 337 | // ); | |
| 338 | //} | |
| 339 | // | |
| 316 | test "zig fmt: asm expression with comptime content" { | |
| 317 | try testCanonical( | |
| 318 | \\comptime { | |
| 319 | \\ asm ("foo" ++ "bar"); | |
| 320 | \\} | |
| 321 | \\pub fn main() void { | |
| 322 | \\ asm volatile ("foo" ++ "bar"); | |
| 323 | \\ asm volatile ("foo" ++ "bar" | |
| 324 | \\ : [_] "" (x) | |
| 325 | \\ ); | |
| 326 | \\ asm volatile ("foo" ++ "bar" | |
| 327 | \\ : [_] "" (x) | |
| 328 | \\ : [_] "" (y) | |
| 329 | \\ ); | |
| 330 | \\ asm volatile ("foo" ++ "bar" | |
| 331 | \\ : [_] "" (x) | |
| 332 | \\ : [_] "" (y) | |
| 333 | \\ : "h", "e", "l", "l", "o" | |
| 334 | \\ ); | |
| 335 | \\} | |
| 336 | \\ | |
| 337 | ); | |
| 338 | } | |
| 339 | ||
| 340 | 340 | //test "zig fmt: anytype struct field" { |
| 341 | 341 | // try testCanonical( |
| 342 | 342 | // \\pub const Pointer = struct { |
lib/std/zig/render.zig+179-150| ... | ... | @@ -816,118 +816,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 816 | 816 | .IfSimple => return renderIf(ais, tree, tree.ifSimple(node), space), |
| 817 | 817 | .If => return renderIf(ais, tree, tree.ifFull(node), space), |
| 818 | 818 | |
| 819 | .Asm => unreachable, // TODO | |
| 820 | .AsmSimple => unreachable, // TODO | |
| 821 | .AsmOutput => unreachable, // TODO | |
| 822 | .AsmInput => unreachable, // TODO | |
| 823 | //.Asm => { | |
| 824 | // const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base); | |
| 825 | ||
| 826 | // try renderToken(ais, tree, asm_node.asm_token, Space.Space); // asm | |
| 827 | ||
| 828 | // if (asm_node.volatile_token) |volatile_token| { | |
| 829 | // try renderToken(ais, tree, volatile_token, Space.Space); // volatile | |
| 830 | // try renderToken(ais, tree, tree.nextToken(volatile_token), Space.None); // ( | |
| 831 | // } else { | |
| 832 | // try renderToken(ais, tree, tree.nextToken(asm_node.asm_token), Space.None); // ( | |
| 833 | // } | |
| 834 | ||
| 835 | // asmblk: { | |
| 836 | // ais.pushIndent(); | |
| 837 | // defer ais.popIndent(); | |
| 838 | ||
| 839 | // if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { | |
| 840 | // try renderExpression(ais, tree, asm_node.template, Space.None); | |
| 841 | // break :asmblk; | |
| 842 | // } | |
| 843 | ||
| 844 | // try renderExpression(ais, tree, asm_node.template, Space.Newline); | |
| 845 | ||
| 846 | // ais.setIndentDelta(asm_indent_delta); | |
| 847 | // defer ais.setIndentDelta(indent_delta); | |
| 848 | ||
| 849 | // const colon1 = tree.nextToken(asm_node.template.lastToken()); | |
| 850 | ||
| 851 | // const colon2 = if (asm_node.outputs.len == 0) blk: { | |
| 852 | // try renderToken(ais, tree, colon1, Space.Newline); // : | |
| 853 | ||
| 854 | // break :blk tree.nextToken(colon1); | |
| 855 | // } else blk: { | |
| 856 | // try renderToken(ais, tree, colon1, Space.Space); // : | |
| 857 | ||
| 858 | // ais.pushIndent(); | |
| 859 | // defer ais.popIndent(); | |
| 860 | ||
| 861 | // for (asm_node.outputs) |*asm_output, i| { | |
| 862 | // if (i + 1 < asm_node.outputs.len) { | |
| 863 | // const next_asm_output = asm_node.outputs[i + 1]; | |
| 864 | // try renderAsmOutput(allocator, ais, tree, asm_output, Space.None); | |
| 865 | ||
| 866 | // const comma = tree.prevToken(next_asm_output.firstToken()); | |
| 867 | // try renderToken(ais, tree, comma, Space.Newline); // , | |
| 868 | // try renderExtraNewlineToken(ais, tree, next_asm_output.firstToken()); | |
| 869 | // } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { | |
| 870 | // try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline); | |
| 871 | // break :asmblk; | |
| 872 | // } else { | |
| 873 | // try renderAsmOutput(allocator, ais, tree, asm_output, Space.Newline); | |
| 874 | // const comma_or_colon = tree.nextToken(asm_output.lastToken()); | |
| 875 | // break :blk switch (tree.token_tags[comma_or_colon]) { | |
| 876 | // .Comma => tree.nextToken(comma_or_colon), | |
| 877 | // else => comma_or_colon, | |
| 878 | // }; | |
| 879 | // } | |
| 880 | // } | |
| 881 | // unreachable; | |
| 882 | // }; | |
| 883 | ||
| 884 | // const colon3 = if (asm_node.inputs.len == 0) blk: { | |
| 885 | // try renderToken(ais, tree, colon2, Space.Newline); // : | |
| 886 | // break :blk tree.nextToken(colon2); | |
| 887 | // } else blk: { | |
| 888 | // try renderToken(ais, tree, colon2, Space.Space); // : | |
| 889 | // ais.pushIndent(); | |
| 890 | // defer ais.popIndent(); | |
| 891 | // for (asm_node.inputs) |*asm_input, i| { | |
| 892 | // if (i + 1 < asm_node.inputs.len) { | |
| 893 | // const next_asm_input = &asm_node.inputs[i + 1]; | |
| 894 | // try renderAsmInput(allocator, ais, tree, asm_input, Space.None); | |
| 895 | ||
| 896 | // const comma = tree.prevToken(next_asm_input.firstToken()); | |
| 897 | // try renderToken(ais, tree, comma, Space.Newline); // , | |
| 898 | // try renderExtraNewlineToken(ais, tree, next_asm_input.firstToken()); | |
| 899 | // } else if (asm_node.clobbers.len == 0) { | |
| 900 | // try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline); | |
| 901 | // break :asmblk; | |
| 902 | // } else { | |
| 903 | // try renderAsmInput(allocator, ais, tree, asm_input, Space.Newline); | |
| 904 | // const comma_or_colon = tree.nextToken(asm_input.lastToken()); | |
| 905 | // break :blk switch (tree.token_tags[comma_or_colon]) { | |
| 906 | // .Comma => tree.nextToken(comma_or_colon), | |
| 907 | // else => comma_or_colon, | |
| 908 | // }; | |
| 909 | // } | |
| 910 | // } | |
| 911 | // unreachable; | |
| 912 | // }; | |
| 913 | ||
| 914 | // try renderToken(ais, tree, colon3, Space.Space); // : | |
| 915 | // ais.pushIndent(); | |
| 916 | // defer ais.popIndent(); | |
| 917 | // for (asm_node.clobbers) |clobber_node, i| { | |
| 918 | // if (i + 1 >= asm_node.clobbers.len) { | |
| 919 | // try renderExpression(ais, tree, clobber_node, Space.Newline); | |
| 920 | // break :asmblk; | |
| 921 | // } else { | |
| 922 | // try renderExpression(ais, tree, clobber_node, Space.None); | |
| 923 | // const comma = tree.nextToken(clobber_node.lastToken()); | |
| 924 | // try renderToken(ais, tree, comma, Space.Space); // , | |
| 925 | // } | |
| 926 | // } | |
| 927 | // } | |
| 928 | ||
| 929 | // return renderToken(ais, tree, asm_node.rparen, space); | |
| 930 | //}, | |
| 819 | .AsmSimple => return renderAsm(ais, tree, tree.asmSimple(node), space), | |
| 820 | .Asm => return renderAsm(ais, tree, tree.asmFull(node), space), | |
| 931 | 821 | |
| 932 | 822 | .EnumLiteral => { |
| 933 | 823 | try renderToken(ais, tree, main_tokens[node] - 1, .None); // . |
| ... | ... | @@ -945,6 +835,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 945 | 835 | .AlignedVarDecl => unreachable, |
| 946 | 836 | .UsingNamespace => unreachable, |
| 947 | 837 | .TestDecl => unreachable, |
| 838 | .AsmOutput => unreachable, | |
| 839 | .AsmInput => unreachable, | |
| 948 | 840 | } |
| 949 | 841 | } |
| 950 | 842 | |
| ... | ... | @@ -952,7 +844,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac |
| 952 | 844 | fn renderArrayType( |
| 953 | 845 | ais: *Ais, |
| 954 | 846 | tree: ast.Tree, |
| 955 | array_type: ast.Full.ArrayType, | |
| 847 | array_type: ast.full.ArrayType, | |
| 956 | 848 | space: Space, |
| 957 | 849 | ) Error!void { |
| 958 | 850 | try renderToken(ais, tree, array_type.ast.lbracket, .None); // lbracket |
| ... | ... | @@ -968,7 +860,7 @@ fn renderArrayType( |
| 968 | 860 | fn renderPtrType( |
| 969 | 861 | ais: *Ais, |
| 970 | 862 | tree: ast.Tree, |
| 971 | ptr_type: ast.Full.PtrType, | |
| 863 | ptr_type: ast.full.PtrType, | |
| 972 | 864 | space: Space, |
| 973 | 865 | ) Error!void { |
| 974 | 866 | switch (ptr_type.kind) { |
| ... | ... | @@ -1040,7 +932,7 @@ fn renderPtrType( |
| 1040 | 932 | fn renderSlice( |
| 1041 | 933 | ais: *Ais, |
| 1042 | 934 | tree: ast.Tree, |
| 1043 | slice: ast.Full.Slice, | |
| 935 | slice: ast.full.Slice, | |
| 1044 | 936 | space: Space, |
| 1045 | 937 | ) Error!void { |
| 1046 | 938 | const node_tags = tree.nodes.items(.tag); |
| ... | ... | @@ -1072,48 +964,56 @@ fn renderSlice( |
| 1072 | 964 | } |
| 1073 | 965 | |
| 1074 | 966 | fn renderAsmOutput( |
| 1075 | allocator: *mem.Allocator, | |
| 1076 | 967 | ais: *Ais, |
| 1077 | 968 | tree: ast.Tree, |
| 1078 | asm_output: *const ast.Node.Asm.Output, | |
| 969 | asm_output: ast.Node.Index, | |
| 1079 | 970 | space: Space, |
| 1080 | 971 | ) Error!void { |
| 1081 | try ais.writer().writeAll("["); | |
| 1082 | try renderExpression(ais, tree, asm_output.symbolic_name, Space.None); | |
| 1083 | try ais.writer().writeAll("] "); | |
| 1084 | try renderExpression(ais, tree, asm_output.constraint, Space.None); | |
| 1085 | try ais.writer().writeAll(" ("); | |
| 1086 | ||
| 1087 | switch (asm_output.kind) { | |
| 1088 | .Variable => |variable_name| { | |
| 1089 | try renderExpression(ais, tree, &variable_name.base, Space.None); | |
| 1090 | }, | |
| 1091 | .Return => |return_type| { | |
| 1092 | try ais.writer().writeAll("-> "); | |
| 1093 | try renderExpression(ais, tree, return_type, Space.None); | |
| 1094 | }, | |
| 972 | const token_tags = tree.tokens.items(.tag); | |
| 973 | const node_tags = tree.nodes.items(.tag); | |
| 974 | const main_tokens = tree.nodes.items(.main_token); | |
| 975 | const datas = tree.nodes.items(.data); | |
| 976 | assert(node_tags[asm_output] == .AsmOutput); | |
| 977 | const symbolic_name = main_tokens[asm_output]; | |
| 978 | ||
| 979 | try renderToken(ais, tree, symbolic_name - 1, .None); // lbracket | |
| 980 | try renderToken(ais, tree, symbolic_name, .None); // ident | |
| 981 | try renderToken(ais, tree, symbolic_name + 1, .Space); // rbracket | |
| 982 | try renderToken(ais, tree, symbolic_name + 2, .Space); // "constraint" | |
| 983 | try renderToken(ais, tree, symbolic_name + 3, .None); // lparen | |
| 984 | ||
| 985 | if (token_tags[symbolic_name + 4] == .Arrow) { | |
| 986 | try renderToken(ais, tree, symbolic_name + 4, .Space); // -> | |
| 987 | try renderExpression(ais, tree, datas[asm_output].lhs, Space.None); | |
| 988 | return renderToken(ais, tree, datas[asm_output].rhs, space); // rparen | |
| 989 | } else { | |
| 990 | try renderToken(ais, tree, symbolic_name + 4, .None); // ident | |
| 991 | return renderToken(ais, tree, symbolic_name + 5, space); // rparen | |
| 1095 | 992 | } |
| 1096 | ||
| 1097 | return renderToken(ais, tree, asm_output.lastToken(), space); // ) | |
| 1098 | 993 | } |
| 1099 | 994 | |
| 1100 | 995 | fn renderAsmInput( |
| 1101 | allocator: *mem.Allocator, | |
| 1102 | 996 | ais: *Ais, |
| 1103 | 997 | tree: ast.Tree, |
| 1104 | asm_input: *const ast.Node.Asm.Input, | |
| 998 | asm_input: ast.Node.Index, | |
| 1105 | 999 | space: Space, |
| 1106 | 1000 | ) Error!void { |
| 1107 | try ais.writer().writeAll("["); | |
| 1108 | try renderExpression(ais, tree, asm_input.symbolic_name, Space.None); | |
| 1109 | try ais.writer().writeAll("] "); | |
| 1110 | try renderExpression(ais, tree, asm_input.constraint, Space.None); | |
| 1111 | try ais.writer().writeAll(" ("); | |
| 1112 | try renderExpression(ais, tree, asm_input.expr, Space.None); | |
| 1113 | return renderToken(ais, tree, asm_input.lastToken(), space); // ) | |
| 1001 | const node_tags = tree.nodes.items(.tag); | |
| 1002 | const main_tokens = tree.nodes.items(.main_token); | |
| 1003 | const datas = tree.nodes.items(.data); | |
| 1004 | assert(node_tags[asm_input] == .AsmInput); | |
| 1005 | const symbolic_name = main_tokens[asm_input]; | |
| 1006 | ||
| 1007 | try renderToken(ais, tree, symbolic_name - 1, .None); // lbracket | |
| 1008 | try renderToken(ais, tree, symbolic_name, .None); // ident | |
| 1009 | try renderToken(ais, tree, symbolic_name + 1, .Space); // rbracket | |
| 1010 | try renderToken(ais, tree, symbolic_name + 2, .Space); // "constraint" | |
| 1011 | try renderToken(ais, tree, symbolic_name + 3, .None); // lparen | |
| 1012 | try renderExpression(ais, tree, datas[asm_input].lhs, Space.None); | |
| 1013 | return renderToken(ais, tree, datas[asm_input].rhs, space); // rparen | |
| 1114 | 1014 | } |
| 1115 | 1015 | |
| 1116 | fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.Full.VarDecl) Error!void { | |
| 1016 | fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!void { | |
| 1117 | 1017 | if (var_decl.visib_token) |visib_token| { |
| 1118 | 1018 | try renderToken(ais, tree, visib_token, Space.Space); // pub |
| 1119 | 1019 | } |
| ... | ... | @@ -1200,7 +1100,7 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.Full.VarDecl) Error!vo |
| 1200 | 1100 | try renderExpression(ais, tree, var_decl.ast.init_node, .Semicolon); |
| 1201 | 1101 | } |
| 1202 | 1102 | |
| 1203 | fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.Full.If, space: Space) Error!void { | |
| 1103 | fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error!void { | |
| 1204 | 1104 | const node_tags = tree.nodes.items(.tag); |
| 1205 | 1105 | const token_tags = tree.tokens.items(.tag); |
| 1206 | 1106 | |
| ... | ... | @@ -1334,7 +1234,7 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.Full.If, space: Space) Error |
| 1334 | 1234 | fn renderContainerField( |
| 1335 | 1235 | ais: *Ais, |
| 1336 | 1236 | tree: ast.Tree, |
| 1337 | field: ast.Full.ContainerField, | |
| 1237 | field: ast.full.ContainerField, | |
| 1338 | 1238 | space: Space, |
| 1339 | 1239 | ) Error!void { |
| 1340 | 1240 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -1430,7 +1330,7 @@ fn renderBuiltinCall( |
| 1430 | 1330 | } |
| 1431 | 1331 | } |
| 1432 | 1332 | |
| 1433 | fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: Space) Error!void { | |
| 1333 | fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: Space) Error!void { | |
| 1434 | 1334 | const token_tags = tree.tokens.items(.tag); |
| 1435 | 1335 | const token_starts = tree.tokens.items(.start); |
| 1436 | 1336 | |
| ... | ... | @@ -1618,7 +1518,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: S |
| 1618 | 1518 | fn renderSwitchCase( |
| 1619 | 1519 | ais: *Ais, |
| 1620 | 1520 | tree: ast.Tree, |
| 1621 | switch_case: ast.Full.SwitchCase, | |
| 1521 | switch_case: ast.full.SwitchCase, | |
| 1622 | 1522 | space: Space, |
| 1623 | 1523 | ) Error!void { |
| 1624 | 1524 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -1709,7 +1609,7 @@ fn renderBlock( |
| 1709 | 1609 | fn renderStructInit( |
| 1710 | 1610 | ais: *Ais, |
| 1711 | 1611 | tree: ast.Tree, |
| 1712 | struct_init: ast.Full.StructInit, | |
| 1612 | struct_init: ast.full.StructInit, | |
| 1713 | 1613 | space: Space, |
| 1714 | 1614 | ) Error!void { |
| 1715 | 1615 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -1763,7 +1663,7 @@ fn renderStructInit( |
| 1763 | 1663 | fn renderArrayInit( |
| 1764 | 1664 | ais: *Ais, |
| 1765 | 1665 | tree: ast.Tree, |
| 1766 | array_init: ast.Full.ArrayInit, | |
| 1666 | array_init: ast.full.ArrayInit, | |
| 1767 | 1667 | space: Space, |
| 1768 | 1668 | ) Error!void { |
| 1769 | 1669 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -1809,7 +1709,7 @@ fn renderArrayInit( |
| 1809 | 1709 | fn renderContainerDecl( |
| 1810 | 1710 | ais: *Ais, |
| 1811 | 1711 | tree: ast.Tree, |
| 1812 | container_decl: ast.Full.ContainerDecl, | |
| 1712 | container_decl: ast.full.ContainerDecl, | |
| 1813 | 1713 | space: Space, |
| 1814 | 1714 | ) Error!void { |
| 1815 | 1715 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -1894,6 +1794,135 @@ fn renderContainerDecl( |
| 1894 | 1794 | return renderToken(ais, tree, rbrace, space); // rbrace |
| 1895 | 1795 | } |
| 1896 | 1796 | |
| 1797 | fn renderAsm( | |
| 1798 | ais: *Ais, | |
| 1799 | tree: ast.Tree, | |
| 1800 | asm_node: ast.full.Asm, | |
| 1801 | space: Space, | |
| 1802 | ) Error!void { | |
| 1803 | const token_tags = tree.tokens.items(.tag); | |
| 1804 | ||
| 1805 | try renderToken(ais, tree, asm_node.ast.asm_token, .Space); // asm | |
| 1806 | ||
| 1807 | if (asm_node.volatile_token) |volatile_token| { | |
| 1808 | try renderToken(ais, tree, volatile_token, .Space); // volatile | |
| 1809 | try renderToken(ais, tree, volatile_token + 1, .None); // lparen | |
| 1810 | } else { | |
| 1811 | try renderToken(ais, tree, asm_node.ast.asm_token + 1, .None); // lparen | |
| 1812 | } | |
| 1813 | ||
| 1814 | if (asm_node.ast.items.len == 0) { | |
| 1815 | try renderExpression(ais, tree, asm_node.ast.template, .None); | |
| 1816 | if (asm_node.first_clobber) |first_clobber| { | |
| 1817 | // asm ("foo" ::: "a", "b") | |
| 1818 | var tok_i = first_clobber; | |
| 1819 | while (true) : (tok_i += 1) { | |
| 1820 | try renderToken(ais, tree, tok_i, .None); | |
| 1821 | tok_i += 1; | |
| 1822 | switch (token_tags[tok_i]) { | |
| 1823 | .RParen => return renderToken(ais, tree, tok_i, space), | |
| 1824 | .Comma => try renderToken(ais, tree, tok_i, .Space), | |
| 1825 | else => unreachable, | |
| 1826 | } | |
| 1827 | } | |
| 1828 | } else { | |
| 1829 | // asm ("foo") | |
| 1830 | return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen | |
| 1831 | } | |
| 1832 | } | |
| 1833 | ||
| 1834 | ais.pushIndent(); | |
| 1835 | try renderExpression(ais, tree, asm_node.ast.template, .Newline); | |
| 1836 | ais.setIndentDelta(asm_indent_delta); | |
| 1837 | const colon1 = tree.lastToken(asm_node.ast.template) + 1; | |
| 1838 | ||
| 1839 | const colon2 = if (asm_node.outputs.len == 0) colon2: { | |
| 1840 | try renderToken(ais, tree, colon1, .Newline); // : | |
| 1841 | break :colon2 colon1 + 1; | |
| 1842 | } else colon2: { | |
| 1843 | try renderToken(ais, tree, colon1, .Space); // : | |
| 1844 | ||
| 1845 | ais.pushIndent(); | |
| 1846 | for (asm_node.outputs) |asm_output, i| { | |
| 1847 | if (i + 1 < asm_node.outputs.len) { | |
| 1848 | const next_asm_output = asm_node.outputs[i + 1]; | |
| 1849 | try renderAsmOutput(ais, tree, asm_output, .None); | |
| 1850 | ||
| 1851 | const comma = tree.firstToken(next_asm_output) - 1; | |
| 1852 | try renderToken(ais, tree, comma, .Newline); // , | |
| 1853 | try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output)); | |
| 1854 | } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) { | |
| 1855 | try renderAsmOutput(ais, tree, asm_output, .Newline); | |
| 1856 | ais.popIndent(); | |
| 1857 | ais.setIndentDelta(indent_delta); | |
| 1858 | ais.popIndent(); | |
| 1859 | return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen | |
| 1860 | } else { | |
| 1861 | try renderAsmOutput(ais, tree, asm_output, .Newline); | |
| 1862 | const comma_or_colon = tree.lastToken(asm_output) + 1; | |
| 1863 | ais.popIndent(); | |
| 1864 | break :colon2 switch (token_tags[comma_or_colon]) { | |
| 1865 | .Comma => comma_or_colon + 1, | |
| 1866 | else => comma_or_colon, | |
| 1867 | }; | |
| 1868 | } | |
| 1869 | } else unreachable; | |
| 1870 | }; | |
| 1871 | ||
| 1872 | const colon3 = if (asm_node.inputs.len == 0) colon3: { | |
| 1873 | try renderToken(ais, tree, colon2, .Newline); // : | |
| 1874 | break :colon3 colon2 + 1; | |
| 1875 | } else colon3: { | |
| 1876 | try renderToken(ais, tree, colon2, .Space); // : | |
| 1877 | ais.pushIndent(); | |
| 1878 | for (asm_node.inputs) |asm_input, i| { | |
| 1879 | if (i + 1 < asm_node.inputs.len) { | |
| 1880 | const next_asm_input = asm_node.inputs[i + 1]; | |
| 1881 | try renderAsmInput(ais, tree, asm_input, .None); | |
| 1882 | ||
| 1883 | const first_token = tree.firstToken(next_asm_input); | |
| 1884 | try renderToken(ais, tree, first_token - 1, .Newline); // , | |
| 1885 | try renderExtraNewlineToken(ais, tree, first_token); | |
| 1886 | } else if (asm_node.first_clobber == null) { | |
| 1887 | try renderAsmInput(ais, tree, asm_input, .Newline); | |
| 1888 | ais.popIndent(); | |
| 1889 | ais.setIndentDelta(indent_delta); | |
| 1890 | ais.popIndent(); | |
| 1891 | return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen | |
| 1892 | } else { | |
| 1893 | try renderAsmInput(ais, tree, asm_input, .Newline); | |
| 1894 | const comma_or_colon = tree.lastToken(asm_input) + 1; | |
| 1895 | ais.popIndent(); | |
| 1896 | break :colon3 switch (token_tags[comma_or_colon]) { | |
| 1897 | .Comma => comma_or_colon + 1, | |
| 1898 | else => comma_or_colon, | |
| 1899 | }; | |
| 1900 | } | |
| 1901 | } | |
| 1902 | unreachable; | |
| 1903 | }; | |
| 1904 | ||
| 1905 | try renderToken(ais, tree, colon3, .Space); // : | |
| 1906 | const first_clobber = asm_node.first_clobber.?; | |
| 1907 | var tok_i = first_clobber; | |
| 1908 | while (true) { | |
| 1909 | switch (token_tags[tok_i + 1]) { | |
| 1910 | .RParen => { | |
| 1911 | ais.setIndentDelta(indent_delta); | |
| 1912 | ais.popIndent(); | |
| 1913 | try renderToken(ais, tree, tok_i, .Newline); | |
| 1914 | return renderToken(ais, tree, tok_i + 1, space); | |
| 1915 | }, | |
| 1916 | .Comma => { | |
| 1917 | try renderToken(ais, tree, tok_i, .None); | |
| 1918 | try renderToken(ais, tree, tok_i + 1, .Space); | |
| 1919 | tok_i += 2; | |
| 1920 | }, | |
| 1921 | else => unreachable, | |
| 1922 | } | |
| 1923 | } else unreachable; // TODO shouldn't need this on while(true) | |
| 1924 | } | |
| 1925 | ||
| 1897 | 1926 | /// Render an expression, and the comma that follows it, if it is present in the source. |
| 1898 | 1927 | fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void { |
| 1899 | 1928 | const token_tags = tree.tokens.items(.tag); |