authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-04-19 17:03:52-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-20 13:16:08-04:00
logee3c1c763c8201d31321643f72cd1506c369dd71
treea2d8e6470cf0735912aba56dfcdc1e1dae2df415
parente315120b79f98163dd6413e62684d6ad148295ee

stage2: astgen `try`


1 files changed, 105 insertions(+), 1 deletions(-)

src/AstGen.zig+105-1
...@@ -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
820820
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),
824824
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}
31563156
3157fn 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
3157fn orelseCatchExpr(3261fn orelseCatchExpr(
3158 parent_gz: *GenZir,3262 parent_gz: *GenZir,
3159 scope: *Scope,3263 scope: *Scope,