Compare commits
8 Commits
v0.9.1
...
fcf85077b2
| Author | SHA1 | Date | |
|---|---|---|---|
| fcf85077b2 | |||
| 4530fd2e93 | |||
| 2a7079129f | |||
| 88aeb39d4a | |||
| f0f86ed36d | |||
| ed252b4c06 | |||
| 5dcc05d56a | |||
| 2eca3a5338 |
+11
-3
@@ -788,9 +788,9 @@ contract_code(ID) ->
|
||||
Result :: {ok, Source}
|
||||
| {project, Bundle}
|
||||
| {error, Reason},
|
||||
Source :: string(),
|
||||
Source :: binary(),
|
||||
Bundle :: [{FilePath :: string(), Contents :: binary()}],
|
||||
Reason :: chain_error() | string().
|
||||
Reason :: chain_error() | string().
|
||||
%% @doc
|
||||
%% Retrieve the code of a contract as represented on chain.
|
||||
|
||||
@@ -809,6 +809,8 @@ extract(Blobby) ->
|
||||
|
||||
extract2(TarBaby) ->
|
||||
case erl_tar:extract({binary, TarBaby}, [memory, compressed]) of
|
||||
{ok, [{_, Source}]} ->
|
||||
{ok, Source};
|
||||
{ok, Bundle} ->
|
||||
{project, Bundle};
|
||||
Error ->
|
||||
@@ -895,6 +897,12 @@ request(Path) ->
|
||||
hz_man:request(unicode:characters_to_list(Path)).
|
||||
|
||||
|
||||
-spec request(Path, Payload) -> {ok, Value} | {error, Reason}
|
||||
when Path :: unicode:charlist(),
|
||||
Payload :: unicode:charlist(),
|
||||
Value :: map(),
|
||||
Reason :: hz:chain_error().
|
||||
|
||||
request(Path, Payload) ->
|
||||
hz_man:request(unicode:characters_to_list(Path), Payload).
|
||||
|
||||
@@ -930,7 +938,7 @@ contract_create(CreatorID, Path, InitArgs) ->
|
||||
Gas = 500000,
|
||||
GasPrice = min_gas_price(),
|
||||
contract_create(CreatorID, Nonce,
|
||||
Amount, TTL, Gas, GasPrice,
|
||||
Gas, GasPrice, Amount, TTL,
|
||||
Path, InitArgs);
|
||||
Error ->
|
||||
Error
|
||||
|
||||
+60
-9
@@ -796,6 +796,10 @@ coerce_map_to_record(O, N, MemberTypes, Map) ->
|
||||
case zip_record_fields(MemberTypes, Map) of
|
||||
{ok, Zipped} ->
|
||||
case coerce_zipped_bindings(Zipped, to_fate, field) of
|
||||
{ok, [SingleElem]} ->
|
||||
% Singleton records aren't implemented as FATE tuples at
|
||||
% all.
|
||||
{ok, SingleElem};
|
||||
{ok, Converted} ->
|
||||
{ok, {tuple, list_to_tuple(Converted)}};
|
||||
Errors ->
|
||||
@@ -821,10 +825,18 @@ coerce_record_to_map(O, N, MemberTypes, Tuple) ->
|
||||
single_error({record_too_few_terms, O, N, Tuple});
|
||||
{error, too_many_terms} ->
|
||||
single_error({record_too_many_terms, O, N, Tuple});
|
||||
Errors ->
|
||||
Errors
|
||||
{error, Errors} ->
|
||||
correct_record_error_paths(Names, Errors)
|
||||
end.
|
||||
|
||||
correct_record_error_paths(Names, Errors) ->
|
||||
CorrectOne = fun({Error, [{record_element, N} | Path]}) ->
|
||||
FieldName = lists:nth(N + 1, Names),
|
||||
{Error, [{record_element, N, FieldName} | Path]}
|
||||
end,
|
||||
Corrected = lists:map(CorrectOne, Errors),
|
||||
{error, Corrected}.
|
||||
|
||||
zip_record_fields(Fields, Map) ->
|
||||
case lists:mapfoldl(fun zip_record_field/2, {Map, []}, Fields) of
|
||||
{_, {_, Missing = [_|_]}} ->
|
||||
@@ -915,6 +927,11 @@ fate_to_erlang({O, N, {variant, Variants}}, {variant, _, Tag, Tuple}) ->
|
||||
Terms = tuple_to_list(Tuple),
|
||||
{Name, TermTypes} = lists:nth(Tag + 1, Variants),
|
||||
coerce_variant2(O, N, Variants, Name, Tag, TermTypes, Terms, from_fate);
|
||||
fate_to_erlang({O, N, {record, [SingleMemberType]}}, Data) ->
|
||||
% Singleton records aren't implemented as FATE tuples at all.
|
||||
% Pretend they are, so we can get the full error indexing of the
|
||||
% non-singletone case.
|
||||
coerce_record_to_map(O, N, [SingleMemberType], {Data});
|
||||
fate_to_erlang({O, N, {record, MemberTypes}}, {tuple, Tuple}) ->
|
||||
coerce_record_to_map(O, N, MemberTypes, Tuple);
|
||||
fate_to_erlang({O, N, {unknown_type, _}}, Data) ->
|
||||
@@ -927,15 +944,30 @@ fate_to_erlang({O, N, {unknown_type, _}}, Data) ->
|
||||
io:format(Message, [O, N, Data])
|
||||
end,
|
||||
{ok, Data};
|
||||
fate_to_erlang({O, N, _}, Data) ->
|
||||
case N of
|
||||
already_normalized ->
|
||||
io:format("Warning: Unimplemented type ~p.~nUsing term as is:~n~p~n", [O, Data]);
|
||||
_ ->
|
||||
io:format("Warning: Unimplemented type ~p (i.e. ~p).~nUsing term as is:~n~p~n", [O, N, Data])
|
||||
end,
|
||||
fate_to_erlang(Type, Data) ->
|
||||
TypeStr = type_to_iolist(Type),
|
||||
io:format("Warning: Could not coerce term into ~s. Using term as is: ~p~n", [TypeStr, Data]),
|
||||
{ok, Data}.
|
||||
|
||||
type_to_iolist({O, already_normalized, S}) ->
|
||||
% Already normalized. Example output:
|
||||
% type {map, [string, integer]}
|
||||
opaque_type_to_iolist(O, S);
|
||||
type_to_iolist({O, N, S}) ->
|
||||
% Type alias. Print the alias, and then print the normalized version in
|
||||
% parentheses. Example output:
|
||||
% type "my_alias" (i.e. record type {"my_record_type", [integer]})
|
||||
io_lib:format("type ~p (i.e. ~s)", [O, opaque_type_to_iolist(N, S)]).
|
||||
|
||||
opaque_type_to_iolist(N, {record, _}) ->
|
||||
% N is the name of a record definition.
|
||||
io_lib:format("record type ~p", [N]);
|
||||
opaque_type_to_iolist(N, {variant, _}) ->
|
||||
% N is the name of a variant definition.
|
||||
io_lib:format("variant type ~p", [N]);
|
||||
opaque_type_to_iolist(N, _) ->
|
||||
% N is some other constructive type.
|
||||
io_lib:format("type ~p", [N]).
|
||||
|
||||
|
||||
%%% AACI Getters
|
||||
@@ -1120,6 +1152,25 @@ record_substitution_test() ->
|
||||
{ok, {[], Output}} = get_function_signature(AACI, "f"),
|
||||
check_roundtrip(Output, #{"a" => 123, "b" => 456}, {tuple, {123, 456}}).
|
||||
|
||||
singleton_record_substitution_test() ->
|
||||
Contract = "
|
||||
contract C =
|
||||
record single('t) = { it: 't }
|
||||
entrypoint f(): single(int) = { it = 1 }
|
||||
entrypoint g(): single(single(int)) = { it = { it = 2 } }
|
||||
entrypoint h(): single(int * int) = { it = (3, 4) }
|
||||
",
|
||||
{ok, AACI} = aaci_from_string(Contract),
|
||||
{ok, {[], FOutput}} = get_function_signature(AACI, "f"),
|
||||
check_roundtrip(FOutput, #{"it" => 123}, 123),
|
||||
{ok, {[], GOutput}} = get_function_signature(AACI, "g"),
|
||||
check_roundtrip(GOutput, #{"it" => #{"it" => 123}}, 123),
|
||||
{ok, {[], HOutput}} = get_function_signature(AACI, "h"),
|
||||
check_roundtrip(HOutput, #{"it" => {123, 456}}, {tuple, {123, 456}}),
|
||||
% Also check that records have accurate paths, since the implementation for
|
||||
% record error paths is a bit fiddly.
|
||||
{error, [{{tuple_too_many_terms, _, _, _}, [{record_element, 0, "it"}]}]} = fate_to_erlang(HOutput, {tuple, {1, 2, 3}}).
|
||||
|
||||
tuple_substitution_test() ->
|
||||
Contract = "
|
||||
contract C =
|
||||
|
||||
Reference in New Issue
Block a user