Skip to content

Commit

Permalink
gets basic resource and basic cleanup up and running
Browse files Browse the repository at this point in the history
  • Loading branch information
ityonemo committed May 10, 2024
1 parent 57492ef commit 723c604
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 139 deletions.
25 changes: 16 additions & 9 deletions lib/zig/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,30 @@ defmodule Zig.Compiler do
end

defp adjust_elixir_options(opts) do
Map.update!(opts, :nifs, &replace_nif_dots/1)
Map.update!(opts, :nifs, &nif_substitution/1)
end

# if the elixir `nif` option contains `...` then this should be converted
# into `{:auto, <other_options>}`. This function will reverse the list, but
# since order doesn't matter for this option, it is okay.
defp replace_nif_dots({:auto, _} = auto), do: auto

defp replace_nif_dots(opts) do
# into `{:auto, <other_options>}`. Also, if the nif entry is just an atom,
# converts that entry into `{nif, []}`
#
# This function will reverse the list, but since order doesn't matter for this
# option, it is okay.
defp nif_substitution({:auto, _} = auto), do: auto

defp nif_substitution(opts) do
Enum.reduce(opts, [], fn
{:..., _, _}, {:auto, list} -> {:auto, list}
{:..., _, _}, {:auto, list} = so_far -> so_far
{:..., _, _}, list -> {:auto, list}
other, {:auto, list} -> {:auto, [other | list]}
other, list -> [other | list]
other, so_far -> prepend_nif(so_far, other)
end)
end

defp prepend_nif({:auto, so_far}, nif_name) when is_atom(nif_name), do: {:auto, [{nif_name, []} | so_far]}
defp prepend_nif(so_far, nif_name) when is_atom(nif_name), do: [{nif_name, []} | so_far]
defp prepend_nif({:auto, so_far}, nif_info), do: {:auto, [nif_info | so_far]}
defp prepend_nif(so_far, nif_info), do: [nif_info | so_far]

# note that this function is made public so that it can be both accessed
# from the :zigler entrypoint for erlang parse transforms, as well as the
# __before_compile__ entrypoint for Elixir
Expand Down
3 changes: 3 additions & 0 deletions lib/zig/type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,7 @@ defimpl Zig.Type, for: Atom do
term()
end
end

def marshal_param(_, _, _, _), do: Type._default_marshal()
def marshal_return(_, _, _), do: Type._default_marshal()
end
5 changes: 5 additions & 0 deletions lib/zig/type/resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ defmodule Zig.Type.Resource do

def return_allowed?(_resource), do: true
def param_allowed?(_), do: true

def render_payload_options(_, _, _), do: Type._default_payload_options()
def render_return(_, _), do: Type._default_return()
def marshal_param(_, _, _, _), do: Type._default_marshal()
def marshal_return(_, _, _), do: Type._default_marshal()
end
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ defmodule Zigler.MixProject do
{:jason, "~> 1.4"},
# zig parser is pinned to a version of zig parser because versions of zig parser
# are pinned to zig versions
{:zig_parser, "~> 0.3.0"},
{:zig_parser, "~> 0.4.0"},
# utility to help manage type protocols
{:protoss, "~> 0.1.1"},
# documentation
{:ex_doc, "~> 0.30.0", only: :dev, runtime: false},
{:zig_doc, "~> 0.3.1", only: :dev, runtime: false}
#{:zig_doc, "~> 0.3.1", only: :dev, runtime: false}
]
end
end
18 changes: 9 additions & 9 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
%{
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"credo": {:hex, :credo, "1.7.6", "b8f14011a5443f2839b04def0b252300842ce7388f3af177157c86da18dfbeea", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "146f347fb9f8cbc5f7e39e3f22f70acbef51d441baa6d10169dd604bfbc55296"},
"dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"},
"earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"},
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"pegasus": {:hex, :pegasus, "0.2.4", "3d8d5a2c89552face9c7ca14f959cc6c6d2cd645db1df85940db4c77c3b21a24", [:mix], [{:nimble_parsec, "~> 1.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2d21e2b6b946fe3cd441544bf9856e7772f29050332f0255e166a13cdbe65bb4"},
"protoss": {:hex, :protoss, "0.1.1", "c698bc4e08b5fc01fc23fc61ed44fd9fbf4536743748e28fa8df408284e14c2f", [:mix], [], "hexpm", "56abeda35c04d56a1419486b3c8f32e8f5ec3fd296668b13418002e8c509910f"},
"zig_doc": {:hex, :zig_doc, "0.3.1", "62db35ee8da67f2835f8229c91762836a0fe06d1a88e53fbfa7764e0e6d56d59", [:mix], [{:ex_doc, "~> 0.30.9", [hex: :ex_doc, repo: "hexpm", optional: false]}, {:zig_parser, "~> 0.3.0", [hex: :zig_parser, repo: "hexpm", optional: false]}], "hexpm", "566bd4375536e81f6157811d875cb413b3b73eb52b12bbc162291085e63f7091"},
"zig_parser": {:hex, :zig_parser, "0.3.0", "2a597ae6990447e70e46691d9ca7073afb3c3e13ab143dce1df0865a764c48f4", [:mix], [{:pegasus, "~> 0.2.4", [hex: :pegasus, repo: "hexpm", optional: false]}], "hexpm", "6b90ee53cf23e53824dbdad2d2ca597a1cb8d882b0748638921bddda1563a736"},
"zig_parser": {:hex, :zig_parser, "0.4.0", "5230576fcea30c061f08f6053448ad3dc5194a45485065564a7f8047bb351ce9", [:mix], [{:pegasus, "~> 0.2.4", [hex: :pegasus, repo: "hexpm", optional: false]}], "hexpm", "ec54cf14e80a1485e29a80b42756d0421426db81eb9e2630721fd46ab5c21bcb"},
}
115 changes: 56 additions & 59 deletions test/integration/resource/basic_test.exs
Original file line number Diff line number Diff line change
@@ -1,63 +1,60 @@
defmodule ZiglerTest.Resource.BasicTest do
use ZiglerTest.IntegrationCase, async: true

@moduletag :resource
test "restore"

# use Zig, otp_app: :zigler, resources: [:StructResource, :U64Resource]
#
# ~Z"""
# const beam = @import("beam");
# const Resource = beam.Resource;
# const root = @import("root");
#
# pub const Struct = struct {
# payload: u64,
# };
#
# pub const StructResource = Resource(Struct, root, .{});
# pub const U64Resource = Resource(u64, root, .{});
#
# pub fn new_scalar(resource: u64) U64Resource {
# return U64Resource.create(resource, .{}) catch unreachable;
# }
#
# pub fn unpack_scalar(resource: U64Resource) u64 {
# return resource.unpack();
# }
#
# pub fn increment_scalar(resource: U64Resource) void {
# const to_increment = resource.unpack();
# return resource.update(to_increment + 1);
# }
#
# pub fn new_struct(s: Struct) StructResource {
# return StructResource.create(s, .{}) catch unreachable;
# }
#
# pub fn unpack_struct(resource: StructResource) Struct {
# return resource.unpack();
# }
#
# pub fn increment_struct(resource: StructResource) void {
# const to_increment_struct = resource.unpack();
# return resource.update(.{.payload = to_increment_struct.payload + 1});
# }
# """
#
# test "basic scalar resources work" do
# res = new_scalar(47)
# assert is_reference(res)
# assert 47 = unpack_scalar(res)
# increment_scalar(res)
# assert 48 = unpack_scalar(res)
# end
#
# test "basic struct resources work" do
# res = new_struct(%{payload: 47})
# assert is_reference(res)
# assert %{payload: 47} = unpack_struct(res)
# increment_struct(res)
# assert %{payload: 48} = unpack_struct(res)
# end
use Zig, otp_app: :zigler, resources: [:StructResource, :U64Resource]

~Z"""
const beam = @import("beam");
const Resource = beam.Resource;
const root = @import("root");
pub const Struct = struct {
payload: u64,
};
pub const StructResource = Resource(Struct, root, .{});
pub const U64Resource = Resource(u64, root, .{});
pub fn new_scalar(resource: u64) U64Resource {
return U64Resource.create(resource, .{}) catch unreachable;
}
pub fn unpack_scalar(resource: U64Resource) u64 {
return resource.unpack();
}
pub fn increment_scalar(resource: U64Resource) void {
const to_increment = resource.unpack();
return resource.update(to_increment + 1);
}
pub fn new_struct(s: Struct) StructResource {
return StructResource.create(s, .{}) catch unreachable;
}
pub fn unpack_struct(resource: StructResource) Struct {
return resource.unpack();
}
pub fn increment_struct(resource: StructResource) void {
const to_increment_struct = resource.unpack();
return resource.update(.{.payload = to_increment_struct.payload + 1});
}
"""

test "basic scalar resources work" do
res = new_scalar(47)
assert is_reference(res)
assert 47 = unpack_scalar(res)
increment_scalar(res)
assert 48 = unpack_scalar(res)
end

test "basic struct resources work" do
res = new_struct(%{payload: 47})
assert is_reference(res)
assert %{payload: 47} = unpack_struct(res)
increment_struct(res)
assert %{payload: 48} = unpack_struct(res)
end
end
117 changes: 57 additions & 60 deletions test/integration/resource/cleanup_test.exs
Original file line number Diff line number Diff line change
@@ -1,63 +1,60 @@
defmodule ZiglerTest.Resource.CleanupTest do
use ZiglerTest.IntegrationCase, async: true

@moduletag :resource
test "restore"

#use Zig,
# otp_app: :zigler,
# resources: [:PidResource],
# nifs: [
# :create_released,
# maybe_release: [args: [[cleanup: false], []]]
# ]
#
#~Z"""
#const beam = @import("beam");
#const std = @import("std");
#const Resource = beam.Resource;
#
#pub const PidResource = Resource(beam.pid, @import("root"), .{.Callbacks = PidResourceCallbacks});
#
#pub const PidResourceCallbacks = struct {
# pub fn dtor(pid: *beam.pid) void {
# _ = beam.send(pid.*, .cleaned, .{.clean = false}) catch unreachable;
# }
#};
#
#pub fn create_released(pid: beam.pid) PidResource {
# const resource = PidResource.create(pid, .{}) catch unreachable;
# return resource;
#}
#
#pub fn maybe_release(resource: PidResource, release: bool) void {
# if (release) {
# resource.release();
# }
#}
#"""
#
#test "a function call will keep resources, with no cleanup it doesn't release" do
# this = self()
#
# spawn(fn ->
# this
# |> create_released()
# |> maybe_release(false)
# end)
#
# refute_receive :cleaned, 500
#end
#
#test "a function call will keep resources, you can manually release" do
# this = self()
#
# spawn(fn ->
# this
# |> create_released()
# |> maybe_release(true)
# end)
#
# assert_receive :cleaned, 100
#end
end
use Zig,
otp_app: :zigler,
resources: [:PidResource],
nifs: [
:create_released,
maybe_release: [args: [[cleanup: false], []]]
]

~Z"""
const beam = @import("beam");
const std = @import("std");
const Resource = beam.Resource;
pub const PidResource = Resource(beam.pid, @import("root"), .{.Callbacks = PidResourceCallbacks});
pub const PidResourceCallbacks = struct {
pub fn dtor(pid: *beam.pid) void {
_ = beam.send(pid.*, .cleaned, .{.clean = false}) catch unreachable;
}
};
pub fn create_released(pid: beam.pid) PidResource {
const resource = PidResource.create(pid, .{}) catch unreachable;
return resource;
}
pub fn maybe_release(resource: PidResource, release: bool) void {
if (release) {
resource.release();
}
}
"""

test "a function call will keep resources, with no cleanup it doesn't release" do
this = self()

spawn(fn ->
this
|> create_released()
|> maybe_release(false)
end)

refute_receive :cleaned, 500
end

test "a function call will keep resources, you can manually release" do
this = self()

spawn(fn ->
this
|> create_released()
|> maybe_release(true)
end)

assert_receive :cleaned, 100
end
end

0 comments on commit 723c604

Please sign in to comment.