Skip to content

add @tryImport #8033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/stage1/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1754,6 +1754,7 @@ enum BuiltinFnId {
BuiltinFnIdBswap,
BuiltinFnIdBitReverse,
BuiltinFnIdImport,
BuiltinFnIdTryImport,
BuiltinFnIdCImport,
BuiltinFnIdErrName,
BuiltinFnIdBreakpoint,
Expand Down Expand Up @@ -2562,6 +2563,7 @@ enum IrInstSrcId {
IrInstSrcIdBswap,
IrInstSrcIdBitReverse,
IrInstSrcIdImport,
IrInstSrcIdTryImport,
IrInstSrcIdCImport,
IrInstSrcIdCInclude,
IrInstSrcIdCDefine,
Expand Down Expand Up @@ -3438,6 +3440,12 @@ struct IrInstSrcImport {
IrInstSrc *name;
};

struct IrInstSrcTryImport {
IrInstSrc base;

IrInstSrc *name;
};

struct IrInstSrcRef {
IrInstSrc base;

Expand Down
1 change: 1 addition & 0 deletions src/stage1/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8812,6 +8812,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdBswap, "byteSwap", 2);
create_builtin_fn(g, BuiltinFnIdBitReverse, "bitReverse", 2);
create_builtin_fn(g, BuiltinFnIdImport, "import", 1);
create_builtin_fn(g, BuiltinFnIdTryImport, "tryImport", 1);
create_builtin_fn(g, BuiltinFnIdCImport, "cImport", 1);
create_builtin_fn(g, BuiltinFnIdErrName, "errorName", 1);
create_builtin_fn(g, BuiltinFnIdTypeName, "typeName", 1);
Expand Down
59 changes: 55 additions & 4 deletions src/stage1/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchTarget *>(inst));
case IrInstSrcIdImport:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcImport *>(inst));
case IrInstSrcIdTryImport:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTryImport *>(inst));
case IrInstSrcIdRef:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcRef *>(inst));
case IrInstSrcIdCompileErr:
Expand Down Expand Up @@ -1278,6 +1280,10 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcImport *) {
return IrInstSrcIdImport;
}

static constexpr IrInstSrcId ir_inst_id(IrInstSrcTryImport *) {
return IrInstSrcIdTryImport;
}

static constexpr IrInstSrcId ir_inst_id(IrInstSrcCImport *) {
return IrInstSrcIdCImport;
}
Expand Down Expand Up @@ -3360,6 +3366,15 @@ static IrInstSrc *ir_build_import(IrBuilderSrc *irb, Scope *scope, AstNode *sour
return &instruction->base;
}

static IrInstSrc *ir_build_try_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) {
IrInstSrcTryImport *instruction = ir_build_instruction<IrInstSrcTryImport>(irb, scope, source_node);
instruction->name = name;

ir_ref_instruction(name, irb->current_basic_block);

return &instruction->base;
}

static IrInstSrc *ir_build_ref_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) {
IrInstSrcRef *instruction = ir_build_instruction<IrInstSrcRef>(irb, scope, source_node);
instruction->value = value;
Expand Down Expand Up @@ -6464,6 +6479,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
IrInstSrc *import = ir_build_import(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, import, lval, result_loc);
}
case BuiltinFnIdTryImport:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
if (arg0_value == irb->codegen->invalid_inst_src)
return arg0_value;

IrInstSrc *try_import = ir_build_try_import(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, try_import, lval, result_loc);
}
case BuiltinFnIdCImport:
{
IrInstSrc *c_import = ir_build_c_import(irb, scope, node);
Expand Down Expand Up @@ -24425,15 +24450,15 @@ static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira,
return target_value_ptr;
}

static IrInstGen *ir_analyze_instruction_import(IrAnalyze *ira, IrInstSrcImport *import_instruction) {
static IrInstGen *ir_analyze_instruction_import_common(IrAnalyze *ira, IrInstSrc *base_instruction, IrInstSrc *name, bool is_try) {
Error err;

IrInstGen *name_value = import_instruction->name->child;
IrInstGen *name_value = name->child;
Buf *import_target_str = ir_resolve_str(ira, name_value);
if (!import_target_str)
return ira->codegen->invalid_inst_gen;

AstNode *source_node = import_instruction->base.base.source_node;
AstNode *source_node = base_instruction->base.source_node;
ZigType *import = source_node->owner;

ZigType *target_import;
Expand All @@ -24448,6 +24473,12 @@ static IrInstGen *ir_analyze_instruction_import(IrAnalyze *ira, IrInstSrcImport
buf_ptr(import_target_path)));
return ira->codegen->invalid_inst_gen;
} else if (err == ErrorFileNotFound) {
if (is_try) {
ZigType *result_type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
IrInstGen *result = ir_const(ira, &base_instruction->base, result_type);
set_optional_value_to_null(result->value);
return result;
}
ir_add_error_node(ira, source_node,
buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
return ira->codegen->invalid_inst_gen;
Expand All @@ -24458,7 +24489,24 @@ static IrInstGen *ir_analyze_instruction_import(IrAnalyze *ira, IrInstSrcImport
}
}

return ir_const_type(ira, &import_instruction->base.base, target_import);
IrInstGen *target_import_result = ir_const_type(ira, &base_instruction->base, target_import);

if (!is_try) {
return target_import_result;
}

ZigType *result_type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
IrInstGen *result = ir_const(ira, &base_instruction->base, result_type);
set_optional_payload(result->value, ir_resolve_const(ira, target_import_result, UndefBad));
return result;
}

static IrInstGen *ir_analyze_instruction_import(IrAnalyze *ira, IrInstSrcImport *import_instruction) {
return ir_analyze_instruction_import_common(ira, &import_instruction->base, import_instruction->name, false);
}

static IrInstGen *ir_analyze_instruction_try_import(IrAnalyze *ira, IrInstSrcTryImport *try_import_instruction) {
return ir_analyze_instruction_import_common(ira, &try_import_instruction->base, try_import_instruction->name, true);
}

static IrInstGen *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstSrcRef *ref_instruction) {
Expand Down Expand Up @@ -32257,6 +32305,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_switch_else_var(ira, (IrInstSrcSwitchElseVar *)instruction);
case IrInstSrcIdImport:
return ir_analyze_instruction_import(ira, (IrInstSrcImport *)instruction);
case IrInstSrcIdTryImport:
return ir_analyze_instruction_try_import(ira, (IrInstSrcTryImport *)instruction);
case IrInstSrcIdRef:
return ir_analyze_instruction_ref(ira, (IrInstSrcRef *)instruction);
case IrInstSrcIdContainerInitList:
Expand Down Expand Up @@ -32726,6 +32776,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdSetRuntimeSafety:
case IrInstSrcIdSetFloatMode:
case IrInstSrcIdImport:
case IrInstSrcIdTryImport:
case IrInstSrcIdCompileErr:
case IrInstSrcIdCompileLog:
case IrInstSrcIdCImport:
Expand Down
11 changes: 11 additions & 0 deletions src/stage1/ir_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcBitReverse";
case IrInstSrcIdImport:
return "SrcImport";
case IrInstSrcIdTryImport:
return "SrcTryImport";
case IrInstSrcIdCImport:
return "SrcCImport";
case IrInstSrcIdCInclude:
Expand Down Expand Up @@ -1479,6 +1481,12 @@ static void ir_print_import(IrPrintSrc *irp, IrInstSrcImport *instruction) {
fprintf(irp->f, ")");
}

static void ir_print_try_import(IrPrintSrc *irp, IrInstSrcTryImport *instruction) {
fprintf(irp->f, "@tryImport(");
ir_print_other_inst_src(irp, instruction->name);
fprintf(irp->f, ")");
}

static void ir_print_ref(IrPrintSrc *irp, IrInstSrcRef *instruction) {
fprintf(irp->f, "ref ");
ir_print_other_inst_src(irp, instruction->value);
Expand Down Expand Up @@ -2747,6 +2755,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdImport:
ir_print_import(irp, (IrInstSrcImport *)instruction);
break;
case IrInstSrcIdTryImport:
ir_print_try_import(irp, (IrInstSrcTryImport *)instruction);
break;
case IrInstSrcIdRef:
ir_print_ref(irp, (IrInstSrcRef *)instruction);
break;
Expand Down
1 change: 1 addition & 0 deletions test/standalone.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
cases.addBuildFile("test/standalone/issue_794/build.zig");
cases.addBuildFile("test/standalone/issue_5825/build.zig");
cases.addBuildFile("test/standalone/pkg_import/build.zig");
cases.addBuildFile("test/standalone/tryimport/build.zig");
cases.addBuildFile("test/standalone/use_alias/build.zig");
cases.addBuildFile("test/standalone/brace_expansion/build.zig");
cases.addBuildFile("test/standalone/empty_env/build.zig");
Expand Down
28 changes: 28 additions & 0 deletions test/standalone/tryimport/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const std = @import("std");
const Builder = std.build.Builder;

pub fn build(b: *Builder) void {
const test_step = b.step("test", "Test it");
_ = addExe(b, test_step, "example-no-pkg", "example.zig", &[_][]const u8 {
"my_pkg is missing",
});
_ = addExe(b, test_step, "example-with-pkg", "example.zig", &[_][]const u8 {
"have my_pkg",
"a message from pkg.zig",
}).addPackagePath("my_pkg", "pkg.zig");
}

fn addExe(
b: *Builder,
step: *std.build.Step,
name: []const u8,
root: []const u8,
expect_matches: []const []const u8
) *std.build.LibExeObjStep {
const exe = b.addExecutable(name, root);
exe.setBuildMode(b.standardReleaseOptions());
const run = exe.run();
run.stdout_action = .{ .expect_matches = expect_matches };
step.dependOn(&run.step);
return exe;
}
8 changes: 8 additions & 0 deletions test/standalone/tryimport/example.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub fn main() !void {
if (@tryImport("my_pkg")) |my_pkg| {
try @import("std").io.getStdOut().writeAll("have my_pkg\n");
try my_pkg.doSomething();
} else {
try @import("std").io.getStdOut().writeAll("my_pkg is missing\n");
}
}
3 changes: 3 additions & 0 deletions test/standalone/tryimport/pkg.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub fn doSomething() !void {
try @import("std").io.getStdOut().writeAll("a message from pkg.zig\n");
}