| ... | @@ -820,7 +820,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn | ... | @@ -820,7 +820,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn |
| 820 | | 820 | |
| 821 | .@"defer" => return astgen.failNode(node, "TODO implement astgen.expr for .defer", .{}), | 821 | .@"defer" => return astgen.failNode(node, "TODO implement astgen.expr for .defer", .{}), |
| 822 | .@"errdefer" => return astgen.failNode(node, "TODO implement astgen.expr for .errdefer", .{}), | 822 | .@"errdefer" => return astgen.failNode(node, "TODO implement astgen.expr for .errdefer", .{}), |
| 823 | .@"try" => return astgen.failNode(node, "TODO implement astgen.expr for .Try", .{}), | 823 | .@"try" => return tryExpr(gz, scope, rl, node_datas[node].lhs), |
| 824 | | 824 | |
| 825 | .array_init_one, .array_init_one_comma => { | 825 | .array_init_one, .array_init_one_comma => { |
| 826 | var elements: [1]ast.Node.Index = undefined; | 826 | var elements: [1]ast.Node.Index = undefined; |
| ... | @@ -3154,6 +3154,110 @@ fn errorSetDecl( | ... | @@ -3154,6 +3154,110 @@ fn errorSetDecl( |
| 3154 | return rvalue(gz, scope, rl, result, node); | 3154 | return rvalue(gz, scope, rl, result, node); |
| 3155 | } | 3155 | } |
| 3156 | | 3156 | |
| | 3157 | fn tryExpr( |
| | 3158 | parent_gz: *GenZir, |
| | 3159 | scope: *Scope, |
| | 3160 | rl: ResultLoc, |
| | 3161 | node: ast.Node.Index, |
| | 3162 | ) InnerError!Zir.Inst.Ref { |
| | 3163 | const astgen = parent_gz.astgen; |
| | 3164 | const tree = &astgen.file.tree; |
| | 3165 | const main_tokens = tree.nodes.items(.main_token); |
| | 3166 | const token_tags = tree.tokens.items(.tag); |
| | 3167 | const node_datas = tree.nodes.items(.data); |
| | 3168 | const node_tags = tree.nodes.items(.tag); |
| | 3169 | |
| | 3170 | var block_scope: GenZir = .{ |
| | 3171 | .parent = scope, |
| | 3172 | .decl_node_index = parent_gz.decl_node_index, |
| | 3173 | .astgen = parent_gz.astgen, |
| | 3174 | .force_comptime = parent_gz.force_comptime, |
| | 3175 | .instructions = .{}, |
| | 3176 | }; |
| | 3177 | block_scope.setBreakResultLoc(rl); |
| | 3178 | defer block_scope.instructions.deinit(astgen.gpa); |
| | 3179 | |
| | 3180 | // This could be a pointer or value depending on the `operand_rl` parameter. |
| | 3181 | // We cannot use `block_scope.break_result_loc` because that has the bare |
| | 3182 | // type, whereas this expression has the optional type. Later we make |
| | 3183 | // up for this fact by calling rvalue on the else branch. |
| | 3184 | block_scope.break_count += 1; |
| | 3185 | |
| | 3186 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| | 3187 | .ref => .ref, |
| | 3188 | .discard, .none, .none_or_ref, .block_ptr, .inferred_ptr => .none, |
| | 3189 | .ty => |elem_ty| { |
| | 3190 | @panic("TODO"); |
| | 3191 | }, |
| | 3192 | .ptr => |ptr_ty| { |
| | 3193 | @panic("TODO"); |
| | 3194 | }, |
| | 3195 | }; |
| | 3196 | const ops = switch (rl) { |
| | 3197 | .ref => [3]Zir.Inst.Tag{ .is_err_ptr, .err_union_code_ptr, .err_union_payload_unsafe_ptr }, |
| | 3198 | else => [3]Zir.Inst.Tag{ .is_err, .err_union_code, .err_union_payload_unsafe }, |
| | 3199 | }; |
| | 3200 | const operand = try expr(&block_scope, &block_scope.base, operand_rl, node); |
| | 3201 | const cond = try block_scope.addUnNode(ops[0], operand, node); |
| | 3202 | const condbr = try block_scope.addCondBr(.condbr, node); |
| | 3203 | |
| | 3204 | const block = try parent_gz.addBlock(.block, node); |
| | 3205 | try parent_gz.instructions.append(astgen.gpa, block); |
| | 3206 | try block_scope.setBlockBody(block); |
| | 3207 | |
| | 3208 | var then_scope: GenZir = .{ |
| | 3209 | .parent = scope, |
| | 3210 | .decl_node_index = parent_gz.decl_node_index, |
| | 3211 | .astgen = parent_gz.astgen, |
| | 3212 | .force_comptime = block_scope.force_comptime, |
| | 3213 | .instructions = .{}, |
| | 3214 | }; |
| | 3215 | defer then_scope.instructions.deinit(astgen.gpa); |
| | 3216 | |
| | 3217 | const then_result = try then_scope.addUnNode(ops[1], operand, node); |
| | 3218 | const to_return = try then_scope.addUnNode(.ret_node, then_result, node); |
| | 3219 | |
| | 3220 | block_scope.break_count += 1; |
| | 3221 | // We hold off on the break instructions as well as copying the then/else |
| | 3222 | // instructions into place until we know whether to keep store_to_block_ptr |
| | 3223 | // instructions or not. |
| | 3224 | |
| | 3225 | var else_scope: GenZir = .{ |
| | 3226 | .parent = scope, |
| | 3227 | .decl_node_index = parent_gz.decl_node_index, |
| | 3228 | .astgen = parent_gz.astgen, |
| | 3229 | .force_comptime = block_scope.force_comptime, |
| | 3230 | .instructions = .{}, |
| | 3231 | }; |
| | 3232 | defer else_scope.instructions.deinit(astgen.gpa); |
| | 3233 | |
| | 3234 | // This could be a pointer or value depending on `unwrap_op`. |
| | 3235 | const unwrapped_payload = try else_scope.addUnNode(ops[2], operand, node); |
| | 3236 | const else_result = switch (rl) { |
| | 3237 | .ref => unwrapped_payload, |
| | 3238 | else => try rvalue(&else_scope, &else_scope.base, block_scope.break_result_loc, unwrapped_payload, node), |
| | 3239 | }; |
| | 3240 | |
| | 3241 | return finishThenElseBlock( |
| | 3242 | parent_gz, |
| | 3243 | scope, |
| | 3244 | rl, |
| | 3245 | node, |
| | 3246 | &block_scope, |
| | 3247 | &then_scope, |
| | 3248 | &else_scope, |
| | 3249 | condbr, |
| | 3250 | cond, |
| | 3251 | node, |
| | 3252 | node, |
| | 3253 | to_return, |
| | 3254 | else_result, |
| | 3255 | block, |
| | 3256 | block, |
| | 3257 | .@"break", |
| | 3258 | ); |
| | 3259 | } |
| | 3260 | |
| 3157 | fn orelseCatchExpr( | 3261 | fn orelseCatchExpr( |
| 3158 | parent_gz: *GenZir, | 3262 | parent_gz: *GenZir, |
| 3159 | scope: *Scope, | 3263 | scope: *Scope, |