Rename 'flatten' and so on to 'annotate'
This commit is contained in:
parent
ad7be7c8db
commit
c27005c424
108
src/hz.erl
108
src/hz.erl
@ -1414,19 +1414,13 @@ prepare_aaci(ACI) ->
|
||||
{Name, OpaqueSpecs, TypeDefs} = convert_aci_types(ACI),
|
||||
|
||||
% Now that we have the opaque types, we can dereference the function specs
|
||||
% down to the concrete types they actually represent.
|
||||
Specs = expand_contract_specs(OpaqueSpecs, TypeDefs, #{}),
|
||||
% down to the concrete types they actually represent. We annotate each
|
||||
% subexpression of this concrete type with other info too, in case it helps
|
||||
% make error messages easier to understand.
|
||||
Specs = annotate_function_specs(OpaqueSpecs, TypeDefs, #{}),
|
||||
|
||||
{aaci, Name, Specs, TypeDefs}.
|
||||
|
||||
expand_contract_specs([], _Types, Specs) ->
|
||||
Specs;
|
||||
expand_contract_specs([{Name, ArgsOpaque, ResultOpaque} | Rest], Types, Specs) ->
|
||||
{ok, Args} = flatten_opaque_types(ArgsOpaque, Types, []),
|
||||
{ok, Result} = flatten_opaque_type(ResultOpaque, Types),
|
||||
NewSpecs = maps:put(Name, {Args, Result}, Specs),
|
||||
expand_contract_specs(Rest, Types, NewSpecs).
|
||||
|
||||
convert_aci_types(ACI) ->
|
||||
% Find the main contract, so we can get the specifications of its
|
||||
% entrypoints.
|
||||
@ -1552,10 +1546,10 @@ opaque_type_name(Name) -> binary_to_list(Name).
|
||||
% together form an 'annotated type'. First, we need the fully opaque name,
|
||||
% "bazquux", then we need the normalized name, which is an opaque name with the
|
||||
% bare-minimum substitution needed to make the outer-most type-constructor an
|
||||
% identifiable built-in, ADT, or record type, and then we need the flattened
|
||||
% identifiable built-in, ADT, or record type, and then we need the dereferenced
|
||||
% type, which is the raw {variant, [{Name, Fields}, ...]} or
|
||||
% {record, [{Name, Type}]} expression that can be used in actual Sophia->FATE
|
||||
% coercion. The type sub-expressions in these flattened types will each be
|
||||
% coercion. The type sub-expressions in these dereferenced types will each be
|
||||
% fully annotated as well, i.e. they will each contain *all three* of the above
|
||||
% representations, so that coercion of subexpressions remains fast AND
|
||||
% informative.
|
||||
@ -1566,16 +1560,24 @@ opaque_type_name(Name) -> binary_to_list(Name).
|
||||
% can simply render the normalized type expression and know that the error will
|
||||
% make sense.
|
||||
|
||||
flatten_opaque_type(T, Types) ->
|
||||
annotate_function_specs([], _Types, Specs) ->
|
||||
Specs;
|
||||
annotate_function_specs([{Name, ArgsOpaque, ResultOpaque} | Rest], Types, Specs) ->
|
||||
{ok, Args} = annotate_types(ArgsOpaque, Types, []),
|
||||
{ok, Result} = annotate_type(ResultOpaque, Types),
|
||||
NewSpecs = maps:put(Name, {Args, Result}, Specs),
|
||||
annotate_function_specs(Rest, Types, NewSpecs).
|
||||
|
||||
annotate_type(T, Types) ->
|
||||
case normalize_opaque_type(T, Types) of
|
||||
{ok, AlreadyNormalized, NOpaque, NExpanded} ->
|
||||
flatten_opaque_type2(T, AlreadyNormalized, NOpaque, NExpanded, Types);
|
||||
annotate_type2(T, AlreadyNormalized, NOpaque, NExpanded, Types);
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
flatten_opaque_type2(T, AlreadyNormalized, NOpaque, NExpanded, Types) ->
|
||||
case flatten_normalized_type(NExpanded, Types) of
|
||||
annotate_type2(T, AlreadyNormalized, NOpaque, NExpanded, Types) ->
|
||||
case annotate_type_subexpressions(NExpanded, Types) of
|
||||
{ok, Flat} ->
|
||||
case AlreadyNormalized of
|
||||
true -> {ok, {T, already_normalized, Flat}};
|
||||
@ -1585,48 +1587,48 @@ flatten_opaque_type2(T, AlreadyNormalized, NOpaque, NExpanded, Types) ->
|
||||
Error
|
||||
end.
|
||||
|
||||
flatten_opaque_types([T | Rest], Types, Acc) ->
|
||||
case flatten_opaque_type(T, Types) of
|
||||
{ok, Type} -> flatten_opaque_types(Rest, Types, [Type | Acc]);
|
||||
annotate_types([T | Rest], Types, Acc) ->
|
||||
case annotate_type(T, Types) of
|
||||
{ok, Type} -> annotate_types(Rest, Types, [Type | Acc]);
|
||||
Error -> Error
|
||||
end;
|
||||
flatten_opaque_types([], _Types, Acc) ->
|
||||
annotate_types([], _Types, Acc) ->
|
||||
{ok, lists:reverse(Acc)}.
|
||||
|
||||
flatten_opaque_bindings([{Name, T} | Rest], Types, Acc) ->
|
||||
case flatten_opaque_type(T, Types) of
|
||||
{ok, Type} -> flatten_opaque_bindings(Rest, Types, [{Name, Type} | Acc]);
|
||||
Error -> Error
|
||||
end;
|
||||
flatten_opaque_bindings([], _Types, Acc) ->
|
||||
{ok, lists:reverse(Acc)}.
|
||||
|
||||
flatten_opaque_variants([{Name, Elems} | Rest], Types, Acc) ->
|
||||
case flatten_opaque_types(Elems, Types, []) of
|
||||
{ok, ElemsFlat} -> flatten_opaque_variants(Rest, Types, [{Name, ElemsFlat} | Acc]);
|
||||
Error -> Error
|
||||
end;
|
||||
flatten_opaque_variants([], _Types, Acc) ->
|
||||
{ok, lists:reverse(Acc)}.
|
||||
|
||||
flatten_normalized_type(PrimitiveType, _Types) when is_atom(PrimitiveType) ->
|
||||
annotate_type_subexpressions(PrimitiveType, _Types) when is_atom(PrimitiveType) ->
|
||||
{ok, PrimitiveType};
|
||||
flatten_normalized_type({variant, VariantsOpaque}, Types) ->
|
||||
case flatten_opaque_variants(VariantsOpaque, Types, []) of
|
||||
annotate_type_subexpressions({variant, VariantsOpaque}, Types) ->
|
||||
case annotate_variants(VariantsOpaque, Types, []) of
|
||||
{ok, Variants} -> {ok, {variant, Variants}};
|
||||
Error -> Error
|
||||
end;
|
||||
flatten_normalized_type({record, FieldsOpaque}, Types) ->
|
||||
case flatten_opaque_bindings(FieldsOpaque, Types, []) of
|
||||
annotate_type_subexpressions({record, FieldsOpaque}, Types) ->
|
||||
case annotate_bindings(FieldsOpaque, Types, []) of
|
||||
{ok, Fields} -> {ok, {record, Fields}};
|
||||
Error -> Error
|
||||
end;
|
||||
flatten_normalized_type({T, ElemsOpaque}, Types) ->
|
||||
case flatten_opaque_types(ElemsOpaque, Types, []) of
|
||||
annotate_type_subexpressions({T, ElemsOpaque}, Types) ->
|
||||
case annotate_types(ElemsOpaque, Types, []) of
|
||||
{ok, Elems} -> {ok, {T, Elems}};
|
||||
Error -> Error
|
||||
end.
|
||||
|
||||
annotate_bindings([{Name, T} | Rest], Types, Acc) ->
|
||||
case annotate_type(T, Types) of
|
||||
{ok, Type} -> annotate_bindings(Rest, Types, [{Name, Type} | Acc]);
|
||||
Error -> Error
|
||||
end;
|
||||
annotate_bindings([], _Types, Acc) ->
|
||||
{ok, lists:reverse(Acc)}.
|
||||
|
||||
annotate_variants([{Name, Elems} | Rest], Types, Acc) ->
|
||||
case annotate_types(Elems, Types, []) of
|
||||
{ok, ElemsFlat} -> annotate_variants(Rest, Types, [{Name, ElemsFlat} | Acc]);
|
||||
Error -> Error
|
||||
end;
|
||||
annotate_variants([], _Types, Acc) ->
|
||||
{ok, lists:reverse(Acc)}.
|
||||
|
||||
normalize_opaque_type(T, Types) ->
|
||||
case type_is_expanded(T) of
|
||||
false -> normalize_opaque_type(T, Types, true);
|
||||
@ -2228,11 +2230,11 @@ try_coerce(Type, Sophia, Fate) ->
|
||||
ok.
|
||||
|
||||
coerce_int_test() ->
|
||||
{ok, Type} = flatten_opaque_type(integer, #{}),
|
||||
{ok, Type} = annotate_type(integer, #{}),
|
||||
try_coerce(Type, 123, 123).
|
||||
|
||||
coerce_address_test() ->
|
||||
{ok, Type} = flatten_opaque_type(address, #{}),
|
||||
{ok, Type} = annotate_type(address, #{}),
|
||||
try_coerce(Type,
|
||||
"ak_2FTnrGfV8qsfHpaSEHpBrziioCpwwzLqSevHqfxQY3PaAAdARx",
|
||||
{address, <<164,136,155,90,124,22,40,206,255,76,213,56,238,123,
|
||||
@ -2240,7 +2242,7 @@ coerce_address_test() ->
|
||||
210,39,214>>}).
|
||||
|
||||
coerce_contract_test() ->
|
||||
{ok, Type} = flatten_opaque_type(contract, #{}),
|
||||
{ok, Type} = annotate_type(contract, #{}),
|
||||
try_coerce(Type,
|
||||
"ct_2FTnrGfV8qsfHpaSEHpBrziioCpwwzLqSevHqfxQY3PaAAdARx",
|
||||
{contract, <<164,136,155,90,124,22,40,206,255,76,213,56,238,123,
|
||||
@ -2248,35 +2250,35 @@ coerce_contract_test() ->
|
||||
210,39,214>>}).
|
||||
|
||||
coerce_bool_test() ->
|
||||
{ok, Type} = flatten_opaque_type(boolean, #{}),
|
||||
{ok, Type} = annotate_type(boolean, #{}),
|
||||
try_coerce(Type, true, true),
|
||||
try_coerce(Type, false, false).
|
||||
|
||||
coerce_string_test() ->
|
||||
{ok, Type} = flatten_opaque_type(string, #{}),
|
||||
{ok, Type} = annotate_type(string, #{}),
|
||||
try_coerce(Type, "hello world", <<"hello world">>).
|
||||
|
||||
coerce_list_test() ->
|
||||
{ok, Type} = flatten_opaque_type({list, [string]}, #{}),
|
||||
{ok, Type} = annotate_type({list, [string]}, #{}),
|
||||
try_coerce(Type, ["hello world", [65, 32, 65]], [<<"hello world">>, <<65, 32, 65>>]).
|
||||
|
||||
coerce_map_test() ->
|
||||
{ok, Type} = flatten_opaque_type({map, [string, {list, [integer]}]}, #{}),
|
||||
{ok, Type} = annotate_type({map, [string, {list, [integer]}]}, #{}),
|
||||
try_coerce(Type, #{"a" => "a", "b" => "b"}, #{<<"a">> => "a", <<"b">> => "b"}).
|
||||
|
||||
coerce_tuple_test() ->
|
||||
{ok, Type} = flatten_opaque_type({tuple, [integer, string]}, #{}),
|
||||
{ok, Type} = annotate_type({tuple, [integer, string]}, #{}),
|
||||
try_coerce(Type, {123, "456"}, {tuple, {123, <<"456">>}}).
|
||||
|
||||
coerce_variant_test() ->
|
||||
{ok, Type} = flatten_opaque_type({variant, [{"A", [integer]},
|
||||
{ok, Type} = annotate_type({variant, [{"A", [integer]},
|
||||
{"B", [integer, integer]}]},
|
||||
#{}),
|
||||
try_coerce(Type, {"A", 123}, {variant, [1, 2], 0, {123}}),
|
||||
try_coerce(Type, {"B", 456, 789}, {variant, [1, 2], 1, {456, 789}}).
|
||||
|
||||
coerce_record_test() ->
|
||||
{ok, Type} = flatten_opaque_type({record, [{"a", integer}, {"b", integer}]}, #{}),
|
||||
{ok, Type} = annotate_type({record, [{"a", integer}, {"b", integer}]}, #{}),
|
||||
try_coerce(Type, #{"a" => 123, "b" => 456}, {tuple, {123, 456}}).
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user