Factor handling of different ACI typedef cases

A lot of this complexity was a consequence of trying to avoid redundant
extraction of the namespace's/contract's name, so on the other hand
letting it be redundant made all of the complexity kind of evaporate.
Add to that that we're now building a little deep list and then
flattening it, and this logic was able to get really neat in a way that
I couldn't work out a year ago.
This commit is contained in:
SpiveeWorks 2025-01-29 19:16:44 +11:00
parent c27005c424
commit 4e71d3215b

View File

@ -1457,30 +1457,38 @@ convert_arg(#{name := NameBin, type := TypeDef}) ->
{Name, Type}.
convert_namespace_typedefs(#{namespace := NS}) ->
convert_namespace_typedefs2(NS, false);
Name = namespace_name(NS),
convert_typedefs(NS, Name);
convert_namespace_typedefs(#{contract := NS}) ->
convert_namespace_typedefs2(NS, true).
Name = namespace_name(NS),
ImplicitTypes = convert_implicit_types(NS, Name),
ExplicitTypes = convert_typedefs(NS, Name),
[ImplicitTypes, ExplicitTypes].
convert_namespace_typedefs2(NS, IsContract) ->
TypeDefs = maps:get(typedefs, NS),
NameBin = maps:get(name, NS),
Name = binary_to_list(NameBin),
ContractAsType = case IsContract of
true -> {Name, [], contract};
false -> []
end,
State = case maps:find(state, NS) of
{ok, StateDefACI} ->
StateDefOpaque = opaque_type([], StateDefACI),
{Name ++ ".state", [], StateDefOpaque};
error ->
[]
end,
ExplicitTypeDefs = convert_explicit_typedefs(TypeDefs, Name ++ ".", []),
% Throw all the weird sources of types into one messy deeplist.
[ContractAsType, State, ExplicitTypeDefs].
namespace_name(#{name := NameBin}) ->
binary_to_list(NameBin).
convert_implicit_types(#{state := StateDefACI}, Name) ->
StateDefOpaque = opaque_type([], StateDefACI),
[{Name, [], contract},
{Name ++ ".state", [], StateDefOpaque}];
convert_implicit_types(_, Name) ->
[{Name, [], contract}].
convert_typedefs(#{typedefs := TypeDefs}, Name) ->
convert_typedefs_loop(TypeDefs, Name ++ ".", []).
% Take a namespace that has already had a period appended, and use that as a
% prefix to convert and annotate a list of types.
convert_typedefs_loop([], _NamePrefix, Converted) ->
Converted;
convert_typedefs_loop([Next | Rest], NamePrefix, Converted) ->
#{name := NameBin, vars := ParamDefs, typedef := DefACI} = Next,
Name = NamePrefix ++ binary_to_list(NameBin),
Params = [binary_to_list(Param) || #{name := Param} <- ParamDefs],
Def = opaque_type(Params, DefACI),
convert_typedefs_loop(Rest, NamePrefix, [Converted, {Name, Params, Def}]).
% The easiest step, turn a deep list of opaque types into a map.
collect_opaque_types([], Types) ->
Types;
collect_opaque_types([L | R], Types) ->
@ -1489,16 +1497,6 @@ collect_opaque_types([L | R], Types) ->
collect_opaque_types({Name, Params, Def}, Types) ->
maps:put(Name, {Params, Def}, Types).
convert_explicit_typedefs([], _NamePrefix, Converted) ->
Converted;
convert_explicit_typedefs([Next | Rest], NamePrefix, Converted) ->
#{name := NameBin, vars := ParamDefs, typedef := DefACI} = Next,
Name = NamePrefix ++ binary_to_list(NameBin),
Params = [binary_to_list(Param) || #{name := Param} <- ParamDefs],
Def = opaque_type(Params, DefACI),
convert_explicit_typedefs(Rest, NamePrefix, [Converted, {Name, Params, Def}]).
% Convert an ACI type defintion/spec into the 'opaque type' representation that
% our dereferencing algorithms can reason about.
opaque_type(Params, NameBin) when is_binary(NameBin) ->