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:
parent
c27005c424
commit
4e71d3215b
60
src/hz.erl
60
src/hz.erl
@ -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) ->
|
||||
|
Loading…
x
Reference in New Issue
Block a user