diff --git a/src/hz.erl b/src/hz.erl index 2014adb..d255c24 100644 --- a/src/hz.erl +++ b/src/hz.erl @@ -1546,6 +1546,7 @@ opaque_type_name(Name) -> binary_to_list(Name). builtin_typedefs() -> #{"unit" => {[], {tuple, []}}, + "void" => {[], {variant, []}}, "hash" => {[], {bytes, [32]}}, "option" => {["'T"], {variant, [{"None", []}, {"Some", [{var, "'T"}]}]}}, @@ -1589,7 +1590,15 @@ builtin_typedefs() -> {"ChannelSnapshotSoloTx", [address]}, {"ContractCreateTx", [integer]}, {"ContractCallTx", [address, integer]}, - {"GAAttachTx", []}]}} + {"GAAttachTx", []}]}}, + "Chain.tx" => {[], {record, [{"paying_for", {"option", ["Chain.paying_for_tx"]}}, + {"ga_metas", {list, ["Chain.ga_meta_tx"]}}, + {"actor", address}, + {"fee", integer}, + {"ttl", integer}, + {"tx", "Chain.base_tx"}]}}, + "MCL_BLS12_381.fr" => {[], {bytes, [32]}}, + "MCL_BLS12_381.fp" => {[], {bytes, [48]}} }. % Type preparation has two goals. First, we need a data structure that can be @@ -1701,12 +1710,6 @@ normalize_opaque_type(T, Types) -> normalize_opaque_type(T, Types, true). % FIXME detect infinite loops % FIXME detect builtins with the wrong number of arguments % FIXME should nullary types have an empty list of arguments added before now? -% These types represent some FATE variant: -% Chain.ttl, AENS.pointee, AENS.name, AENSv2.pointee, AENSv2.name, -% Chain.ga_meta_tx, Chain.paying_for_tx, Chain.base_tx, -% -% And then MCL_BLS12_381.fr represent bytes(32), and MCL_BLS12_381.fp -% represents bytes(48). normalize_opaque_type(T, _Types, IsFirst) when is_atom(T) -> % Once we have eliminated the above rewrite cases, all other cases are % handled explicitly by the coerce logic, and so are considered normalized. @@ -2715,6 +2718,7 @@ param_test() -> obscure_aaci_test() -> Contract = " + include \"Set.aes\" contract C = entrypoint options(): option(int) = None entrypoint fixed_bytes(): bytes(4) = #DEADBEEF @@ -2741,6 +2745,11 @@ obscure_aaci_test() -> entrypoint pointee2(x): AENSv2.pointee = AENSv2.DataPt(x) entrypoint name2(x, y, z): AENSv2.name = AENSv2.Name(x, y, z) + entrypoint fr(x): MCL_BLS12_381.fr = x + entrypoint fp(x): MCL_BLS12_381.fp = x + + entrypoint set(): Set.set(int) = Set.new() + ", {ok, AACI} = aaci_from_string(Contract), @@ -2757,15 +2766,18 @@ obscure_aaci_test() -> {ok, {_, {"Chain.paying_for_tx", _, {variant, _}}}} = aaci_lookup_spec(AACI, "paying_for"), {ok, {_, {"Chain.ga_meta_tx", _, {variant, _}}}} = aaci_lookup_spec(AACI, "ga_meta_tx"), {ok, {_, {"Chain.base_tx", _, {variant, _}}}} = aaci_lookup_spec(AACI, "base_tx"), - % Why do the other types here get hard coded in the compiler, but this one - % doesn't? Should we be getting stdlib types from includes? - %{ok, {_, {"Chain.tx", _, {variant, _}}}} = aaci_lookup_spec(AACI, "tx"), + {ok, {_, {"Chain.tx", _, {record, _}}}} = aaci_lookup_spec(AACI, "tx"), {ok, {_, {"AENS.pointee", _, {variant, _}}}} = aaci_lookup_spec(AACI, "pointee"), {ok, {_, {"AENS.name", _, {variant, _}}}} = aaci_lookup_spec(AACI, "name"), {ok, {_, {"AENSv2.pointee", _, {variant, _}}}} = aaci_lookup_spec(AACI, "pointee2"), {ok, {_, {"AENSv2.name", _, {variant, _}}}} = aaci_lookup_spec(AACI, "name2"), + {ok, {_, {"MCL_BLS12_381.fr", _, {bytes, [32]}}}} = aaci_lookup_spec(AACI, "fr"), + {ok, {_, {"MCL_BLS12_381.fp", _, {bytes, [48]}}}} = aaci_lookup_spec(AACI, "fp"), + + {ok, {[], {{"Set.set", [integer]}, _, {record, [{"to_map", _}]}}}} = aaci_lookup_spec(AACI, "set"), + ok. name_coerce_test() -> @@ -2786,4 +2798,11 @@ name_coerce_test() -> NameFate = {variant, [3], 0, {AddrFate, TTLFate, #{<<"myname">> => PointeeFate}}}, try_coerce(Name, NameSoph, NameFate). +void_coerce_test() -> + % Void itself can't be represented, but other types built out of void are + % valid. + {ok, NonOption} = annotate_type({"option", ["void"]}, builtin_typedefs()), + try_coerce(NonOption, {"None"}, {variant, [0, 1], 0, {}}), + {ok, NonList} = annotate_type({list, ["void"]}, builtin_typedefs()), + try_coerce(NonList, [], []).