| ... | ... | @@ -55,7 +55,7 @@ pub const ResultLoc = union(enum) { |
| 55 | 55 | }; |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | | pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*zir.Inst { |
| 58 | pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!*zir.Inst { |
| 59 | 59 | const type_src = scope.tree().token_locs[type_node.firstToken()].start; |
| 60 | 60 | const type_type = try addZIRInstConst(mod, scope, type_src, .{ |
| 61 | 61 | .ty = Type.initTag(.type), |
| ... | ... | @@ -65,134 +65,133 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z |
| 65 | 65 | return expr(mod, scope, type_rl, type_node); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | | fn lvalExpr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { |
| 69 | | switch (node.tag) { |
| 70 | | .Root => unreachable, |
| 71 | | .Use => unreachable, |
| 72 | | .TestDecl => unreachable, |
| 73 | | .DocComment => unreachable, |
| 74 | | .VarDecl => unreachable, |
| 75 | | .SwitchCase => unreachable, |
| 76 | | .SwitchElse => unreachable, |
| 77 | | .Else => unreachable, |
| 78 | | .Payload => unreachable, |
| 79 | | .PointerPayload => unreachable, |
| 80 | | .PointerIndexPayload => unreachable, |
| 81 | | .ErrorTag => unreachable, |
| 82 | | .FieldInitializer => unreachable, |
| 83 | | .ContainerField => unreachable, |
| 84 | | |
| 85 | | .Assign, |
| 86 | | .AssignBitAnd, |
| 87 | | .AssignBitOr, |
| 88 | | .AssignBitShiftLeft, |
| 89 | | .AssignBitShiftRight, |
| 90 | | .AssignBitXor, |
| 91 | | .AssignDiv, |
| 92 | | .AssignSub, |
| 93 | | .AssignSubWrap, |
| 94 | | .AssignMod, |
| 95 | | .AssignAdd, |
| 96 | | .AssignAddWrap, |
| 97 | | .AssignMul, |
| 98 | | .AssignMulWrap, |
| 99 | | .Add, |
| 100 | | .AddWrap, |
| 101 | | .Sub, |
| 102 | | .SubWrap, |
| 103 | | .Mul, |
| 104 | | .MulWrap, |
| 105 | | .Div, |
| 106 | | .Mod, |
| 107 | | .BitAnd, |
| 108 | | .BitOr, |
| 109 | | .BitShiftLeft, |
| 110 | | .BitShiftRight, |
| 111 | | .BitXor, |
| 112 | | .BangEqual, |
| 113 | | .EqualEqual, |
| 114 | | .GreaterThan, |
| 115 | | .GreaterOrEqual, |
| 116 | | .LessThan, |
| 117 | | .LessOrEqual, |
| 118 | | .ArrayCat, |
| 119 | | .ArrayMult, |
| 120 | | .BoolAnd, |
| 121 | | .BoolOr, |
| 122 | | .Asm, |
| 123 | | .StringLiteral, |
| 124 | | .IntegerLiteral, |
| 125 | | .Call, |
| 126 | | .Unreachable, |
| 127 | | .Return, |
| 128 | | .If, |
| 129 | | .While, |
| 130 | | .BoolNot, |
| 131 | | .AddressOf, |
| 132 | | .FloatLiteral, |
| 133 | | .UndefinedLiteral, |
| 134 | | .BoolLiteral, |
| 135 | | .NullLiteral, |
| 136 | | .OptionalType, |
| 137 | | .Block, |
| 138 | | .LabeledBlock, |
| 139 | | .Break, |
| 68 | fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { |
| 69 | const tree = scope.tree(); |
| 70 | const node_tags = tree.nodes.items(.tag); |
| 71 | const main_tokens = tree.nodes.items(.main_token); |
| 72 | switch (node_tags[node]) { |
| 73 | .root => unreachable, |
| 74 | .@"usingnamespace" => unreachable, |
| 75 | .test_decl => unreachable, |
| 76 | .doc_comment => unreachable, |
| 77 | .var_decl => unreachable, |
| 78 | .switch_case => unreachable, |
| 79 | .switch_else => unreachable, |
| 80 | .container_field_init => unreachable, |
| 81 | .container_field_align => unreachable, |
| 82 | .container_field => unreachable, |
| 83 | |
| 84 | .assign, |
| 85 | .assign_bit_and, |
| 86 | .assign_bit_or, |
| 87 | .assign_bit_shift_left, |
| 88 | .assign_bit_shift_right, |
| 89 | .assign_bit_xor, |
| 90 | .assign_div, |
| 91 | .assign_sub, |
| 92 | .assign_sub_wrap, |
| 93 | .assign_mod, |
| 94 | .assign_add, |
| 95 | .assign_add_wrap, |
| 96 | .assign_mul, |
| 97 | .assign_mul_wrap, |
| 98 | .add, |
| 99 | .add_wrap, |
| 100 | .sub, |
| 101 | .sub_wrap, |
| 102 | .mul, |
| 103 | .mul_wrap, |
| 104 | .div, |
| 105 | .mod, |
| 106 | .bit_and, |
| 107 | .bit_or, |
| 108 | .bit_shift_left, |
| 109 | .bit_shift_right, |
| 110 | .bit_xor, |
| 111 | .bang_equal, |
| 112 | .equal_equal, |
| 113 | .greater_than, |
| 114 | .greater_or_equal, |
| 115 | .less_than, |
| 116 | .less_or_equal, |
| 117 | .array_cat, |
| 118 | .array_mult, |
| 119 | .bool_and, |
| 120 | .bool_or, |
| 121 | .@"asm", |
| 122 | .string_literal, |
| 123 | .integer_literal, |
| 124 | .call, |
| 125 | .@"unreachable", |
| 126 | .@"return", |
| 127 | .@"if", |
| 128 | .@"while", |
| 129 | .bool_not, |
| 130 | .address_of, |
| 131 | .float_literal, |
| 132 | .undefined_literal, |
| 133 | .bool_literal, |
| 134 | .null_literal, |
| 135 | .optional_type, |
| 136 | .block, |
| 137 | .labeled_block, |
| 138 | .@"break", |
| 140 | 139 | .PtrType, |
| 141 | | .ArrayType, |
| 142 | | .ArrayTypeSentinel, |
| 143 | | .EnumLiteral, |
| 140 | .array_type, |
| 141 | .array_type_sentinel, |
| 142 | .enum_literal, |
| 144 | 143 | .MultilineStringLiteral, |
| 145 | | .CharLiteral, |
| 146 | | .Defer, |
| 147 | | .Catch, |
| 148 | | .ErrorUnion, |
| 149 | | .MergeErrorSets, |
| 150 | | .Range, |
| 151 | | .Await, |
| 152 | | .BitNot, |
| 153 | | .Negation, |
| 154 | | .NegationWrap, |
| 155 | | .Resume, |
| 156 | | .Try, |
| 157 | | .SliceType, |
| 158 | | .Slice, |
| 144 | .char_literal, |
| 145 | .@"defer", |
| 146 | .@"catch", |
| 147 | .error_union, |
| 148 | .merge_error_sets, |
| 149 | .range, |
| 150 | .@"await", |
| 151 | .bit_not, |
| 152 | .negation, |
| 153 | .negation_wrap, |
| 154 | .@"resume", |
| 155 | .@"try", |
| 156 | .slice_type, |
| 157 | .slice, |
| 159 | 158 | .ArrayInitializer, |
| 160 | 159 | .ArrayInitializerDot, |
| 161 | 160 | .StructInitializer, |
| 162 | 161 | .StructInitializerDot, |
| 163 | | .Switch, |
| 164 | | .For, |
| 165 | | .Suspend, |
| 166 | | .Continue, |
| 167 | | .AnyType, |
| 168 | | .ErrorType, |
| 162 | .@"switch", |
| 163 | .@"for", |
| 164 | .@"suspend", |
| 165 | .@"continue", |
| 166 | .@"anytype", |
| 167 | .error_type, |
| 169 | 168 | .FnProto, |
| 170 | | .AnyFrameType, |
| 171 | | .ErrorSetDecl, |
| 169 | .anyframe_type, |
| 170 | .error_set_decl, |
| 172 | 171 | .ContainerDecl, |
| 173 | | .Comptime, |
| 174 | | .Nosuspend, |
| 172 | .@"comptime", |
| 173 | .@"nosuspend", |
| 174 | .builtin_call, |
| 175 | .builtin_call_comma, |
| 175 | 176 | => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}), |
| 176 | 177 | |
| 177 | | // @field can be assigned to |
| 178 | | .BuiltinCall => { |
| 179 | | const call = node.castTag(.BuiltinCall).?; |
| 180 | | const tree = scope.tree(); |
| 181 | | const builtin_name = tree.tokenSlice(call.builtin_token); |
| 182 | | |
| 178 | // `@field` can be assigned to. |
| 179 | .builtin_call_two, .builtin_call_two_comma => { |
| 180 | const builtin_token = main_tokens[node]; |
| 181 | const builtin_name = tree.tokenSlice(builtin_token); |
| 183 | 182 | if (!mem.eql(u8, builtin_name, "@field")) { |
| 184 | 183 | return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}); |
| 185 | 184 | } |
| 186 | 185 | }, |
| 187 | 186 | |
| 188 | 187 | // can be assigned to |
| 189 | | .UnwrapOptional, |
| 190 | | .Deref, |
| 191 | | .Period, |
| 192 | | .ArrayAccess, |
| 193 | | .Identifier, |
| 194 | | .GroupedExpression, |
| 195 | | .OrElse, |
| 188 | .unwrap_optional, |
| 189 | .deref, |
| 190 | .period, |
| 191 | .array_access, |
| 192 | .identifier, |
| 193 | .grouped_expression, |
| 194 | .@"orelse", |
| 196 | 195 | => {}, |
| 197 | 196 | } |
| 198 | 197 | return expr(mod, scope, .ref, node); |
| ... | ... | @@ -202,16 +201,16 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { |
| 202 | 201 | /// When `rl` is discard, ptr, inferred_ptr, bitcasted_ptr, or inferred_ptr, the |
| 203 | 202 | /// result instruction can be used to inspect whether it is isNoReturn() but that is it, |
| 204 | 203 | /// it must otherwise not be used. |
| 205 | | pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst { |
| 204 | pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst { |
| 206 | 205 | switch (node.tag) { |
| 207 | | .Root => unreachable, // Top-level declaration. |
| 208 | | .Use => unreachable, // Top-level declaration. |
| 209 | | .TestDecl => unreachable, // Top-level declaration. |
| 210 | | .DocComment => unreachable, // Top-level declaration. |
| 211 | | .VarDecl => unreachable, // Handled in `blockExpr`. |
| 212 | | .SwitchCase => unreachable, // Handled in `switchExpr`. |
| 213 | | .SwitchElse => unreachable, // Handled in `switchExpr`. |
| 214 | | .Range => unreachable, // Handled in `switchExpr`. |
| 206 | .root => unreachable, // Top-level declaration. |
| 207 | .@"usingnamespace" => unreachable, // Top-level declaration. |
| 208 | .test_decl => unreachable, // Top-level declaration. |
| 209 | .doc_comment => unreachable, // Top-level declaration. |
| 210 | .var_decl => unreachable, // Handled in `blockExpr`. |
| 211 | .switch_case => unreachable, // Handled in `switchExpr`. |
| 212 | .switch_else => unreachable, // Handled in `switchExpr`. |
| 213 | .range => unreachable, // Handled in `switchExpr`. |
| 215 | 214 | .Else => unreachable, // Handled explicitly the control flow expression functions. |
| 216 | 215 | .Payload => unreachable, // Handled explicitly. |
| 217 | 216 | .PointerPayload => unreachable, // Handled explicitly. |
| ... | ... | @@ -220,114 +219,113 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 220 | 219 | .FieldInitializer => unreachable, // Handled explicitly. |
| 221 | 220 | .ContainerField => unreachable, // Handled explicitly. |
| 222 | 221 | |
| 223 | | .Assign => return rvalueVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)), |
| 224 | | .AssignBitAnd => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bit_and)), |
| 225 | | .AssignBitOr => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitOr).?, .bit_or)), |
| 226 | | .AssignBitShiftLeft => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftLeft).?, .shl)), |
| 227 | | .AssignBitShiftRight => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitShiftRight).?, .shr)), |
| 228 | | .AssignBitXor => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitXor).?, .xor)), |
| 229 | | .AssignDiv => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignDiv).?, .div)), |
| 230 | | .AssignSub => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSub).?, .sub)), |
| 231 | | .AssignSubWrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignSubWrap).?, .subwrap)), |
| 232 | | .AssignMod => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMod).?, .mod_rem)), |
| 233 | | .AssignAdd => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAdd).?, .add)), |
| 234 | | .AssignAddWrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignAddWrap).?, .addwrap)), |
| 235 | | .AssignMul => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMul).?, .mul)), |
| 236 | | .AssignMulWrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignMulWrap).?, .mulwrap)), |
| 237 | | |
| 238 | | .Add => return simpleBinOp(mod, scope, rl, node.castTag(.Add).?, .add), |
| 239 | | .AddWrap => return simpleBinOp(mod, scope, rl, node.castTag(.AddWrap).?, .addwrap), |
| 240 | | .Sub => return simpleBinOp(mod, scope, rl, node.castTag(.Sub).?, .sub), |
| 241 | | .SubWrap => return simpleBinOp(mod, scope, rl, node.castTag(.SubWrap).?, .subwrap), |
| 242 | | .Mul => return simpleBinOp(mod, scope, rl, node.castTag(.Mul).?, .mul), |
| 243 | | .MulWrap => return simpleBinOp(mod, scope, rl, node.castTag(.MulWrap).?, .mulwrap), |
| 244 | | .Div => return simpleBinOp(mod, scope, rl, node.castTag(.Div).?, .div), |
| 245 | | .Mod => return simpleBinOp(mod, scope, rl, node.castTag(.Mod).?, .mod_rem), |
| 246 | | .BitAnd => return simpleBinOp(mod, scope, rl, node.castTag(.BitAnd).?, .bit_and), |
| 247 | | .BitOr => return simpleBinOp(mod, scope, rl, node.castTag(.BitOr).?, .bit_or), |
| 248 | | .BitShiftLeft => return simpleBinOp(mod, scope, rl, node.castTag(.BitShiftLeft).?, .shl), |
| 249 | | .BitShiftRight => return simpleBinOp(mod, scope, rl, node.castTag(.BitShiftRight).?, .shr), |
| 250 | | .BitXor => return simpleBinOp(mod, scope, rl, node.castTag(.BitXor).?, .xor), |
| 251 | | |
| 252 | | .BangEqual => return simpleBinOp(mod, scope, rl, node.castTag(.BangEqual).?, .cmp_neq), |
| 253 | | .EqualEqual => return simpleBinOp(mod, scope, rl, node.castTag(.EqualEqual).?, .cmp_eq), |
| 254 | | .GreaterThan => return simpleBinOp(mod, scope, rl, node.castTag(.GreaterThan).?, .cmp_gt), |
| 255 | | .GreaterOrEqual => return simpleBinOp(mod, scope, rl, node.castTag(.GreaterOrEqual).?, .cmp_gte), |
| 256 | | .LessThan => return simpleBinOp(mod, scope, rl, node.castTag(.LessThan).?, .cmp_lt), |
| 257 | | .LessOrEqual => return simpleBinOp(mod, scope, rl, node.castTag(.LessOrEqual).?, .cmp_lte), |
| 258 | | |
| 259 | | .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat), |
| 260 | | .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul), |
| 261 | | |
| 262 | | .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?), |
| 263 | | .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?), |
| 264 | | |
| 265 | | .BoolNot => return rvalue(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)), |
| 266 | | .BitNot => return rvalue(mod, scope, rl, try bitNot(mod, scope, node.castTag(.BitNot).?)), |
| 267 | | .Negation => return rvalue(mod, scope, rl, try negation(mod, scope, node.castTag(.Negation).?, .sub)), |
| 268 | | .NegationWrap => return rvalue(mod, scope, rl, try negation(mod, scope, node.castTag(.NegationWrap).?, .subwrap)), |
| 269 | | |
| 270 | | .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?), |
| 271 | | .Asm => return rvalue(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)), |
| 272 | | .StringLiteral => return rvalue(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)), |
| 273 | | .IntegerLiteral => return rvalue(mod, scope, rl, try integerLiteral(mod, scope, node.castTag(.IntegerLiteral).?)), |
| 274 | | .BuiltinCall => return builtinCall(mod, scope, rl, node.castTag(.BuiltinCall).?), |
| 275 | | .Call => return callExpr(mod, scope, rl, node.castTag(.Call).?), |
| 276 | | .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?), |
| 277 | | .Return => return ret(mod, scope, node.castTag(.Return).?), |
| 278 | | .If => return ifExpr(mod, scope, rl, node.castTag(.If).?), |
| 279 | | .While => return whileExpr(mod, scope, rl, node.castTag(.While).?), |
| 280 | | .Period => return field(mod, scope, rl, node.castTag(.Period).?), |
| 281 | | .Deref => return rvalue(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)), |
| 282 | | .AddressOf => return rvalue(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)), |
| 283 | | .FloatLiteral => return rvalue(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)), |
| 284 | | .UndefinedLiteral => return rvalue(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)), |
| 285 | | .BoolLiteral => return rvalue(mod, scope, rl, try boolLiteral(mod, scope, node.castTag(.BoolLiteral).?)), |
| 286 | | .NullLiteral => return rvalue(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)), |
| 287 | | .OptionalType => return rvalue(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)), |
| 288 | | .UnwrapOptional => return unwrapOptional(mod, scope, rl, node.castTag(.UnwrapOptional).?), |
| 289 | | .Block => return rvalueVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)), |
| 290 | | .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?, .block), |
| 291 | | .Break => return rvalue(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)), |
| 292 | | .Continue => return rvalue(mod, scope, rl, try continueExpr(mod, scope, node.castTag(.Continue).?)), |
| 293 | | .PtrType => return rvalue(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)), |
| 294 | | .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr), |
| 295 | | .ArrayType => return rvalue(mod, scope, rl, try arrayType(mod, scope, node.castTag(.ArrayType).?)), |
| 296 | | .ArrayTypeSentinel => return rvalue(mod, scope, rl, try arrayTypeSentinel(mod, scope, node.castTag(.ArrayTypeSentinel).?)), |
| 297 | | .EnumLiteral => return rvalue(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)), |
| 298 | | .MultilineStringLiteral => return rvalue(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)), |
| 299 | | .CharLiteral => return rvalue(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)), |
| 300 | | .SliceType => return rvalue(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)), |
| 301 | | .ErrorUnion => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)), |
| 302 | | .MergeErrorSets => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)), |
| 303 | | .AnyFrameType => return rvalue(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)), |
| 304 | | .ErrorSetDecl => return rvalue(mod, scope, rl, try errorSetDecl(mod, scope, node.castTag(.ErrorSetDecl).?)), |
| 305 | | .ErrorType => return rvalue(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)), |
| 306 | | .For => return forExpr(mod, scope, rl, node.castTag(.For).?), |
| 307 | | .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?), |
| 308 | | .Slice => return rvalue(mod, scope, rl, try sliceExpr(mod, scope, node.castTag(.Slice).?)), |
| 309 | | .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?), |
| 310 | | .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?), |
| 311 | | .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?), |
| 312 | | .Switch => return switchExpr(mod, scope, rl, node.castTag(.Switch).?), |
| 313 | | .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?), |
| 314 | | |
| 315 | | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), |
| 316 | | .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}), |
| 317 | | .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}), |
| 318 | | .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| 222 | .assign => return rvalueVoid(mod, scope, rl, node, try assign(mod, scope, node)), |
| 223 | .assign_bit_and => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .bit_and)), |
| 224 | .assign_bit_or => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .bit_or)), |
| 225 | .assign_bit_shift_left => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .shl)), |
| 226 | .assign_bit_shift_right => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .shr)), |
| 227 | .assign_bit_xor => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .xor)), |
| 228 | .assign_div => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .div)), |
| 229 | .assign_sub => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .sub)), |
| 230 | .assign_sub_wrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .subwrap)), |
| 231 | .assign_mod => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .mod_rem)), |
| 232 | .assign_add => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .add)), |
| 233 | .assign_add_wrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .addwrap)), |
| 234 | .assign_mul => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .mul)), |
| 235 | .assign_mul_wrap => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .mulwrap)), |
| 236 | |
| 237 | .add => return simpleBinOp(mod, scope, rl, node, .add), |
| 238 | .add_wrap => return simpleBinOp(mod, scope, rl, node, .addwrap), |
| 239 | .sub => return simpleBinOp(mod, scope, rl, node, .sub), |
| 240 | .sub_wrap => return simpleBinOp(mod, scope, rl, node, .subwrap), |
| 241 | .mul => return simpleBinOp(mod, scope, rl, node, .mul), |
| 242 | .mul_wrap => return simpleBinOp(mod, scope, rl, node, .mulwrap), |
| 243 | .div => return simpleBinOp(mod, scope, rl, node, .div), |
| 244 | .mod => return simpleBinOp(mod, scope, rl, node, .mod_rem), |
| 245 | .bit_and => return simpleBinOp(mod, scope, rl, node, .bit_and), |
| 246 | .bit_or => return simpleBinOp(mod, scope, rl, node, .bit_or), |
| 247 | .bit_shift_left => return simpleBinOp(mod, scope, rl, node, .shl), |
| 248 | .bit_shift_right => return simpleBinOp(mod, scope, rl, node, .shr), |
| 249 | .bit_xor => return simpleBinOp(mod, scope, rl, node, .xor), |
| 250 | |
| 251 | .bang_equal => return simpleBinOp(mod, scope, rl, node, .cmp_neq), |
| 252 | .equal_equal => return simpleBinOp(mod, scope, rl, node, .cmp_eq), |
| 253 | .greater_than => return simpleBinOp(mod, scope, rl, node, .cmp_gt), |
| 254 | .greater_or_equal => return simpleBinOp(mod, scope, rl, node, .cmp_gte), |
| 255 | .less_than => return simpleBinOp(mod, scope, rl, node, .cmp_lt), |
| 256 | .less_or_equal => return simpleBinOp(mod, scope, rl, node, .cmp_lte), |
| 257 | |
| 258 | .array_cat => return simpleBinOp(mod, scope, rl, node, .array_cat), |
| 259 | .array_mult => return simpleBinOp(mod, scope, rl, node, .array_mul), |
| 260 | |
| 261 | .bool_and => return boolBinOp(mod, scope, rl, node), |
| 262 | .bool_or => return boolBinOp(mod, scope, rl, node), |
| 263 | |
| 264 | .bool_not => return rvalue(mod, scope, rl, try boolNot(mod, scope, node)), |
| 265 | .bit_not => return rvalue(mod, scope, rl, try bitNot(mod, scope, node)), |
| 266 | .negation => return rvalue(mod, scope, rl, try negation(mod, scope, node, .sub)), |
| 267 | .negation_wrap => return rvalue(mod, scope, rl, try negation(mod, scope, node, .subwrap)), |
| 268 | |
| 269 | .identifier => return try identifier(mod, scope, rl, node), |
| 270 | .@"asm" => return rvalue(mod, scope, rl, try assembly(mod, scope, node)), |
| 271 | .string_literal => return rvalue(mod, scope, rl, try stringLiteral(mod, scope, node)), |
| 272 | .integer_literal => return rvalue(mod, scope, rl, try integerLiteral(mod, scope, node)), |
| 273 | .builtin_call => return builtinCall(mod, scope, rl, node), |
| 274 | .call => return callExpr(mod, scope, rl, node), |
| 275 | .@"unreachable" => return unreach(mod, scope, node), |
| 276 | .@"return" => return ret(mod, scope, node), |
| 277 | .@"if" => return ifExpr(mod, scope, rl, node), |
| 278 | .@"while" => return whileExpr(mod, scope, rl, node), |
| 279 | .period => return field(mod, scope, rl, node), |
| 280 | .deref => return rvalue(mod, scope, rl, try deref(mod, scope, node)), |
| 281 | .address_of => return rvalue(mod, scope, rl, try addressOf(mod, scope, node)), |
| 282 | .float_literal => return rvalue(mod, scope, rl, try floatLiteral(mod, scope, node)), |
| 283 | .undefined_literal => return rvalue(mod, scope, rl, try undefLiteral(mod, scope, node)), |
| 284 | .bool_literal => return rvalue(mod, scope, rl, try boolLiteral(mod, scope, node)), |
| 285 | .null_literal => return rvalue(mod, scope, rl, try nullLiteral(mod, scope, node)), |
| 286 | .optional_type => return rvalue(mod, scope, rl, try optionalType(mod, scope, node)), |
| 287 | .unwrap_optional => return unwrapOptional(mod, scope, rl, node), |
| 288 | .block => return rvalueVoid(mod, scope, rl, node, try blockExpr(mod, scope, node)), |
| 289 | .labeled_block => return labeledBlockExpr(mod, scope, rl, node, .block), |
| 290 | .@"break" => return rvalue(mod, scope, rl, try breakExpr(mod, scope, node)), |
| 291 | .@"continue" => return rvalue(mod, scope, rl, try continueExpr(mod, scope, node)), |
| 292 | .grouped_expression => return expr(mod, scope, rl, node.expr), |
| 293 | .array_type => return rvalue(mod, scope, rl, try arrayType(mod, scope, node)), |
| 294 | .array_type_sentinel => return rvalue(mod, scope, rl, try arrayTypeSentinel(mod, scope, node)), |
| 295 | .enum_literal => return rvalue(mod, scope, rl, try enumLiteral(mod, scope, node)), |
| 296 | .MultilineStringLiteral => return rvalue(mod, scope, rl, try multilineStrLiteral(mod, scope, node)), |
| 297 | .char_literal => return rvalue(mod, scope, rl, try charLiteral(mod, scope, node)), |
| 298 | .slice_type => return rvalue(mod, scope, rl, try sliceType(mod, scope, node)), |
| 299 | .error_union => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node, .error_union_type)), |
| 300 | .merge_error_sets => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node, .merge_error_sets)), |
| 301 | .anyframe_type => return rvalue(mod, scope, rl, try anyFrameType(mod, scope, node)), |
| 302 | .error_set_decl => return rvalue(mod, scope, rl, try errorSetDecl(mod, scope, node)), |
| 303 | .error_type => return rvalue(mod, scope, rl, try errorType(mod, scope, node)), |
| 304 | .@"for" => return forExpr(mod, scope, rl, node), |
| 305 | .array_access => return arrayAccess(mod, scope, rl, node), |
| 306 | .slice => return rvalue(mod, scope, rl, try sliceExpr(mod, scope, node)), |
| 307 | .@"catch" => return catchExpr(mod, scope, rl, node), |
| 308 | .@"comptime" => return comptimeKeyword(mod, scope, rl, node), |
| 309 | .@"orelse" => return orelseExpr(mod, scope, rl, node), |
| 310 | .@"switch" => return switchExpr(mod, scope, rl, node), |
| 311 | .ContainerDecl => return containerDecl(mod, scope, rl, node), |
| 312 | |
| 313 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), |
| 314 | .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}), |
| 315 | .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}), |
| 316 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| 319 | 317 | .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}), |
| 320 | 318 | .ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}), |
| 321 | 319 | .StructInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializer", .{}), |
| 322 | 320 | .StructInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializerDot", .{}), |
| 323 | | .Suspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Suspend", .{}), |
| 324 | | .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}), |
| 321 | .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}), |
| 322 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), |
| 325 | 323 | .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}), |
| 326 | | .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}), |
| 324 | .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}), |
| 327 | 325 | } |
| 328 | 326 | } |
| 329 | 327 | |
| 330 | | fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Comptime) InnerError!*zir.Inst { |
| 328 | fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.@"comptime") InnerError!*zir.Inst { |
| 331 | 329 | const tracy = trace(@src()); |
| 332 | 330 | defer tracy.end(); |
| 333 | 331 | |
| ... | ... | @@ -338,7 +336,7 @@ pub fn comptimeExpr( |
| 338 | 336 | mod: *Module, |
| 339 | 337 | parent_scope: *Scope, |
| 340 | 338 | rl: ResultLoc, |
| 341 | | node: *ast.Node, |
| 339 | node: ast.Node.Index, |
| 342 | 340 | ) InnerError!*zir.Inst { |
| 343 | 341 | // If we are already in a comptime scope, no need to make another one. |
| 344 | 342 | if (parent_scope.isComptime()) { |
| ... | ... | @@ -347,7 +345,7 @@ pub fn comptimeExpr( |
| 347 | 345 | |
| 348 | 346 | // Optimization for labeled blocks: don't need to have 2 layers of blocks, |
| 349 | 347 | // we can reuse the existing one. |
| 350 | | if (node.castTag(.LabeledBlock)) |block_node| { |
| 348 | if (node.castTag(.labeled_block)) |block_node| { |
| 351 | 349 | return labeledBlockExpr(mod, parent_scope, rl, block_node, .block_comptime); |
| 352 | 350 | } |
| 353 | 351 | |
| ... | ... | @@ -366,6 +364,8 @@ pub fn comptimeExpr( |
| 366 | 364 | _ = try expr(mod, &block_scope.base, rl, node); |
| 367 | 365 | |
| 368 | 366 | const tree = parent_scope.tree(); |
| 367 | const node_datas = tree.nodes.items(.data); |
| 368 | const main_tokens = tree.nodes.items(.main_token); |
| 369 | 369 | const src = tree.token_locs[node.firstToken()].start; |
| 370 | 370 | |
| 371 | 371 | const block = try addZIRInstBlock(mod, parent_scope, src, .block_comptime_flat, .{ |
| ... | ... | @@ -381,6 +381,8 @@ fn breakExpr( |
| 381 | 381 | node: *ast.Node.ControlFlowExpression, |
| 382 | 382 | ) InnerError!*zir.Inst { |
| 383 | 383 | const tree = parent_scope.tree(); |
| 384 | const node_datas = tree.nodes.items(.data); |
| 385 | const main_tokens = tree.nodes.items(.main_token); |
| 384 | 386 | const src = tree.token_locs[node.ltoken].start; |
| 385 | 387 | |
| 386 | 388 | // Look for the label in the scope. |
| ... | ... | @@ -445,6 +447,8 @@ fn breakExpr( |
| 445 | 447 | |
| 446 | 448 | fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst { |
| 447 | 449 | const tree = parent_scope.tree(); |
| 450 | const node_datas = tree.nodes.items(.data); |
| 451 | const main_tokens = tree.nodes.items(.main_token); |
| 448 | 452 | const src = tree.token_locs[node.ltoken].start; |
| 449 | 453 | |
| 450 | 454 | // Look for the label in the scope. |
| ... | ... | @@ -485,7 +489,7 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowE |
| 485 | 489 | } |
| 486 | 490 | } |
| 487 | 491 | |
| 488 | | pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block) InnerError!void { |
| 492 | pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.block) InnerError!void { |
| 489 | 493 | const tracy = trace(@src()); |
| 490 | 494 | defer tracy.end(); |
| 491 | 495 | |
| ... | ... | @@ -502,6 +506,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn |
| 502 | 506 | if (gen_zir.label) |prev_label| { |
| 503 | 507 | if (try tokenIdentEql(mod, parent_scope, label, prev_label.token)) { |
| 504 | 508 | const tree = parent_scope.tree(); |
| 509 | const node_datas = tree.nodes.items(.data); |
| 510 | const main_tokens = tree.nodes.items(.main_token); |
| 505 | 511 | const label_src = tree.token_locs[label].start; |
| 506 | 512 | const prev_label_src = tree.token_locs[prev_label.token].start; |
| 507 | 513 | |
| ... | ... | @@ -539,7 +545,7 @@ fn labeledBlockExpr( |
| 539 | 545 | mod: *Module, |
| 540 | 546 | parent_scope: *Scope, |
| 541 | 547 | rl: ResultLoc, |
| 542 | | block_node: *ast.Node.LabeledBlock, |
| 548 | block_node: *ast.Node.labeled_block, |
| 543 | 549 | zir_tag: zir.Inst.Tag, |
| 544 | 550 | ) InnerError!*zir.Inst { |
| 545 | 551 | const tracy = trace(@src()); |
| ... | ... | @@ -548,6 +554,8 @@ fn labeledBlockExpr( |
| 548 | 554 | assert(zir_tag == .block or zir_tag == .block_comptime); |
| 549 | 555 | |
| 550 | 556 | const tree = parent_scope.tree(); |
| 557 | const node_datas = tree.nodes.items(.data); |
| 558 | const main_tokens = tree.nodes.items(.main_token); |
| 551 | 559 | const src = tree.token_locs[block_node.lbrace].start; |
| 552 | 560 | |
| 553 | 561 | try checkLabelRedefinition(mod, parent_scope, block_node.label); |
| ... | ... | @@ -627,10 +635,12 @@ fn labeledBlockExpr( |
| 627 | 635 | fn blockExprStmts( |
| 628 | 636 | mod: *Module, |
| 629 | 637 | parent_scope: *Scope, |
| 630 | | node: *ast.Node, |
| 631 | | statements: []*ast.Node, |
| 638 | node: ast.Node.Index, |
| 639 | statements: []const ast.Node.Index, |
| 632 | 640 | ) !void { |
| 633 | 641 | const tree = parent_scope.tree(); |
| 642 | const node_datas = tree.nodes.items(.data); |
| 643 | const main_tokens = tree.nodes.items(.main_token); |
| 634 | 644 | |
| 635 | 645 | var block_arena = std.heap.ArenaAllocator.init(mod.gpa); |
| 636 | 646 | defer block_arena.deinit(); |
| ... | ... | @@ -640,24 +650,24 @@ fn blockExprStmts( |
| 640 | 650 | const src = tree.token_locs[statement.firstToken()].start; |
| 641 | 651 | _ = try addZIRNoOp(mod, scope, src, .dbg_stmt); |
| 642 | 652 | switch (statement.tag) { |
| 643 | | .VarDecl => { |
| 644 | | const var_decl_node = statement.castTag(.VarDecl).?; |
| 653 | .var_decl => { |
| 654 | const var_decl_node = statement.castTag(.var_decl).?; |
| 645 | 655 | scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator); |
| 646 | 656 | }, |
| 647 | | .Assign => try assign(mod, scope, statement.castTag(.Assign).?), |
| 648 | | .AssignBitAnd => try assignOp(mod, scope, statement.castTag(.AssignBitAnd).?, .bit_and), |
| 649 | | .AssignBitOr => try assignOp(mod, scope, statement.castTag(.AssignBitOr).?, .bit_or), |
| 650 | | .AssignBitShiftLeft => try assignOp(mod, scope, statement.castTag(.AssignBitShiftLeft).?, .shl), |
| 651 | | .AssignBitShiftRight => try assignOp(mod, scope, statement.castTag(.AssignBitShiftRight).?, .shr), |
| 652 | | .AssignBitXor => try assignOp(mod, scope, statement.castTag(.AssignBitXor).?, .xor), |
| 653 | | .AssignDiv => try assignOp(mod, scope, statement.castTag(.AssignDiv).?, .div), |
| 654 | | .AssignSub => try assignOp(mod, scope, statement.castTag(.AssignSub).?, .sub), |
| 655 | | .AssignSubWrap => try assignOp(mod, scope, statement.castTag(.AssignSubWrap).?, .subwrap), |
| 656 | | .AssignMod => try assignOp(mod, scope, statement.castTag(.AssignMod).?, .mod_rem), |
| 657 | | .AssignAdd => try assignOp(mod, scope, statement.castTag(.AssignAdd).?, .add), |
| 658 | | .AssignAddWrap => try assignOp(mod, scope, statement.castTag(.AssignAddWrap).?, .addwrap), |
| 659 | | .AssignMul => try assignOp(mod, scope, statement.castTag(.AssignMul).?, .mul), |
| 660 | | .AssignMulWrap => try assignOp(mod, scope, statement.castTag(.AssignMulWrap).?, .mulwrap), |
| 657 | .assign => try assign(mod, scope, statement), |
| 658 | .assign_bit_and => try assignOp(mod, scope, statement, .bit_and), |
| 659 | .assign_bit_or => try assignOp(mod, scope, statement, .bit_or), |
| 660 | .assign_bit_shift_left => try assignOp(mod, scope, statement, .shl), |
| 661 | .assign_bit_shift_right => try assignOp(mod, scope, statement, .shr), |
| 662 | .assign_bit_xor => try assignOp(mod, scope, statement, .xor), |
| 663 | .assign_div => try assignOp(mod, scope, statement, .div), |
| 664 | .assign_sub => try assignOp(mod, scope, statement, .sub), |
| 665 | .assign_sub_wrap => try assignOp(mod, scope, statement, .subwrap), |
| 666 | .assign_mod => try assignOp(mod, scope, statement, .mod_rem), |
| 667 | .assign_add => try assignOp(mod, scope, statement, .add), |
| 668 | .assign_add_wrap => try assignOp(mod, scope, statement, .addwrap), |
| 669 | .assign_mul => try assignOp(mod, scope, statement, .mul), |
| 670 | .assign_mul_wrap => try assignOp(mod, scope, statement, .mulwrap), |
| 661 | 671 | |
| 662 | 672 | else => { |
| 663 | 673 | const possibly_unused_result = try expr(mod, scope, .none, statement); |
| ... | ... | @@ -672,7 +682,7 @@ fn blockExprStmts( |
| 672 | 682 | fn varDecl( |
| 673 | 683 | mod: *Module, |
| 674 | 684 | scope: *Scope, |
| 675 | | node: *ast.Node.VarDecl, |
| 685 | node: *ast.Node.var_decl, |
| 676 | 686 | block_arena: *Allocator, |
| 677 | 687 | ) InnerError!*Scope { |
| 678 | 688 | if (node.getComptimeToken()) |comptime_token| { |
| ... | ... | @@ -682,6 +692,8 @@ fn varDecl( |
| 682 | 692 | return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{}); |
| 683 | 693 | } |
| 684 | 694 | const tree = scope.tree(); |
| 695 | const node_datas = tree.nodes.items(.data); |
| 696 | const main_tokens = tree.nodes.items(.main_token); |
| 685 | 697 | const name_src = tree.token_locs[node.name_token].start; |
| 686 | 698 | const ident_name = try mod.identifierTokenString(scope, node.name_token); |
| 687 | 699 | |
| ... | ... | @@ -733,7 +745,7 @@ fn varDecl( |
| 733 | 745 | return mod.fail(scope, name_src, "variables must be initialized", .{}); |
| 734 | 746 | |
| 735 | 747 | switch (tree.token_ids[node.mut_token]) { |
| 736 | | .Keyword_const => { |
| 748 | .keyword_const => { |
| 737 | 749 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 738 | 750 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 739 | 751 | // the variable, no memory location needed. |
| ... | ... | @@ -834,7 +846,7 @@ fn varDecl( |
| 834 | 846 | }; |
| 835 | 847 | return &sub_scope.base; |
| 836 | 848 | }, |
| 837 | | .Keyword_var => { |
| 849 | .keyword_var => { |
| 838 | 850 | var resolve_inferred_alloc: ?*zir.Inst = null; |
| 839 | 851 | const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTypeNode()) |type_node| a: { |
| 840 | 852 | const type_inst = try typeExpr(mod, scope, type_node); |
| ... | ... | @@ -862,33 +874,39 @@ fn varDecl( |
| 862 | 874 | } |
| 863 | 875 | } |
| 864 | 876 | |
| 865 | | fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!void { |
| 866 | | if (infix_node.lhs.castTag(.Identifier)) |ident| { |
| 867 | | // This intentionally does not support @"_" syntax. |
| 868 | | const ident_name = scope.tree().tokenSlice(ident.token); |
| 877 | fn assign(mod: *Module, scope: *Scope, infix_node: ast.Node.Index) InnerError!void { |
| 878 | const tree = scope.tree(); |
| 879 | const node_datas = tree.nodes.items(.data); |
| 880 | const main_tokens = tree.nodes.items(.main_token); |
| 881 | const lhs = node_datas[infix_node].lhs; |
| 882 | const rhs = node_datas[infix_node].rhs; |
| 883 | if (node_tags[lhs] == .identifier) { |
| 884 | // This intentionally does not support `@"_"` syntax. |
| 885 | const ident_name = tree.tokenSlice(main_tokens[lhs]); |
| 869 | 886 | if (mem.eql(u8, ident_name, "_")) { |
| 870 | 887 | _ = try expr(mod, scope, .discard, infix_node.rhs); |
| 871 | 888 | return; |
| 872 | 889 | } |
| 873 | 890 | } |
| 874 | | const lvalue = try lvalExpr(mod, scope, infix_node.lhs); |
| 875 | | _ = try expr(mod, scope, .{ .ptr = lvalue }, infix_node.rhs); |
| 891 | const lvalue = try lvalExpr(mod, scope, lhs); |
| 892 | _ = try expr(mod, scope, .{ .ptr = lvalue }, rhs); |
| 876 | 893 | } |
| 877 | 894 | |
| 878 | 895 | fn assignOp( |
| 879 | 896 | mod: *Module, |
| 880 | 897 | scope: *Scope, |
| 881 | | infix_node: *ast.Node.SimpleInfixOp, |
| 898 | infix_node: ast.Node.Index, |
| 882 | 899 | op_inst_tag: zir.Inst.Tag, |
| 883 | 900 | ) InnerError!void { |
| 884 | | const lhs_ptr = try lvalExpr(mod, scope, infix_node.lhs); |
| 885 | | const lhs = try addZIRUnOp(mod, scope, lhs_ptr.src, .deref, lhs_ptr); |
| 886 | | const lhs_type = try addZIRUnOp(mod, scope, lhs_ptr.src, .typeof, lhs); |
| 887 | | const rhs = try expr(mod, scope, .{ .ty = lhs_type }, infix_node.rhs); |
| 888 | | |
| 889 | 901 | const tree = scope.tree(); |
| 890 | | const src = tree.token_locs[infix_node.op_token].start; |
| 902 | const node_datas = tree.nodes.items(.data); |
| 903 | const main_tokens = tree.nodes.items(.main_token); |
| 891 | 904 | |
| 905 | const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs); |
| 906 | const lhs = try addZIRUnOp(mod, scope, lhs_ptr.src, .deref, lhs_ptr); |
| 907 | const lhs_type = try addZIRUnOp(mod, scope, lhs_ptr.src, .typeof, lhs); |
| 908 | const rhs = try expr(mod, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs); |
| 909 | const src = token_starts[main_tokens[infix_node]]; |
| 892 | 910 | const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs); |
| 893 | 911 | _ = try addZIRBinOp(mod, scope, src, .store, lhs_ptr, result); |
| 894 | 912 | } |
| ... | ... | @@ -935,7 +953,7 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn |
| 935 | 953 | return addZIRUnOp(mod, scope, src, .optional_type, operand); |
| 936 | 954 | } |
| 937 | 955 | |
| 938 | | fn sliceType(mod: *Module, scope: *Scope, node: *ast.Node.SliceType) InnerError!*zir.Inst { |
| 956 | fn sliceType(mod: *Module, scope: *Scope, node: *ast.Node.slice_type) InnerError!*zir.Inst { |
| 939 | 957 | const tree = scope.tree(); |
| 940 | 958 | const src = tree.token_locs[node.op_token].start; |
| 941 | 959 | return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, .Slice); |
| ... | ... | @@ -948,7 +966,7 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir |
| 948 | 966 | .Asterisk, .AsteriskAsterisk => .One, |
| 949 | 967 | // TODO stage1 type inference bug |
| 950 | 968 | .LBracket => @as(std.builtin.TypeInfo.Pointer.Size, switch (tree.token_ids[node.op_token + 2]) { |
| 951 | | .Identifier => .C, |
| 969 | .identifier => .C, |
| 952 | 970 | else => .Many, |
| 953 | 971 | }), |
| 954 | 972 | else => unreachable, |
| ... | ... | @@ -998,7 +1016,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, |
| 998 | 1016 | return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); |
| 999 | 1017 | } |
| 1000 | 1018 | |
| 1001 | | fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst { |
| 1019 | fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.array_type) !*zir.Inst { |
| 1002 | 1020 | const tree = scope.tree(); |
| 1003 | 1021 | const src = tree.token_locs[node.op_token].start; |
| 1004 | 1022 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | ... | @@ -1013,7 +1031,7 @@ fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst |
| 1013 | 1031 | return addZIRBinOp(mod, scope, src, .array_type, len, elem_type); |
| 1014 | 1032 | } |
| 1015 | 1033 | |
| 1016 | | fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst { |
| 1034 | fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.array_type_sentinel) !*zir.Inst { |
| 1017 | 1035 | const tree = scope.tree(); |
| 1018 | 1036 | const src = tree.token_locs[node.op_token].start; |
| 1019 | 1037 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | ... | @@ -1034,7 +1052,7 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSenti |
| 1034 | 1052 | }, .{}); |
| 1035 | 1053 | } |
| 1036 | 1054 | |
| 1037 | | fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) InnerError!*zir.Inst { |
| 1055 | fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.anyframe_type) InnerError!*zir.Inst { |
| 1038 | 1056 | const tree = scope.tree(); |
| 1039 | 1057 | const src = tree.token_locs[node.anyframe_token].start; |
| 1040 | 1058 | if (node.result) |some| { |
| ... | ... | @@ -1056,7 +1074,7 @@ fn typeInixOp(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp, op_ins |
| 1056 | 1074 | return addZIRBinOp(mod, scope, src, op_inst_tag, error_set, payload); |
| 1057 | 1075 | } |
| 1058 | 1076 | |
| 1059 | | fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.EnumLiteral) !*zir.Inst { |
| 1077 | fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.enum_literal) !*zir.Inst { |
| 1060 | 1078 | const tree = scope.tree(); |
| 1061 | 1079 | const src = tree.token_locs[node.name].start; |
| 1062 | 1080 | const name = try mod.identifierTokenString(scope, node.name); |
| ... | ... | @@ -1141,13 +1159,13 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1141 | 1159 | |
| 1142 | 1160 | var layout: std.builtin.TypeInfo.ContainerLayout = .Auto; |
| 1143 | 1161 | if (node.layout_token) |some| switch (tree.token_ids[some]) { |
| 1144 | | .Keyword_extern => layout = .Extern, |
| 1145 | | .Keyword_packed => layout = .Packed, |
| 1162 | .keyword_extern => layout = .Extern, |
| 1163 | .keyword_packed => layout = .Packed, |
| 1146 | 1164 | else => unreachable, |
| 1147 | 1165 | }; |
| 1148 | 1166 | |
| 1149 | 1167 | const container_type = switch (tree.token_ids[node.kind_token]) { |
| 1150 | | .Keyword_enum => blk: { |
| 1168 | .keyword_enum => blk: { |
| 1151 | 1169 | const tag_type: ?*zir.Inst = switch (node.init_arg_expr) { |
| 1152 | 1170 | .Type => |t| try typeExpr(mod, &gen_scope.base, t), |
| 1153 | 1171 | .None => null, |
| ... | ... | @@ -1174,7 +1192,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1174 | 1192 | }; |
| 1175 | 1193 | break :blk Type.initPayload(&enum_type.base); |
| 1176 | 1194 | }, |
| 1177 | | .Keyword_struct => blk: { |
| 1195 | .keyword_struct => blk: { |
| 1178 | 1196 | assert(node.init_arg_expr == .None); |
| 1179 | 1197 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{ |
| 1180 | 1198 | .fields = try arena.dupe(*zir.Inst, fields.items), |
| ... | ... | @@ -1196,7 +1214,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1196 | 1214 | }; |
| 1197 | 1215 | break :blk Type.initPayload(&struct_type.base); |
| 1198 | 1216 | }, |
| 1199 | | .Keyword_union => blk: { |
| 1217 | .keyword_union => blk: { |
| 1200 | 1218 | const init_inst = switch (node.init_arg_expr) { |
| 1201 | 1219 | .Enum => |e| if (e) |t| try typeExpr(mod, &gen_scope.base, t) else null, |
| 1202 | 1220 | .None => null, |
| ... | ... | @@ -1229,7 +1247,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1229 | 1247 | }; |
| 1230 | 1248 | break :blk Type.initPayload(&union_type.base); |
| 1231 | 1249 | }, |
| 1232 | | .Keyword_opaque => blk: { |
| 1250 | .keyword_opaque => blk: { |
| 1233 | 1251 | if (fields.items.len > 0) { |
| 1234 | 1252 | return mod.fail(scope, fields.items[0].src, "opaque types cannot have fields", .{}); |
| 1235 | 1253 | } |
| ... | ... | @@ -1258,7 +1276,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1258 | 1276 | } |
| 1259 | 1277 | } |
| 1260 | 1278 | |
| 1261 | | fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst { |
| 1279 | fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.error_set_decl) InnerError!*zir.Inst { |
| 1262 | 1280 | const tree = scope.tree(); |
| 1263 | 1281 | const src = tree.token_locs[node.error_token].start; |
| 1264 | 1282 | const decls = node.decls(); |
| ... | ... | @@ -1281,7 +1299,7 @@ fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!* |
| 1281 | 1299 | }); |
| 1282 | 1300 | } |
| 1283 | 1301 | |
| 1284 | | fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Catch) InnerError!*zir.Inst { |
| 1302 | fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.@"catch") InnerError!*zir.Inst { |
| 1285 | 1303 | switch (rl) { |
| 1286 | 1304 | .ref => return orelseCatchExpr( |
| 1287 | 1305 | mod, |
| ... | ... | @@ -1528,7 +1546,7 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleI |
| 1528 | 1546 | const tree = scope.tree(); |
| 1529 | 1547 | const src = tree.token_locs[node.op_token].start; |
| 1530 | 1548 | // TODO custom AST node for field access so that we don't have to go through a node cast here |
| 1531 | | const field_name = try mod.identifierTokenString(scope, node.rhs.castTag(.Identifier).?.token); |
| 1549 | const field_name = try mod.identifierTokenString(scope, node.rhs.castTag(.identifier).?.token); |
| 1532 | 1550 | if (rl == .ref) { |
| 1533 | 1551 | return addZirInstTag(mod, scope, src, .field_ptr, .{ |
| 1534 | 1552 | .object = try expr(mod, scope, .ref, node.lhs), |
| ... | ... | @@ -1545,7 +1563,7 @@ fn namedField( |
| 1545 | 1563 | mod: *Module, |
| 1546 | 1564 | scope: *Scope, |
| 1547 | 1565 | rl: ResultLoc, |
| 1548 | | call: *ast.Node.BuiltinCall, |
| 1566 | call: *ast.Node.builtin_call, |
| 1549 | 1567 | ) InnerError!*zir.Inst { |
| 1550 | 1568 | try ensureBuiltinParamCount(mod, scope, call, 2); |
| 1551 | 1569 | |
| ... | ... | @@ -1571,7 +1589,7 @@ fn namedField( |
| 1571 | 1589 | })); |
| 1572 | 1590 | } |
| 1573 | 1591 | |
| 1574 | | fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ArrayAccess) InnerError!*zir.Inst { |
| 1592 | fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.array_access) InnerError!*zir.Inst { |
| 1575 | 1593 | const tree = scope.tree(); |
| 1576 | 1594 | const src = tree.token_locs[node.rtoken].start; |
| 1577 | 1595 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | ... | @@ -1592,7 +1610,7 @@ fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Array |
| 1592 | 1610 | })); |
| 1593 | 1611 | } |
| 1594 | 1612 | |
| 1595 | | fn sliceExpr(mod: *Module, scope: *Scope, node: *ast.Node.Slice) InnerError!*zir.Inst { |
| 1613 | fn sliceExpr(mod: *Module, scope: *Scope, node: *ast.Node.slice) InnerError!*zir.Inst { |
| 1596 | 1614 | const tree = scope.tree(); |
| 1597 | 1615 | const src = tree.token_locs[node.rtoken].start; |
| 1598 | 1616 | |
| ... | ... | @@ -1633,15 +1651,16 @@ fn simpleBinOp( |
| 1633 | 1651 | mod: *Module, |
| 1634 | 1652 | scope: *Scope, |
| 1635 | 1653 | rl: ResultLoc, |
| 1636 | | infix_node: *ast.Node.SimpleInfixOp, |
| 1654 | infix_node: ast.Node.Index, |
| 1637 | 1655 | op_inst_tag: zir.Inst.Tag, |
| 1638 | 1656 | ) InnerError!*zir.Inst { |
| 1639 | 1657 | const tree = scope.tree(); |
| 1640 | | const src = tree.token_locs[infix_node.op_token].start; |
| 1641 | | |
| 1642 | | const lhs = try expr(mod, scope, .none, infix_node.lhs); |
| 1643 | | const rhs = try expr(mod, scope, .none, infix_node.rhs); |
| 1658 | const node_datas = tree.nodes.items(.data); |
| 1659 | const main_tokens = tree.nodes.items(.main_token); |
| 1644 | 1660 | |
| 1661 | const lhs = try expr(mod, scope, .none, node_datas[infix_node].lhs); |
| 1662 | const rhs = try expr(mod, scope, .none, node_datas[infix_node].rhs); |
| 1663 | const src = token_starts[main_tokens[infix_node]]; |
| 1645 | 1664 | const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs); |
| 1646 | 1665 | return rvalue(mod, scope, rl, result); |
| 1647 | 1666 | } |
| ... | ... | @@ -1653,6 +1672,9 @@ fn boolBinOp( |
| 1653 | 1672 | infix_node: *ast.Node.SimpleInfixOp, |
| 1654 | 1673 | ) InnerError!*zir.Inst { |
| 1655 | 1674 | const tree = scope.tree(); |
| 1675 | const node_datas = tree.nodes.items(.data); |
| 1676 | const main_tokens = tree.nodes.items(.main_token); |
| 1677 | |
| 1656 | 1678 | const src = tree.token_locs[infix_node.op_token].start; |
| 1657 | 1679 | const bool_type = try addZIRInstConst(mod, scope, src, .{ |
| 1658 | 1680 | .ty = Type.initTag(.type), |
| ... | ... | @@ -1703,7 +1725,7 @@ fn boolBinOp( |
| 1703 | 1725 | }; |
| 1704 | 1726 | defer const_scope.instructions.deinit(mod.gpa); |
| 1705 | 1727 | |
| 1706 | | const is_bool_and = infix_node.base.tag == .BoolAnd; |
| 1728 | const is_bool_and = infix_node.base.tag == .bool_and; |
| 1707 | 1729 | _ = try addZIRInst(mod, &const_scope.base, src, zir.Inst.Break, .{ |
| 1708 | 1730 | .block = block, |
| 1709 | 1731 | .operand = try addZIRInstConst(mod, &const_scope.base, src, .{ |
| ... | ... | @@ -1769,7 +1791,7 @@ const CondKind = union(enum) { |
| 1769 | 1791 | return &then_scope.base; |
| 1770 | 1792 | }; |
| 1771 | 1793 | const is_ptr = payload.ptr_token != null; |
| 1772 | | const ident_node = payload.value_symbol.castTag(.Identifier).?; |
| 1794 | const ident_node = payload.value_symbol.castTag(.identifier).?; |
| 1773 | 1795 | |
| 1774 | 1796 | // This intentionally does not support @"_" syntax. |
| 1775 | 1797 | const ident_name = then_scope.base.tree().tokenSlice(ident_node.token); |
| ... | ... | @@ -1788,7 +1810,7 @@ const CondKind = union(enum) { |
| 1788 | 1810 | const payload_ptr = try addZIRUnOp(mod, &else_scope.base, src, .err_union_payload_unsafe_ptr, self.err_union.?); |
| 1789 | 1811 | |
| 1790 | 1812 | const payload = payload_node.?.castTag(.Payload).?; |
| 1791 | | const ident_node = payload.error_symbol.castTag(.Identifier).?; |
| 1813 | const ident_node = payload.error_symbol.castTag(.identifier).?; |
| 1792 | 1814 | |
| 1793 | 1815 | // This intentionally does not support @"_" syntax. |
| 1794 | 1816 | const ident_name = else_scope.base.tree().tokenSlice(ident_node.token); |
| ... | ... | @@ -1800,7 +1822,7 @@ const CondKind = union(enum) { |
| 1800 | 1822 | } |
| 1801 | 1823 | }; |
| 1802 | 1824 | |
| 1803 | | fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) InnerError!*zir.Inst { |
| 1825 | fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.@"if") InnerError!*zir.Inst { |
| 1804 | 1826 | var cond_kind: CondKind = .bool; |
| 1805 | 1827 | if (if_node.payload) |_| cond_kind = .{ .optional = null }; |
| 1806 | 1828 | if (if_node.@"else") |else_node| { |
| ... | ... | @@ -1819,6 +1841,8 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 1819 | 1841 | defer block_scope.instructions.deinit(mod.gpa); |
| 1820 | 1842 | |
| 1821 | 1843 | const tree = scope.tree(); |
| 1844 | const node_datas = tree.nodes.items(.data); |
| 1845 | const main_tokens = tree.nodes.items(.main_token); |
| 1822 | 1846 | const if_src = tree.token_locs[if_node.if_token].start; |
| 1823 | 1847 | const cond = try cond_kind.cond(mod, &block_scope, if_src, if_node.condition); |
| 1824 | 1848 | |
| ... | ... | @@ -1918,7 +1942,7 @@ fn whileExpr( |
| 1918 | 1942 | mod: *Module, |
| 1919 | 1943 | scope: *Scope, |
| 1920 | 1944 | rl: ResultLoc, |
| 1921 | | while_node: *ast.Node.While, |
| 1945 | while_node: *ast.Node.@"while", |
| 1922 | 1946 | ) InnerError!*zir.Inst { |
| 1923 | 1947 | var cond_kind: CondKind = .bool; |
| 1924 | 1948 | if (while_node.payload) |_| cond_kind = .{ .optional = null }; |
| ... | ... | @@ -1955,6 +1979,8 @@ fn whileExpr( |
| 1955 | 1979 | defer continue_scope.instructions.deinit(mod.gpa); |
| 1956 | 1980 | |
| 1957 | 1981 | const tree = scope.tree(); |
| 1982 | const node_datas = tree.nodes.items(.data); |
| 1983 | const main_tokens = tree.nodes.items(.main_token); |
| 1958 | 1984 | const while_src = tree.token_locs[while_node.while_token].start; |
| 1959 | 1985 | const void_type = try addZIRInstConst(mod, scope, while_src, .{ |
| 1960 | 1986 | .ty = Type.initTag(.type), |
| ... | ... | @@ -2066,7 +2092,7 @@ fn forExpr( |
| 2066 | 2092 | mod: *Module, |
| 2067 | 2093 | scope: *Scope, |
| 2068 | 2094 | rl: ResultLoc, |
| 2069 | | for_node: *ast.Node.For, |
| 2095 | for_node: *ast.Node.@"for", |
| 2070 | 2096 | ) InnerError!*zir.Inst { |
| 2071 | 2097 | if (for_node.label) |label| { |
| 2072 | 2098 | try checkLabelRedefinition(mod, scope, label); |
| ... | ... | @@ -2077,6 +2103,8 @@ fn forExpr( |
| 2077 | 2103 | |
| 2078 | 2104 | // setup variables and constants |
| 2079 | 2105 | const tree = scope.tree(); |
| 2106 | const node_datas = tree.nodes.items(.data); |
| 2107 | const main_tokens = tree.nodes.items(.main_token); |
| 2080 | 2108 | const for_src = tree.token_locs[for_node.for_token].start; |
| 2081 | 2109 | const index_ptr = blk: { |
| 2082 | 2110 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ |
| ... | ... | @@ -2246,9 +2274,9 @@ fn forExpr( |
| 2246 | 2274 | ); |
| 2247 | 2275 | } |
| 2248 | 2276 | |
| 2249 | | fn switchCaseUsesRef(node: *ast.Node.Switch) bool { |
| 2277 | fn switchCaseUsesRef(node: *ast.Node.@"switch") bool { |
| 2250 | 2278 | for (node.cases()) |uncasted_case| { |
| 2251 | | const case = uncasted_case.castTag(.SwitchCase).?; |
| 2279 | const case = uncasted_case.castTag(.switch_case).?; |
| 2252 | 2280 | const uncasted_payload = case.payload orelse continue; |
| 2253 | 2281 | const payload = uncasted_payload.castTag(.PointerPayload).?; |
| 2254 | 2282 | if (payload.ptr_token) |_| return true; |
| ... | ... | @@ -2260,15 +2288,17 @@ fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp { |
| 2260 | 2288 | var cur = node; |
| 2261 | 2289 | while (true) { |
| 2262 | 2290 | switch (cur.tag) { |
| 2263 | | .Range => return @fieldParentPtr(ast.Node.SimpleInfixOp, "base", cur), |
| 2264 | | .GroupedExpression => cur = @fieldParentPtr(ast.Node.GroupedExpression, "base", cur).expr, |
| 2291 | .range => return @fieldParentPtr(ast.Node.SimpleInfixOp, "base", cur), |
| 2292 | .grouped_expression => cur = @fieldParentPtr(ast.Node.grouped_expression, "base", cur).expr, |
| 2265 | 2293 | else => return null, |
| 2266 | 2294 | } |
| 2267 | 2295 | } |
| 2268 | 2296 | } |
| 2269 | 2297 | |
| 2270 | | fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node.Switch) InnerError!*zir.Inst { |
| 2298 | fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node.@"switch") InnerError!*zir.Inst { |
| 2271 | 2299 | const tree = scope.tree(); |
| 2300 | const node_datas = tree.nodes.items(.data); |
| 2301 | const main_tokens = tree.nodes.items(.main_token); |
| 2272 | 2302 | const switch_src = tree.token_locs[switch_node.switch_token].start; |
| 2273 | 2303 | const use_ref = switchCaseUsesRef(switch_node); |
| 2274 | 2304 | |
| ... | ... | @@ -2291,12 +2321,12 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2291 | 2321 | var first_range: ?*zir.Inst = null; |
| 2292 | 2322 | var simple_case_count: usize = 0; |
| 2293 | 2323 | for (switch_node.cases()) |uncasted_case| { |
| 2294 | | const case = uncasted_case.castTag(.SwitchCase).?; |
| 2324 | const case = uncasted_case.castTag(.switch_case).?; |
| 2295 | 2325 | const case_src = tree.token_locs[case.firstToken()].start; |
| 2296 | 2326 | assert(case.items_len != 0); |
| 2297 | 2327 | |
| 2298 | 2328 | // Check for else/_ prong, those are handled last. |
| 2299 | | if (case.items_len == 1 and case.items()[0].tag == .SwitchElse) { |
| 2329 | if (case.items_len == 1 and case.items()[0].tag == .switch_else) { |
| 2300 | 2330 | if (else_src) |src| { |
| 2301 | 2331 | const msg = msg: { |
| 2302 | 2332 | const msg = try mod.errMsg( |
| ... | ... | @@ -2313,7 +2343,7 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2313 | 2343 | } |
| 2314 | 2344 | else_src = case_src; |
| 2315 | 2345 | continue; |
| 2316 | | } else if (case.items_len == 1 and case.items()[0].tag == .Identifier and |
| 2346 | } else if (case.items_len == 1 and case.items()[0].tag == .identifier and |
| 2317 | 2347 | mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_")) |
| 2318 | 2348 | { |
| 2319 | 2349 | if (underscore_src) |src| { |
| ... | ... | @@ -2412,20 +2442,20 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2412 | 2442 | defer else_scope.instructions.deinit(mod.gpa); |
| 2413 | 2443 | |
| 2414 | 2444 | // Now generate all but the special cases |
| 2415 | | var special_case: ?*ast.Node.SwitchCase = null; |
| 2445 | var special_case: ?*ast.Node.switch_case = null; |
| 2416 | 2446 | var items_index: usize = 0; |
| 2417 | 2447 | var case_index: usize = 0; |
| 2418 | 2448 | for (switch_node.cases()) |uncasted_case| { |
| 2419 | | const case = uncasted_case.castTag(.SwitchCase).?; |
| 2449 | const case = uncasted_case.castTag(.switch_case).?; |
| 2420 | 2450 | const case_src = tree.token_locs[case.firstToken()].start; |
| 2421 | 2451 | // reset without freeing to reduce allocations. |
| 2422 | 2452 | case_scope.instructions.items.len = 0; |
| 2423 | 2453 | |
| 2424 | 2454 | // Check for else/_ prong, those are handled last. |
| 2425 | | if (case.items_len == 1 and case.items()[0].tag == .SwitchElse) { |
| 2455 | if (case.items_len == 1 and case.items()[0].tag == .switch_else) { |
| 2426 | 2456 | special_case = case; |
| 2427 | 2457 | continue; |
| 2428 | | } else if (case.items_len == 1 and case.items()[0].tag == .Identifier and |
| 2458 | } else if (case.items_len == 1 and case.items()[0].tag == .identifier and |
| 2429 | 2459 | mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_")) |
| 2430 | 2460 | { |
| 2431 | 2461 | special_case = case; |
| ... | ... | @@ -2528,11 +2558,13 @@ fn switchCaseExpr( |
| 2528 | 2558 | scope: *Scope, |
| 2529 | 2559 | rl: ResultLoc, |
| 2530 | 2560 | block: *zir.Inst.Block, |
| 2531 | | case: *ast.Node.SwitchCase, |
| 2561 | case: *ast.Node.switch_case, |
| 2532 | 2562 | target: *zir.Inst, |
| 2533 | 2563 | target_ptr: ?*zir.Inst, |
| 2534 | 2564 | ) !void { |
| 2535 | 2565 | const tree = scope.tree(); |
| 2566 | const node_datas = tree.nodes.items(.data); |
| 2567 | const main_tokens = tree.nodes.items(.main_token); |
| 2536 | 2568 | const case_src = tree.token_locs[case.firstToken()].start; |
| 2537 | 2569 | const sub_scope = blk: { |
| 2538 | 2570 | const uncasted_payload = case.payload orelse break :blk scope; |
| ... | ... | @@ -2559,6 +2591,8 @@ fn switchCaseExpr( |
| 2559 | 2591 | |
| 2560 | 2592 | fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst { |
| 2561 | 2593 | const tree = scope.tree(); |
| 2594 | const node_datas = tree.nodes.items(.data); |
| 2595 | const main_tokens = tree.nodes.items(.main_token); |
| 2562 | 2596 | const src = tree.token_locs[cfe.ltoken].start; |
| 2563 | 2597 | if (cfe.getRHS()) |rhs_node| { |
| 2564 | 2598 | if (nodeMayNeedMemoryLocation(rhs_node, scope)) { |
| ... | ... | @@ -2580,6 +2614,8 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo |
| 2580 | 2614 | defer tracy.end(); |
| 2581 | 2615 | |
| 2582 | 2616 | const tree = scope.tree(); |
| 2617 | const node_datas = tree.nodes.items(.data); |
| 2618 | const main_tokens = tree.nodes.items(.main_token); |
| 2583 | 2619 | const ident_name = try mod.identifierTokenString(scope, ident.token); |
| 2584 | 2620 | const src = tree.token_locs[ident.token].start; |
| 2585 | 2621 | if (mem.eql(u8, ident_name, "_")) { |
| ... | ... | @@ -2667,6 +2703,8 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo |
| 2667 | 2703 | |
| 2668 | 2704 | fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 2669 | 2705 | const tree = scope.tree(); |
| 2706 | const node_datas = tree.nodes.items(.data); |
| 2707 | const main_tokens = tree.nodes.items(.main_token); |
| 2670 | 2708 | const unparsed_bytes = tree.tokenSlice(str_lit.token); |
| 2671 | 2709 | const arena = scope.arena(); |
| 2672 | 2710 | |
| ... | ... | @@ -2686,6 +2724,8 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner |
| 2686 | 2724 | |
| 2687 | 2725 | fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStringLiteral) !*zir.Inst { |
| 2688 | 2726 | const tree = scope.tree(); |
| 2727 | const node_datas = tree.nodes.items(.data); |
| 2728 | const main_tokens = tree.nodes.items(.main_token); |
| 2689 | 2729 | const lines = node.linesConst(); |
| 2690 | 2730 | const src = tree.token_locs[lines[0]].start; |
| 2691 | 2731 | |
| ... | ... | @@ -2713,6 +2753,8 @@ fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStr |
| 2713 | 2753 | |
| 2714 | 2754 | fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst { |
| 2715 | 2755 | const tree = scope.tree(); |
| 2756 | const node_datas = tree.nodes.items(.data); |
| 2757 | const main_tokens = tree.nodes.items(.main_token); |
| 2716 | 2758 | const src = tree.token_locs[node.token].start; |
| 2717 | 2759 | const slice = tree.tokenSlice(node.token); |
| 2718 | 2760 | |
| ... | ... | @@ -2733,6 +2775,8 @@ fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst |
| 2733 | 2775 | fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 2734 | 2776 | const arena = scope.arena(); |
| 2735 | 2777 | const tree = scope.tree(); |
| 2778 | const node_datas = tree.nodes.items(.data); |
| 2779 | const main_tokens = tree.nodes.items(.main_token); |
| 2736 | 2780 | const prefixed_bytes = tree.tokenSlice(int_lit.token); |
| 2737 | 2781 | const base = if (mem.startsWith(u8, prefixed_bytes, "0x")) |
| 2738 | 2782 | 16 |
| ... | ... | @@ -2762,6 +2806,8 @@ fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) Inne |
| 2762 | 2806 | fn floatLiteral(mod: *Module, scope: *Scope, float_lit: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 2763 | 2807 | const arena = scope.arena(); |
| 2764 | 2808 | const tree = scope.tree(); |
| 2809 | const node_datas = tree.nodes.items(.data); |
| 2810 | const main_tokens = tree.nodes.items(.main_token); |
| 2765 | 2811 | const bytes = tree.tokenSlice(float_lit.token); |
| 2766 | 2812 | if (bytes.len > 2 and bytes[1] == 'x') { |
| 2767 | 2813 | return mod.failTok(scope, float_lit.token, "TODO hex floats", .{}); |
| ... | ... | @@ -2780,6 +2826,8 @@ fn floatLiteral(mod: *Module, scope: *Scope, float_lit: *ast.Node.OneToken) Inne |
| 2780 | 2826 | fn undefLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 2781 | 2827 | const arena = scope.arena(); |
| 2782 | 2828 | const tree = scope.tree(); |
| 2829 | const node_datas = tree.nodes.items(.data); |
| 2830 | const main_tokens = tree.nodes.items(.main_token); |
| 2783 | 2831 | const src = tree.token_locs[node.token].start; |
| 2784 | 2832 | return addZIRInstConst(mod, scope, src, .{ |
| 2785 | 2833 | .ty = Type.initTag(.@"undefined"), |
| ... | ... | @@ -2790,12 +2838,14 @@ fn undefLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerErro |
| 2790 | 2838 | fn boolLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 2791 | 2839 | const arena = scope.arena(); |
| 2792 | 2840 | const tree = scope.tree(); |
| 2841 | const node_datas = tree.nodes.items(.data); |
| 2842 | const main_tokens = tree.nodes.items(.main_token); |
| 2793 | 2843 | const src = tree.token_locs[node.token].start; |
| 2794 | 2844 | return addZIRInstConst(mod, scope, src, .{ |
| 2795 | 2845 | .ty = Type.initTag(.bool), |
| 2796 | 2846 | .val = switch (tree.token_ids[node.token]) { |
| 2797 | | .Keyword_true => Value.initTag(.bool_true), |
| 2798 | | .Keyword_false => Value.initTag(.bool_false), |
| 2847 | .keyword_true => Value.initTag(.bool_true), |
| 2848 | .keyword_false => Value.initTag(.bool_false), |
| 2799 | 2849 | else => unreachable, |
| 2800 | 2850 | }, |
| 2801 | 2851 | }); |
| ... | ... | @@ -2804,6 +2854,8 @@ fn boolLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError |
| 2804 | 2854 | fn nullLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 2805 | 2855 | const arena = scope.arena(); |
| 2806 | 2856 | const tree = scope.tree(); |
| 2857 | const node_datas = tree.nodes.items(.data); |
| 2858 | const main_tokens = tree.nodes.items(.main_token); |
| 2807 | 2859 | const src = tree.token_locs[node.token].start; |
| 2808 | 2860 | return addZIRInstConst(mod, scope, src, .{ |
| 2809 | 2861 | .ty = Type.initTag(.@"null"), |
| ... | ... | @@ -2811,12 +2863,14 @@ fn nullLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError |
| 2811 | 2863 | }); |
| 2812 | 2864 | } |
| 2813 | 2865 | |
| 2814 | | fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zir.Inst { |
| 2866 | fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.@"asm") InnerError!*zir.Inst { |
| 2815 | 2867 | if (asm_node.outputs.len != 0) { |
| 2816 | 2868 | return mod.failNode(scope, &asm_node.base, "TODO implement asm with an output", .{}); |
| 2817 | 2869 | } |
| 2818 | 2870 | const arena = scope.arena(); |
| 2819 | 2871 | const tree = scope.tree(); |
| 2872 | const node_datas = tree.nodes.items(.data); |
| 2873 | const main_tokens = tree.nodes.items(.main_token); |
| 2820 | 2874 | |
| 2821 | 2875 | const inputs = try arena.alloc(*zir.Inst, asm_node.inputs.len); |
| 2822 | 2876 | const args = try arena.alloc(*zir.Inst, asm_node.inputs.len); |
| ... | ... | @@ -2839,7 +2893,7 @@ fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zi |
| 2839 | 2893 | .ty = Type.initTag(.type), |
| 2840 | 2894 | .val = Value.initTag(.void_type), |
| 2841 | 2895 | }); |
| 2842 | | const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.Asm, .{ |
| 2896 | const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.@"asm", .{ |
| 2843 | 2897 | .asm_source = try expr(mod, scope, str_type_rl, asm_node.template), |
| 2844 | 2898 | .return_type = return_type, |
| 2845 | 2899 | }, .{ |
| ... | ... | @@ -2851,7 +2905,7 @@ fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zi |
| 2851 | 2905 | return asm_inst; |
| 2852 | 2906 | } |
| 2853 | 2907 | |
| 2854 | | fn ensureBuiltinParamCount(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall, count: u32) !void { |
| 2908 | fn ensureBuiltinParamCount(mod: *Module, scope: *Scope, call: *ast.Node.builtin_call, count: u32) !void { |
| 2855 | 2909 | if (call.params_len == count) |
| 2856 | 2910 | return; |
| 2857 | 2911 | |
| ... | ... | @@ -2863,11 +2917,13 @@ fn simpleCast( |
| 2863 | 2917 | mod: *Module, |
| 2864 | 2918 | scope: *Scope, |
| 2865 | 2919 | rl: ResultLoc, |
| 2866 | | call: *ast.Node.BuiltinCall, |
| 2920 | call: *ast.Node.builtin_call, |
| 2867 | 2921 | inst_tag: zir.Inst.Tag, |
| 2868 | 2922 | ) InnerError!*zir.Inst { |
| 2869 | 2923 | try ensureBuiltinParamCount(mod, scope, call, 2); |
| 2870 | 2924 | const tree = scope.tree(); |
| 2925 | const node_datas = tree.nodes.items(.data); |
| 2926 | const main_tokens = tree.nodes.items(.main_token); |
| 2871 | 2927 | const src = tree.token_locs[call.builtin_token].start; |
| 2872 | 2928 | const params = call.params(); |
| 2873 | 2929 | const dest_type = try typeExpr(mod, scope, params[0]); |
| ... | ... | @@ -2876,10 +2932,12 @@ fn simpleCast( |
| 2876 | 2932 | return rvalue(mod, scope, rl, result); |
| 2877 | 2933 | } |
| 2878 | 2934 | |
| 2879 | | fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 2935 | fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 2880 | 2936 | try ensureBuiltinParamCount(mod, scope, call, 1); |
| 2881 | 2937 | const operand = try expr(mod, scope, .none, call.params()[0]); |
| 2882 | 2938 | const tree = scope.tree(); |
| 2939 | const node_datas = tree.nodes.items(.data); |
| 2940 | const main_tokens = tree.nodes.items(.main_token); |
| 2883 | 2941 | const src = tree.token_locs[call.builtin_token].start; |
| 2884 | 2942 | return addZIRUnOp(mod, scope, src, .ptrtoint, operand); |
| 2885 | 2943 | } |
| ... | ... | @@ -2888,10 +2946,12 @@ fn as( |
| 2888 | 2946 | mod: *Module, |
| 2889 | 2947 | scope: *Scope, |
| 2890 | 2948 | rl: ResultLoc, |
| 2891 | | call: *ast.Node.BuiltinCall, |
| 2949 | call: *ast.Node.builtin_call, |
| 2892 | 2950 | ) InnerError!*zir.Inst { |
| 2893 | 2951 | try ensureBuiltinParamCount(mod, scope, call, 2); |
| 2894 | 2952 | const tree = scope.tree(); |
| 2953 | const node_datas = tree.nodes.items(.data); |
| 2954 | const main_tokens = tree.nodes.items(.main_token); |
| 2895 | 2955 | const src = tree.token_locs[call.builtin_token].start; |
| 2896 | 2956 | const params = call.params(); |
| 2897 | 2957 | const dest_type = try typeExpr(mod, scope, params[0]); |
| ... | ... | @@ -2963,9 +3023,11 @@ fn asRlPtr( |
| 2963 | 3023 | } |
| 2964 | 3024 | } |
| 2965 | 3025 | |
| 2966 | | fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3026 | fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 2967 | 3027 | try ensureBuiltinParamCount(mod, scope, call, 2); |
| 2968 | 3028 | const tree = scope.tree(); |
| 3029 | const node_datas = tree.nodes.items(.data); |
| 3030 | const main_tokens = tree.nodes.items(.main_token); |
| 2969 | 3031 | const src = tree.token_locs[call.builtin_token].start; |
| 2970 | 3032 | const params = call.params(); |
| 2971 | 3033 | const dest_type = try typeExpr(mod, scope, params[0]); |
| ... | ... | @@ -3007,27 +3069,33 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa |
| 3007 | 3069 | } |
| 3008 | 3070 | } |
| 3009 | 3071 | |
| 3010 | | fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3072 | fn import(mod: *Module, scope: *Scope, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 3011 | 3073 | try ensureBuiltinParamCount(mod, scope, call, 1); |
| 3012 | 3074 | const tree = scope.tree(); |
| 3075 | const node_datas = tree.nodes.items(.data); |
| 3076 | const main_tokens = tree.nodes.items(.main_token); |
| 3013 | 3077 | const src = tree.token_locs[call.builtin_token].start; |
| 3014 | 3078 | const params = call.params(); |
| 3015 | 3079 | const target = try expr(mod, scope, .none, params[0]); |
| 3016 | 3080 | return addZIRUnOp(mod, scope, src, .import, target); |
| 3017 | 3081 | } |
| 3018 | 3082 | |
| 3019 | | fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3083 | fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 3020 | 3084 | try ensureBuiltinParamCount(mod, scope, call, 1); |
| 3021 | 3085 | const tree = scope.tree(); |
| 3086 | const node_datas = tree.nodes.items(.data); |
| 3087 | const main_tokens = tree.nodes.items(.main_token); |
| 3022 | 3088 | const src = tree.token_locs[call.builtin_token].start; |
| 3023 | 3089 | const params = call.params(); |
| 3024 | 3090 | const target = try expr(mod, scope, .none, params[0]); |
| 3025 | 3091 | return addZIRUnOp(mod, scope, src, .compile_error, target); |
| 3026 | 3092 | } |
| 3027 | 3093 | |
| 3028 | | fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3094 | fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 3029 | 3095 | try ensureBuiltinParamCount(mod, scope, call, 1); |
| 3030 | 3096 | const tree = scope.tree(); |
| 3097 | const node_datas = tree.nodes.items(.data); |
| 3098 | const main_tokens = tree.nodes.items(.main_token); |
| 3031 | 3099 | const src = tree.token_locs[call.builtin_token].start; |
| 3032 | 3100 | const params = call.params(); |
| 3033 | 3101 | const u32_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | ... | @@ -3038,8 +3106,10 @@ fn setEvalBranchQuota(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) |
| 3038 | 3106 | return addZIRUnOp(mod, scope, src, .set_eval_branch_quota, quota); |
| 3039 | 3107 | } |
| 3040 | 3108 | |
| 3041 | | fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3109 | fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 3042 | 3110 | const tree = scope.tree(); |
| 3111 | const node_datas = tree.nodes.items(.data); |
| 3112 | const main_tokens = tree.nodes.items(.main_token); |
| 3043 | 3113 | const arena = scope.arena(); |
| 3044 | 3114 | const src = tree.token_locs[call.builtin_token].start; |
| 3045 | 3115 | const params = call.params(); |
| ... | ... | @@ -3054,8 +3124,10 @@ fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCal |
| 3054 | 3124 | items[param_i] = try expr(mod, scope, .none, param); |
| 3055 | 3125 | return rvalue(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{})); |
| 3056 | 3126 | } |
| 3057 | | fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3127 | fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 3058 | 3128 | const tree = scope.tree(); |
| 3129 | const node_datas = tree.nodes.items(.data); |
| 3130 | const main_tokens = tree.nodes.items(.main_token); |
| 3059 | 3131 | const arena = scope.arena(); |
| 3060 | 3132 | const src = tree.token_locs[call.builtin_token].start; |
| 3061 | 3133 | const params = call.params(); |
| ... | ... | @@ -3065,8 +3137,10 @@ fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerErr |
| 3065 | 3137 | return addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{}); |
| 3066 | 3138 | } |
| 3067 | 3139 | |
| 3068 | | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 3140 | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.builtin_call) InnerError!*zir.Inst { |
| 3069 | 3141 | const tree = scope.tree(); |
| 3142 | const node_datas = tree.nodes.items(.data); |
| 3143 | const main_tokens = tree.nodes.items(.main_token); |
| 3070 | 3144 | const builtin_name = tree.tokenSlice(call.builtin_token); |
| 3071 | 3145 | |
| 3072 | 3146 | // We handle the different builtins manually because they have different semantics depending |
| ... | ... | @@ -3104,8 +3178,10 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built |
| 3104 | 3178 | } |
| 3105 | 3179 | } |
| 3106 | 3180 | |
| 3107 | | fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) InnerError!*zir.Inst { |
| 3181 | fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.call) InnerError!*zir.Inst { |
| 3108 | 3182 | const tree = scope.tree(); |
| 3183 | const node_datas = tree.nodes.items(.data); |
| 3184 | const main_tokens = tree.nodes.items(.main_token); |
| 3109 | 3185 | const lhs = try expr(mod, scope, .none, node.lhs); |
| 3110 | 3186 | |
| 3111 | 3187 | const param_nodes = node.params(); |
| ... | ... | @@ -3130,6 +3206,8 @@ fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) In |
| 3130 | 3206 | |
| 3131 | 3207 | fn unreach(mod: *Module, scope: *Scope, unreach_node: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 3132 | 3208 | const tree = scope.tree(); |
| 3209 | const node_datas = tree.nodes.items(.data); |
| 3210 | const main_tokens = tree.nodes.items(.main_token); |
| 3133 | 3211 | const src = tree.token_locs[unreach_node.token].start; |
| 3134 | 3212 | return addZIRNoOp(mod, scope, src, .unreachable_safe); |
| 3135 | 3213 | } |
| ... | ... | @@ -3176,11 +3254,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3176 | 3254 | while (true) { |
| 3177 | 3255 | switch (node.tag) { |
| 3178 | 3256 | .Root, |
| 3179 | | .Use, |
| 3180 | | .TestDecl, |
| 3181 | | .DocComment, |
| 3182 | | .SwitchCase, |
| 3183 | | .SwitchElse, |
| 3257 | .@"usingnamespace", |
| 3258 | .test_decl, |
| 3259 | .doc_comment, |
| 3260 | .switch_case, |
| 3261 | .switch_else, |
| 3184 | 3262 | .Else, |
| 3185 | 3263 | .Payload, |
| 3186 | 3264 | .PointerPayload, |
| ... | ... | @@ -3190,97 +3268,97 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3190 | 3268 | .FieldInitializer, |
| 3191 | 3269 | => unreachable, |
| 3192 | 3270 | |
| 3193 | | .Return, |
| 3194 | | .Break, |
| 3195 | | .Continue, |
| 3196 | | .BitNot, |
| 3197 | | .BoolNot, |
| 3198 | | .VarDecl, |
| 3199 | | .Defer, |
| 3200 | | .AddressOf, |
| 3201 | | .OptionalType, |
| 3202 | | .Negation, |
| 3203 | | .NegationWrap, |
| 3204 | | .Resume, |
| 3205 | | .ArrayType, |
| 3206 | | .ArrayTypeSentinel, |
| 3271 | .@"return", |
| 3272 | .@"break", |
| 3273 | .@"continue", |
| 3274 | .bit_not, |
| 3275 | .bool_not, |
| 3276 | .var_decl, |
| 3277 | .@"defer", |
| 3278 | .address_of, |
| 3279 | .optional_type, |
| 3280 | .negation, |
| 3281 | .negation_wrap, |
| 3282 | .@"resume", |
| 3283 | .array_type, |
| 3284 | .array_type_sentinel, |
| 3207 | 3285 | .PtrType, |
| 3208 | | .SliceType, |
| 3209 | | .Suspend, |
| 3210 | | .AnyType, |
| 3211 | | .ErrorType, |
| 3286 | .slice_type, |
| 3287 | .@"suspend", |
| 3288 | .@"anytype", |
| 3289 | .error_type, |
| 3212 | 3290 | .FnProto, |
| 3213 | | .AnyFrameType, |
| 3214 | | .IntegerLiteral, |
| 3215 | | .FloatLiteral, |
| 3216 | | .EnumLiteral, |
| 3217 | | .StringLiteral, |
| 3291 | .anyframe_type, |
| 3292 | .integer_literal, |
| 3293 | .float_literal, |
| 3294 | .enum_literal, |
| 3295 | .string_literal, |
| 3218 | 3296 | .MultilineStringLiteral, |
| 3219 | | .CharLiteral, |
| 3220 | | .BoolLiteral, |
| 3221 | | .NullLiteral, |
| 3222 | | .UndefinedLiteral, |
| 3223 | | .Unreachable, |
| 3224 | | .Identifier, |
| 3225 | | .ErrorSetDecl, |
| 3297 | .char_literal, |
| 3298 | .bool_literal, |
| 3299 | .null_literal, |
| 3300 | .undefined_literal, |
| 3301 | .@"unreachable", |
| 3302 | .identifier, |
| 3303 | .error_set_decl, |
| 3226 | 3304 | .ContainerDecl, |
| 3227 | | .Asm, |
| 3228 | | .Add, |
| 3229 | | .AddWrap, |
| 3230 | | .ArrayCat, |
| 3231 | | .ArrayMult, |
| 3232 | | .Assign, |
| 3233 | | .AssignBitAnd, |
| 3234 | | .AssignBitOr, |
| 3235 | | .AssignBitShiftLeft, |
| 3236 | | .AssignBitShiftRight, |
| 3237 | | .AssignBitXor, |
| 3238 | | .AssignDiv, |
| 3239 | | .AssignSub, |
| 3240 | | .AssignSubWrap, |
| 3241 | | .AssignMod, |
| 3242 | | .AssignAdd, |
| 3243 | | .AssignAddWrap, |
| 3244 | | .AssignMul, |
| 3245 | | .AssignMulWrap, |
| 3246 | | .BangEqual, |
| 3247 | | .BitAnd, |
| 3248 | | .BitOr, |
| 3249 | | .BitShiftLeft, |
| 3250 | | .BitShiftRight, |
| 3251 | | .BitXor, |
| 3252 | | .BoolAnd, |
| 3253 | | .BoolOr, |
| 3254 | | .Div, |
| 3255 | | .EqualEqual, |
| 3256 | | .ErrorUnion, |
| 3257 | | .GreaterOrEqual, |
| 3258 | | .GreaterThan, |
| 3259 | | .LessOrEqual, |
| 3260 | | .LessThan, |
| 3261 | | .MergeErrorSets, |
| 3262 | | .Mod, |
| 3263 | | .Mul, |
| 3264 | | .MulWrap, |
| 3265 | | .Range, |
| 3266 | | .Period, |
| 3267 | | .Sub, |
| 3268 | | .SubWrap, |
| 3269 | | .Slice, |
| 3270 | | .Deref, |
| 3271 | | .ArrayAccess, |
| 3272 | | .Block, |
| 3305 | .@"asm", |
| 3306 | .add, |
| 3307 | .add_wrap, |
| 3308 | .array_cat, |
| 3309 | .array_mult, |
| 3310 | .assign, |
| 3311 | .assign_bit_and, |
| 3312 | .assign_bit_or, |
| 3313 | .assign_bit_shift_left, |
| 3314 | .assign_bit_shift_right, |
| 3315 | .assign_bit_xor, |
| 3316 | .assign_div, |
| 3317 | .assign_sub, |
| 3318 | .assign_sub_wrap, |
| 3319 | .assign_mod, |
| 3320 | .assign_add, |
| 3321 | .assign_add_wrap, |
| 3322 | .assign_mul, |
| 3323 | .assign_mul_wrap, |
| 3324 | .bang_equal, |
| 3325 | .bit_and, |
| 3326 | .bit_or, |
| 3327 | .bit_shift_left, |
| 3328 | .bit_shift_right, |
| 3329 | .bit_xor, |
| 3330 | .bool_and, |
| 3331 | .bool_or, |
| 3332 | .div, |
| 3333 | .equal_equal, |
| 3334 | .error_union, |
| 3335 | .greater_or_equal, |
| 3336 | .greater_than, |
| 3337 | .less_or_equal, |
| 3338 | .less_than, |
| 3339 | .merge_error_sets, |
| 3340 | .mod, |
| 3341 | .mul, |
| 3342 | .mul_wrap, |
| 3343 | .range, |
| 3344 | .period, |
| 3345 | .sub, |
| 3346 | .sub_wrap, |
| 3347 | .slice, |
| 3348 | .deref, |
| 3349 | .array_access, |
| 3350 | .block, |
| 3273 | 3351 | => return false, |
| 3274 | 3352 | |
| 3275 | 3353 | // Forward the question to a sub-expression. |
| 3276 | | .GroupedExpression => node = node.castTag(.GroupedExpression).?.expr, |
| 3277 | | .Try => node = node.castTag(.Try).?.rhs, |
| 3278 | | .Await => node = node.castTag(.Await).?.rhs, |
| 3279 | | .Catch => node = node.castTag(.Catch).?.rhs, |
| 3280 | | .OrElse => node = node.castTag(.OrElse).?.rhs, |
| 3281 | | .Comptime => node = node.castTag(.Comptime).?.expr, |
| 3282 | | .Nosuspend => node = node.castTag(.Nosuspend).?.expr, |
| 3283 | | .UnwrapOptional => node = node.castTag(.UnwrapOptional).?.lhs, |
| 3354 | .grouped_expression => node = node.castTag(.grouped_expression).?.expr, |
| 3355 | .@"try" => node = node.castTag(.@"try").?.rhs, |
| 3356 | .@"await" => node = node.castTag(.@"await").?.rhs, |
| 3357 | .@"catch" => node = node.castTag(.@"catch").?.rhs, |
| 3358 | .@"orelse" => node = node.castTag(.@"orelse").?.rhs, |
| 3359 | .@"comptime" => node = node.castTag(.@"comptime").?.expr, |
| 3360 | .@"nosuspend" => node = node.castTag(.@"nosuspend").?.expr, |
| 3361 | .unwrap_optional => node = node.castTag(.unwrap_optional).?.lhs, |
| 3284 | 3362 | |
| 3285 | 3363 | // True because these are exactly the expressions we need memory locations for. |
| 3286 | 3364 | .ArrayInitializer, |
| ... | ... | @@ -3291,14 +3369,14 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3291 | 3369 | |
| 3292 | 3370 | // True because depending on comptime conditions, sub-expressions |
| 3293 | 3371 | // may be the kind that need memory locations. |
| 3294 | | .While, |
| 3295 | | .For, |
| 3296 | | .Switch, |
| 3297 | | .Call, |
| 3298 | | .LabeledBlock, |
| 3372 | .@"while", |
| 3373 | .@"for", |
| 3374 | .@"switch", |
| 3375 | .call, |
| 3376 | .labeled_block, |
| 3299 | 3377 | => return true, |
| 3300 | 3378 | |
| 3301 | | .BuiltinCall => { |
| 3379 | .builtin_call => { |
| 3302 | 3380 | @setEvalBranchQuota(5000); |
| 3303 | 3381 | const builtin_needs_mem_loc = std.ComptimeStringMap(bool, .{ |
| 3304 | 3382 | .{ "@addWithOverflow", false }, |
| ... | ... | @@ -3404,12 +3482,12 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3404 | 3482 | .{ "@TypeOf", false }, |
| 3405 | 3483 | .{ "@unionInit", true }, |
| 3406 | 3484 | }); |
| 3407 | | const name = scope.tree().tokenSlice(node.castTag(.BuiltinCall).?.builtin_token); |
| 3485 | const name = scope.tree().tokenSlice(node.castTag(.builtin_call).?.builtin_token); |
| 3408 | 3486 | return builtin_needs_mem_loc.get(name).?; |
| 3409 | 3487 | }, |
| 3410 | 3488 | |
| 3411 | 3489 | // Depending on AST properties, they may need memory locations. |
| 3412 | | .If => return node.castTag(.If).?.@"else" != null, |
| 3490 | .@"if" => return node.castTag(.@"if").?.@"else" != null, |
| 3413 | 3491 | } |
| 3414 | 3492 | } |
| 3415 | 3493 | } |
| ... | ... | @@ -3450,8 +3528,17 @@ fn rvalue(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr |
| 3450 | 3528 | } |
| 3451 | 3529 | } |
| 3452 | 3530 | |
| 3453 | | fn rvalueVoid(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node, result: void) InnerError!*zir.Inst { |
| 3454 | | const src = scope.tree().token_locs[node.firstToken()].start; |
| 3531 | fn rvalueVoid( |
| 3532 | mod: *Module, |
| 3533 | scope: *Scope, |
| 3534 | rl: ResultLoc, |
| 3535 | node: ast.Node.Index, |
| 3536 | result: void, |
| 3537 | ) InnerError!*zir.Inst { |
| 3538 | const tree = scope.tree(); |
| 3539 | const node_datas = tree.nodes.items(.data); |
| 3540 | const main_tokens = tree.nodes.items(.main_token); |
| 3541 | const src = tree.tokens.items(.start)[tree.firstToken(node)]; |
| 3455 | 3542 | const void_inst = try addZIRInstConst(mod, scope, src, .{ |
| 3456 | 3543 | .ty = Type.initTag(.void), |
| 3457 | 3544 | .val = Value.initTag(.void_value), |