From 4e71d3215baee9d81ef1b0ea42b515cc306b37ed Mon Sep 17 00:00:00 2001 From: SpiveeWorks Date: Wed, 29 Jan 2025 19:16:44 +1100 Subject: [PATCH] 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. --- src/hz.erl | 60 ++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/src/hz.erl b/src/hz.erl index 4cefd8d..664baf1 100644 --- a/src/hz.erl +++ b/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) ->