Skip to content

Commit

Permalink
finishes on_unload and on_upgrade code
Browse files Browse the repository at this point in the history
  • Loading branch information
ityonemo committed May 20, 2024
1 parent 3a2fa58 commit e59597c
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 7 deletions.
56 changes: 56 additions & 0 deletions lib/zig/sema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,62 @@ defmodule Zig.Sema do
)
end

{:on_unload, %{arity: arity}} when arity not in [1, 2] ->
seek_and_raise!(:on_unload, module, &"on_unload callback #{&1} must have arity 1 or 2")

{:on_unload, %{arity: 1} = function} ->
case function.params do
[
%Optional{child: :anyopaque_pointer}
] ->
:ok

[first] ->
seek_and_raise!(
:on_unload,
module,
&"on_unload callback #{&1} with arity 1 must have `?*anyopaque` as a parameter. \n\n got: `#{Type.render_zig(first)}`"
)
end

case function.return do
:void -> :ok

bad ->
seek_and_raise!(
:on_unload,
module,
&"on_unload callback #{&1} with arity 1 must have `void` as a return. \n\n got: `#{Type.render_zig(bad)}`"
)
end

{:on_unload, %{arity: 2} = function} ->
case function.params do
[
:env,
%Optional{child: :anyopaque_pointer}
] ->
:ok

[first, second] ->
seek_and_raise!(
:on_unload,
module,
&"on_unload callback #{&1} with arity 2 must have `beam.env` and `?*anyopaque` as parameters. \n\n got: `#{Type.render_zig(first)}`\n\n and: `#{Type.render_zig(second)}`"
)
end

case function.return do
:void -> :ok

bad ->
seek_and_raise!(
:on_unload,
module,
&"on_unload callback #{&1} with arity 2 must have `void` as a return. \n\n got: `#{Type.render_zig(bad)}`"
)
end

_ ->
:ok
end)
Expand Down
125 changes: 125 additions & 0 deletions test/integration/callbacks/on_unload_malformed_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
defmodule ZiglerTest.Callbacks.OnUnloadMalformedTest do
# this is a test of the "automatic" on_unload function.

use ZiglerTest.IntegrationCase, async: true

test "compiler error when on_unload function has the wrong arity" do
assert_raise CompileError,
"nofile:2: on_unload callback foo must have arity 1 or 2",
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadUnloadArity do
use Zig,
otp_app: :zigler,
callbacks: [on_unload: :foo],
dir: unquote(__DIR__)

~Z"""
const beam = @import("beam");
pub fn foo() void {}
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end

describe "compiler error when on_unload arity 1" do
test "has the wrong parameters" do
assert_raise CompileError,
"nofile:2: on_unload callback foo with arity 1 must have `?*anyopaque` as a parameter. \n\n got: `beam.env`",
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnunload1Parameters do
use Zig,
otp_app: :zigler,
callbacks: [on_unload: :foo],
dir: unquote(__DIR__)

~Z"""
const beam = @import("beam");
pub fn foo(_: beam.env) void {}
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end

test "has the wrong return" do
assert_raise CompileError,
"nofile:2: on_unload callback foo with arity 1 must have `void` as a return. \n\n got: `f32`",
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnunload1Return do
use Zig,
otp_app: :zigler,
callbacks: [on_unload: :foo],
dir: unquote(__DIR__)

~Z"""
const beam = @import("beam");
pub fn foo(_: ?*anyopaque) f32 { return 0.0; }
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end
end

describe "compiler error when on_unload arity 2" do
test "has the wrong parameters" do
assert_raise CompileError,
"nofile:2: on_unload callback foo with arity 2 must have `beam.env` and `?*anyopaque` as parameters. \n\n got: `?*anyopaque`\n\n and: `?*anyopaque`",
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnload2Parameters do
use Zig,
otp_app: :zigler,
callbacks: [on_unload: :foo],
dir: unquote(__DIR__)

~Z"""
const beam = @import("beam");
pub fn foo(_: ?*anyopaque, _: ?*anyopaque) void { return 0.0; }
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end

test "has the wrong return" do
assert_raise CompileError,
"nofile:3: on_unload callback foo with arity 2 must have `void` as a return. \n\n got: `f32`",
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnload2Return do
use Zig,
otp_app: :zigler,
callbacks: [on_unload: :foo],
dir: unquote(__DIR__)

~Z"""
const beam = @import("beam");
const e = @import("erl_nif");
pub fn foo(_: beam.env, _: ?*anyopaque) f32 { return 0.0; }
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end
end
end
37 changes: 37 additions & 0 deletions test/integration/callbacks/on_unload_missing_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule ZiglerTest.Callbacks.OnUnloadMissingTest do
use ZiglerTest.IntegrationCase, async: true

test "compiler error when on_unload function is missing" do
assert_raise CompileError, "nofile: on_unload callback foo not found", fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.OnunloadMissing do
use Zig, otp_app: :zigler, callbacks: [on_unload: :foo], dir: unquote(__DIR__)

~Z"""
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end

test "compiler error when on_unload function is not pub" do
assert_raise CompileError, "nofile:2: on_unload callback foo must be declared `pub`", fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.OnunloadNotPub do
use Zig, otp_app: :zigler, callbacks: [on_unload: :foo], dir: unquote(__DIR__)

~Z"""
const beam = @import("beam");
fn foo(_: [*c]?*anyopaque) void {}
pub fn bar() u8 { return 47; }
"""
end
end
)
end
end
end
10 changes: 5 additions & 5 deletions test/integration/callbacks/on_upgrade_malformed_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMalformedTest do
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnloadArity do
defmodule ZiglerTest.BadOnupgradeArity do
use Zig,
otp_app: :zigler,
callbacks: [on_upgrade: :foo],
Expand All @@ -33,7 +33,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMalformedTest do
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnload2Parameters do
defmodule ZiglerTest.BadOnupgrade3Parameters do
use Zig,
otp_app: :zigler,
callbacks: [on_upgrade: :foo],
Expand All @@ -56,7 +56,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMalformedTest do
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnload2Return do
defmodule ZiglerTest.BadOnupgrade3Return do
use Zig,
otp_app: :zigler,
callbacks: [on_upgrade: :foo],
Expand All @@ -81,7 +81,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMalformedTest do
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnload3Parameters do
defmodule ZiglerTest.BadOnupgrade4Parameters do
use Zig,
otp_app: :zigler,
callbacks: [on_upgrade: :foo],
Expand All @@ -104,7 +104,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMalformedTest do
fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.BadOnload3Return do
defmodule ZiglerTest.BadOnupgrade4Return do
use Zig,
otp_app: :zigler,
callbacks: [on_upgrade: :foo],
Expand Down
4 changes: 2 additions & 2 deletions test/integration/callbacks/on_upgrade_missing_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMissingTest do
assert_raise CompileError, "nofile: on_upgrade callback foo not found", fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.OnLoadMissing do
defmodule ZiglerTest.OnUpgradeMissing do
use Zig, otp_app: :zigler, callbacks: [on_upgrade: :foo], dir: unquote(__DIR__)

~Z"""
Expand All @@ -21,7 +21,7 @@ defmodule ZiglerTest.Callbacks.OnUpgradeMissingTest do
assert_raise CompileError, "nofile:2: on_upgrade callback foo must be declared `pub`", fn ->
Code.compile_quoted(
quote do
defmodule ZiglerTest.OnLoadNotPub do
defmodule ZiglerTest.OnUpgradeNotPub do
use Zig, otp_app: :zigler, callbacks: [on_upgrade: :foo], dir: unquote(__DIR__)

~Z"""
Expand Down

0 comments on commit e59597c

Please sign in to comment.