Skip to content

Commit

Permalink
more normalization of core functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ityonemo committed Mar 20, 2024
1 parent c136f02 commit 491503e
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 19 deletions.
23 changes: 14 additions & 9 deletions priv/beam/beam.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1168,8 +1168,10 @@ pub fn WrappedResult(comptime FunctionType: type) type {
/// <!-- topic: Exceptions -->
/// The equivalent of [`error`](https://www.erlang.org/doc/man/erlang.html#error-1)
/// in erlang.
pub fn raise_exception(env_: env, reason: anytype) term {
return term{ .v = e.enif_raise_exception(env_, make(env_, reason, .{}).v) };
pub fn raise_exception(reason: anytype, opts: anytype) term {
const T = @TypeOf(opts);
const env_ = if (@hasField(T, "env")) opts.env else context.env;
return term{ .v = e.enif_raise_exception(env_, make(reason, opts).v) };
}

/// <!-- topic: Exceptions -->
Expand All @@ -1183,21 +1185,24 @@ pub fn raise_exception(env_: env, reason: anytype) term {
/// > #### Exception structs are not checked {: .warning }
/// >
/// > The validity of the exception struct is not checked when using this function.
pub fn raise_elixir_exception(env_: env, comptime module: []const u8, data: anytype) term {
pub fn raise_elixir_exception(comptime module: []const u8, data: anytype, opts: anytype) term {
if (@typeInfo(@TypeOf(data)) != .Struct) {
@compileError("elixir exceptions must be structs");
}

const T = @TypeOf(opts);
var env_ = if (@hasField(T, "env")) opts.env else context.env;

const name = comptime name: {
break :name "Elixir." ++ module;
};
var exception: e.ErlNifTerm = undefined;
const initial = make(env_, data, .{});

_ = e.enif_make_map_put(env_, initial.v, make_into_atom(env_, "__struct__").v, make_into_atom(env_, name).v, &exception);
_ = e.enif_make_map_put(env_, exception, make_into_atom(env_, "__exception__").v, make(env_, true, .{}).v, &exception);
_ = e.enif_make_map_put(env_, initial.v, make_into_atom("__struct__", opts).v, make_into_atom(name, opts).v, &exception);
_ = e.enif_make_map_put(env_, exception, make_into_atom("__exception__", opts).v, make(true, opts).v, &exception);

return raise_exception(env_, term{ .v = exception });
return raise_exception(term{ .v = exception }, opts);
}

/// <!-- topic: Exceptions -->
Expand All @@ -1208,11 +1213,11 @@ pub fn raise_elixir_exception(env_: env, comptime module: []const u8, data: anyt
/// stacktrace. In order to concatenate this stacktrace onto your BEAM
/// exception, the function that wraps the nif must be able to catch the
/// error and append the zig error return trace to the existing stacktrace.
pub fn raise_with_error_return(env_: env, err: anytype, maybe_return_trace: ?*std.builtin.StackTrace) term {
pub fn raise_with_error_return(err: anytype, maybe_return_trace: ?*std.builtin.StackTrace, opts: anytype) term {
if (maybe_return_trace) |return_trace| {
return raise_exception(env_, .{ .@"error", err, return_trace });
return raise_exception(.{ .@"error", err, return_trace }, opts);
} else {
return raise_exception(env_, .{ .@"error", err });
return raise_exception(.{ .@"error", err }, opts);
}
}

Expand Down
2 changes: 1 addition & 1 deletion priv/beam/get.zig
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ pub fn get_slice(comptime T: type, src: beam.term, opts: anytype) !T {
errdefer error_expected(T, opts);
errdefer error_got(src, opts);

switch (src.term_type(env)) {
switch (src.term_type(env(opts))) {
.bitstring => return get_slice_binary(T, src, opts),
.list => return get_slice_list(T, src, opts),
else => return GetError.argument_error,
Expand Down
2 changes: 1 addition & 1 deletion priv/beam/make.zig
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ fn make_binary(content: anytype, opts: anytype) beam.term {

fn make_binary_from_u8_slice(slice: []const u8, opts: anytype) beam.term {
var result: beam.term = undefined;
var buf = e.enif_make_new_binary(slice.len, &result.v, opts);
var buf = e.enif_make_new_binary(env(opts), slice.len, &result.v);
std.mem.copy(u8, buf[0..slice.len], slice);
return result;
}
Expand Down
28 changes: 20 additions & 8 deletions priv/beam/resource.zig
Original file line number Diff line number Diff line change
Expand Up @@ -170,37 +170,49 @@ pub fn Resource(comptime T: type, comptime root: type, comptime opts: ResourceOp
}

fn dtor(env: beam.env, obj: ?*anyopaque) callconv(.C) void {
beam.context = .callback;
set_callback_context(env);

if (@hasDecl(Callbacks, "dtor")) {
Callbacks.dtor(env, to_typed(obj));
Callbacks.dtor(to_typed(obj));
}
}

fn down(env: beam.env, obj: ?*anyopaque, pid: [*c]beam.pid, monitor: [*c]beam.monitor) callconv(.C) void {
beam.context = .callback;
set_callback_context(env);

if (@hasDecl(Callbacks, "down")) {
Callbacks.down(env, to_typed(obj), pid[0], monitor[0]);
Callbacks.down(to_typed(obj), pid[0], monitor[0]);
}
}

fn stop(env: beam.env, obj: ?*anyopaque, event: beam.event, is_direct_call: c_int) callconv(.C) void {
beam.context = .callback;
set_callback_context(env);

if (@hasDecl(Callbacks, "stop")) {
Callbacks.stop(env, to_typed(obj), event, is_direct_call != 0);
Callbacks.stop(to_typed(obj), event, is_direct_call != 0);
}
}

fn dyncall(env: beam.env, obj: ?*anyopaque, calldata: ?*anyopaque) callconv(.C) void {
beam.context = .callback;
set_callback_context(env);

if (@hasDecl(Callbacks, "dyncall")) {
return Callbacks.dyncall(env, to_typed(obj), calldata);
return Callbacks.dyncall(to_typed(obj), calldata);
}
}
};
}
};
}

fn set_callback_context(env: beam.env) void {
beam.context = .{
.mode = .callback,
.env = env,
.allocator = beam.allocator,
};
}

pub fn MaybeUnwrap(comptime s: builtin.Type.Struct) ?type {
// verify that this is indeed a resource. A resource has the
// a single field called `__payload` which is a pointer to the wrapped type.
Expand Down

0 comments on commit 491503e

Please sign in to comment.