Address review, fix some dialyzer errors
This commit is contained in:
parent
7898d2a17d
commit
6789b739a5
@ -76,7 +76,9 @@
|
||||
-record(is_contract_constraint,
|
||||
{ contract_t :: utype(),
|
||||
context :: {contract_literal, aeso_syntax:expr()} |
|
||||
{address_to_contract, aeso_syntax:ann()}
|
||||
{address_to_contract, aeso_syntax:ann()} |
|
||||
{bytecode_hash, aeso_syntax:ann()} |
|
||||
{var_args, aeso_syntax:ann(), aeso_syntax:expr()}
|
||||
}).
|
||||
|
||||
-type field_constraint() :: #field_constraint{} | #record_create_constraint{} | #is_contract_constraint{}.
|
||||
@ -99,7 +101,7 @@
|
||||
-type qname() :: [string()].
|
||||
-type typesig() :: {type_sig, aeso_syntax:ann(), type_constraints(), [aeso_syntax:named_arg_t()], [type()], type()}.
|
||||
|
||||
-type type_constraints() :: none | bytes_concat | bytes_split | address_to_contract.
|
||||
-type type_constraints() :: none | bytes_concat | bytes_split | address_to_contract | bytecode_hash.
|
||||
|
||||
-type fun_info() :: {aeso_syntax:ann(), typesig() | type()}.
|
||||
-type type_info() :: {aeso_syntax:ann(), typedef()}.
|
||||
@ -284,9 +286,14 @@ bind_contract({Contract, Ann, Id, Contents}, Env)
|
||||
[ {field_t, Sys, {id, Sys, ?CONSTRUCTOR_MOCK_NAME},
|
||||
contract_call_type(
|
||||
case [ [ArgT || {typed, _, _, ArgT} <- Args]
|
||||
|| {letfun, _, {id, _, "init"}, Args, _, _} <- Contents]
|
||||
++ [ Args || {fun_decl, _, {id, _, "init"}, {fun_t, _, _, Args, _}} <- Contents]
|
||||
++ [ Args || {fun_decl, _, {id, _, "init"}, {type_sig, _, _, _, Args, _}} <- Contents]
|
||||
|| {letfun, AnnF, {id, _, "init"}, Args, _, _} <- Contents,
|
||||
aeso_syntax:get_ann(entrypoint, AnnF, false)]
|
||||
++ [ Args
|
||||
|| {fun_decl, AnnF, {id, _, "init"}, {fun_t, _, _, Args, _}} <- Contents,
|
||||
aeso_syntax:get_ann(entrypoint, AnnF, false)]
|
||||
++ [ Args
|
||||
|| {fun_decl, AnnF, {id, _, "init"}, {type_sig, _, _, _, Args, _}} <- Contents,
|
||||
aeso_syntax:get_ann(entrypoint, AnnF, false)]
|
||||
of
|
||||
[] -> {fun_t, [stateful,payable|Sys], [], [], {id, Sys, "void"}};
|
||||
[Args] -> {fun_t, [stateful,payable|Sys], [], Args, {id, Sys, "void"}}
|
||||
@ -804,7 +811,7 @@ identify_main_contract(Contracts) ->
|
||||
(Contracts -- Children) ++ [{contract_main, Ann, Con, Body}];
|
||||
_ -> type_error({ambiguous_main_contract})
|
||||
end;
|
||||
[_] -> Contracts;
|
||||
[_] -> (Contracts -- Mains) ++ Mains; %% Move to the end
|
||||
_ -> type_error({multiple_main_contracts})
|
||||
end.
|
||||
|
||||
@ -1615,15 +1622,20 @@ infer_var_args_fun(Env, {typed, Ann, Fun, FunType0}, NamedArgs, ArgTypes) ->
|
||||
{fun_t, _, NamedArgsT, var_args, RetT} = FunType0,
|
||||
GasCapMock = {named_arg_t, Ann, {id, Ann, "gas"}, {id, Ann, "int"}, {int, Ann, 0}},
|
||||
ProtectedMock = {named_arg_t, Ann, {id, Ann, "protected"}, {id, Ann, "bool"}, {bool, Ann, false}},
|
||||
|
||||
check_contract_construction(Env, RetT, Fun, [GasCapMock, ProtectedMock|NamedArgsT], ArgTypes, RetT),
|
||||
NamedArgsT1 = case NamedArgsT of
|
||||
[Value|Rest] -> [GasCapMock, Value, ProtectedMock|Rest];
|
||||
% generally type error, but will be caught
|
||||
_ -> [GasCapMock, ProtectedMock|NamedArgsT]
|
||||
end,
|
||||
check_contract_construction(Env, RetT, Fun, NamedArgsT1, ArgTypes, RetT),
|
||||
{fun_t, Ann, NamedArgsT, ArgTypes, RetT};
|
||||
{qid, _, ["Chain", "clone"]} ->
|
||||
{fun_t, _, NamedArgsT, var_args, RetT} = FunType0,
|
||||
ContractT =
|
||||
case [ContractT || {named_arg, _, {id, _, "ref"}, {typed, _, _, ContractT}} <- NamedArgs] of
|
||||
[C] -> C;
|
||||
_ -> type_error({clone_no_contract, Ann})
|
||||
_ -> type_error({clone_no_contract, Ann}),
|
||||
fresh_uvar(Ann)
|
||||
end,
|
||||
NamedArgsTNoRef =
|
||||
lists:filter(fun({named_arg_t, _, {id, _, "ref"}, _, _}) -> false; (_) -> true end, NamedArgsT),
|
||||
@ -1634,12 +1646,14 @@ infer_var_args_fun(Env, {typed, Ann, Fun, FunType0}, NamedArgs, ArgTypes) ->
|
||||
end,
|
||||
{typed, Ann, Fun, FunType}.
|
||||
|
||||
-spec check_contract_construction(env(), utype(), utype(), named_args_t(), [utype()], utype()) -> ok.
|
||||
check_contract_construction(Env, ContractT, Fun, NamedArgsT, ArgTypes, RetT) ->
|
||||
Ann = aeso_syntax:get_ann(Fun),
|
||||
InitT = fresh_uvar(Ann),
|
||||
unify(Env, InitT, {fun_t, Ann, NamedArgsT, ArgTypes, fresh_uvar(Ann)}, {checking_init_args, Ann, ContractT, ArgTypes}),
|
||||
unify(Env, RetT, ContractT, {return_contract, Fun, ContractT}),
|
||||
constrain([ #field_constraint{
|
||||
constrain(
|
||||
[ #field_constraint{
|
||||
record_t = unfold_types_in_type(Env, ContractT),
|
||||
field = {id, Ann, ?CONSTRUCTOR_MOCK_NAME},
|
||||
field_t = InitT,
|
||||
@ -1647,7 +1661,8 @@ check_contract_construction(Env, ContractT, Fun, NamedArgsT, ArgTypes, RetT) ->
|
||||
context = {var_args, Ann, Fun} }
|
||||
, #is_contract_constraint{ contract_t = ContractT,
|
||||
context = {var_args, Ann, Fun} }
|
||||
]).
|
||||
]),
|
||||
ok.
|
||||
|
||||
split_args(Args0) ->
|
||||
NamedArgs = [ Arg || Arg = {named_arg, _, _, _} <- Args0 ],
|
||||
@ -2430,15 +2445,10 @@ unify1(Env, {if_t, _, {id, _, Id}, Then1, Else1}, {if_t, _, {id, _, Id}, Then2,
|
||||
unify1(_Env, {fun_t, _, _, _, _}, {fun_t, _, _, var_args, _}, When) ->
|
||||
type_error({unify_varargs, When});
|
||||
unify1(_Env, {fun_t, _, _, var_args, _}, {fun_t, _, _, _, _}, When) ->
|
||||
error({unify_varargs, When});
|
||||
type_error({unify_varargs, When});
|
||||
unify1(Env, {fun_t, _, Named1, Args1, Result1}, {fun_t, _, Named2, Args2, Result2}, When)
|
||||
when length(Args1) == length(Args2) ->
|
||||
{Named1_, Named2_} =
|
||||
if is_list(Named1) andalso is_list(Named2) ->
|
||||
{lists:keysort(3, Named1), lists:keysort(3, Named2)};
|
||||
true -> {Named1, Named2}
|
||||
end,
|
||||
unify(Env, Named1_, Named2_, When) andalso
|
||||
unify(Env, Named1, Named2, When) andalso
|
||||
unify(Env, Args1, Args2, When) andalso unify(Env, Result1, Result2, When);
|
||||
unify1(Env, {app_t, _, {Tag, _, F}, Args1}, {app_t, _, {Tag, _, F}, Args2}, When)
|
||||
when length(Args1) == length(Args2), Tag == id orelse Tag == qid ->
|
||||
@ -2934,18 +2944,21 @@ mk_error({conflicting_updates_for_field, Upd, Key}) ->
|
||||
Msg = io_lib:format("Conflicting updates for field '~s'\n", [Key]),
|
||||
mk_t_err(pos(Upd), Msg);
|
||||
mk_error({ambiguous_main_contract}) ->
|
||||
Msg = "Could not deduce the main contract. You can point it manually with `main` keyword.",
|
||||
Msg = "Could not deduce the main contract. You can point it out manually with the `main` keyword.",
|
||||
mk_t_err(pos(0, 0), Msg);
|
||||
mk_error({main_contract_undefined}) ->
|
||||
Msg = "No contract defined.",
|
||||
Msg = "No contract defined.\n",
|
||||
mk_t_err(pos(0, 0), Msg);
|
||||
mk_error({multiple_main_contracts}) ->
|
||||
Msg = "Up to one main contract can be defined.",
|
||||
Msg = "Only one main contract can be defined.\n",
|
||||
mk_t_err(pos(0, 0), Msg);
|
||||
mk_error({unify_varargs, When}) ->
|
||||
Msg = io_lib:format("Cannot unify variable argument list.\n"),
|
||||
Msg = "Cannot unify variable argument list.\n",
|
||||
{Pos, Ctxt} = pp_when(When),
|
||||
mk_t_err(Pos, Msg, Ctxt);
|
||||
mk_error({clone_no_contract, Ann}) ->
|
||||
Msg = "Chain.clone requires `ref` named argument of contract type.\n",
|
||||
mk_t_err(pos(Ann), Msg);
|
||||
mk_error(Err) ->
|
||||
Msg = io_lib:format("Unknown error: ~p\n", [Err]),
|
||||
mk_t_err(pos(0, 0), Msg).
|
||||
@ -3096,15 +3109,15 @@ pp_when(unknown) -> {pos(0,0), ""}.
|
||||
pp_why_record({var_args, Ann, Fun}) ->
|
||||
{pos(Ann),
|
||||
io_lib:format("arising from resolution of variadic function ~s (at ~s)",
|
||||
[pp_expr("", Fun), pp_loc(Fun)])};
|
||||
[pp_expr(Fun), pp_loc(Fun)])};
|
||||
pp_why_record(Fld = {field, _Ann, LV, _E}) ->
|
||||
{pos(Fld),
|
||||
io_lib:format("arising from an assignment of the field ~s (at ~s)",
|
||||
[pp_expr("", {lvalue, [], LV}), pp_loc(Fld)])};
|
||||
[pp_expr({lvalue, [], LV}), pp_loc(Fld)])};
|
||||
pp_why_record(Fld = {field, _Ann, LV, _Alias, _E}) ->
|
||||
{pos(Fld),
|
||||
io_lib:format("arising from an assignment of the field ~s (at ~s)",
|
||||
[pp_expr("", {lvalue, [], LV}), pp_loc(Fld)])};
|
||||
[pp_expr({lvalue, [], LV}), pp_loc(Fld)])};
|
||||
pp_why_record({proj, _Ann, Rec, FldName}) ->
|
||||
{pos(Rec),
|
||||
io_lib:format("arising from the projection of the field ~s (at ~s)",
|
||||
|
@ -142,7 +142,7 @@
|
||||
-type child_con_env() :: #{sophia_name() => fcode()}.
|
||||
-type builtins() :: #{ sophia_name() => {builtin(), non_neg_integer() | none | variable} }.
|
||||
|
||||
-type context() :: {main_contract, string()}
|
||||
-type context() :: {contract_def, string()}
|
||||
| {namespace, string()}
|
||||
| {abstract_contract, string()}.
|
||||
|
||||
@ -158,7 +158,8 @@
|
||||
state_layout => state_layout(),
|
||||
context => context(),
|
||||
vars => [var_name()],
|
||||
functions := #{ fun_name() => fun_def() } }.
|
||||
functions := #{ fun_name() => fun_def() }
|
||||
}.
|
||||
|
||||
-define(HASH_BYTES, 32).
|
||||
|
||||
@ -166,7 +167,7 @@
|
||||
|
||||
%% Main entrypoint. Takes typed syntax produced by aeso_ast_infer_types:infer/1,2
|
||||
%% and produces Fate intermediate code.
|
||||
-spec ast_to_fcode(aeso_syntax:ast(), [option()]) -> fcode().
|
||||
-spec ast_to_fcode(aeso_syntax:ast(), [option()]) -> {env(), fcode()}.
|
||||
ast_to_fcode(Code, Options) ->
|
||||
init_fresh_names(),
|
||||
{Env1, FCode1} = to_fcode(init_env(Options), Code),
|
||||
@ -232,7 +233,8 @@ init_env(Options) ->
|
||||
["Chain", "GAAttachTx"] => #con_tag{ tag = 21, arities = ChainTxArities }
|
||||
},
|
||||
options => Options,
|
||||
functions => #{} }.
|
||||
functions => #{}
|
||||
}.
|
||||
|
||||
-spec builtins() -> builtins().
|
||||
builtins() ->
|
||||
@ -322,13 +324,13 @@ get_option(Opt, Env, Default) ->
|
||||
|
||||
%% -- Compilation ------------------------------------------------------------
|
||||
|
||||
-spec to_fcode(env(), aeso_syntax:ast()) -> fcode().
|
||||
-spec to_fcode(env(), aeso_syntax:ast()) -> {env(), fcode()}.
|
||||
to_fcode(Env, [{Contract, Attrs, Con = {con, _, Name}, Decls}|Rest])
|
||||
when ?IS_CONTRACT_HEAD(Contract) ->
|
||||
case Contract =:= contract_interface of
|
||||
false ->
|
||||
#{ builtins := Builtins } = Env,
|
||||
ConEnv = Env#{ context => {main_contract, Name},
|
||||
ConEnv = Env#{ context => {contract_def, Name},
|
||||
builtins => Builtins#{[Name, "state"] => {get_state, none},
|
||||
[Name, "put"] => {set_state, 1},
|
||||
[Name, "Chain", "event"] => {chain_event, 1}} },
|
||||
@ -357,8 +359,8 @@ to_fcode(Env, [{Contract, Attrs, Con = {con, _, Name}, Decls}|Rest])
|
||||
Env1 = decls_to_fcode(Env#{ context => {abstract_contract, Con} }, Decls),
|
||||
to_fcode(Env1, Rest)
|
||||
end;
|
||||
to_fcode(_Env, [NotMain = {NotMainHead, _ ,_ , _}]) when NotMainHead =/= main_contract ->
|
||||
fcode_error({last_declaration_must_be_main_contract, NotMain});
|
||||
to_fcode(_Env, [NotMain = {NotMainHead, _ ,_ , _}]) when NotMainHead =/= contract_def ->
|
||||
fcode_error({last_declaration_must_be_contract_def, NotMain});
|
||||
to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) ->
|
||||
Env1 = decls_to_fcode(Env#{ context => {namespace, Con} }, Decls),
|
||||
to_fcode(Env1, Code).
|
||||
@ -372,7 +374,7 @@ decls_to_fcode(Env, Decls) ->
|
||||
end, Env1, Decls).
|
||||
|
||||
-spec decl_to_fcode(env(), aeso_syntax:decl()) -> env().
|
||||
decl_to_fcode(Env = #{context := {main_contract, _}}, {fun_decl, _, Id, _}) ->
|
||||
decl_to_fcode(Env = #{context := {contract_def, _}}, {fun_decl, _, Id, _}) ->
|
||||
case is_no_code(Env) of
|
||||
false -> fcode_error({missing_definition, Id});
|
||||
true -> Env
|
||||
@ -435,7 +437,7 @@ typedef_to_fcode(Env, Id = {id, _, Name}, Xs, Def) ->
|
||||
Env3 = compute_state_layout(Env2, Name, FDef),
|
||||
bind_type(Env3, Q, FDef).
|
||||
|
||||
compute_state_layout(Env = #{ context := {main_contract, _} }, "state", Type) ->
|
||||
compute_state_layout(Env = #{ context := {contract_def, _} }, "state", Type) ->
|
||||
NoLayout = get_option(no_flatten_state, Env),
|
||||
Layout =
|
||||
case Type([]) of
|
||||
@ -461,7 +463,7 @@ compute_state_layout(R, [H | T]) ->
|
||||
compute_state_layout(R, _) ->
|
||||
{R + 1, {reg, R}}.
|
||||
|
||||
check_state_and_event_types(#{ context := {main_contract, _} }, Id, [_ | _]) ->
|
||||
check_state_and_event_types(#{ context := {contract_def, _} }, Id, [_ | _]) ->
|
||||
case Id of
|
||||
{id, _, "state"} -> fcode_error({parameterized_state, Id});
|
||||
{id, _, "event"} -> fcode_error({parameterized_event, Id});
|
||||
@ -1676,7 +1678,7 @@ add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
||||
make_fun_name(#{ context := Context }, Ann, Name) ->
|
||||
Entrypoint = proplists:get_value(entrypoint, Ann, false),
|
||||
case Context of
|
||||
{main_contract, Main} ->
|
||||
{contract_def, Main} ->
|
||||
if Entrypoint -> {entrypoint, list_to_binary(Name)};
|
||||
true -> {local_fun, [Main, Name]}
|
||||
end;
|
||||
@ -1688,7 +1690,7 @@ make_fun_name(#{ context := Context }, Ann, Name) ->
|
||||
current_namespace(#{ context := Cxt }) ->
|
||||
case Cxt of
|
||||
{abstract_contract, Con} -> Con;
|
||||
{main_contract, Con} -> Con;
|
||||
{contract_def, Con} -> Con;
|
||||
{namespace, NS} -> NS
|
||||
end.
|
||||
|
||||
@ -2035,8 +2037,11 @@ internal_error(Error) ->
|
||||
%% -- Pretty printing --------------------------------------------------------
|
||||
|
||||
format_fcode(#{ functions := Funs }) ->
|
||||
prettypr:format(pp_above(
|
||||
[ pp_fun(Name, Def) || {Name, Def} <- maps:to_list(Funs) ])).
|
||||
prettypr:format(format_funs(Funs)).
|
||||
|
||||
format_funs(Funs) ->
|
||||
pp_above(
|
||||
[ pp_fun(Name, Def) || {Name, Def} <- maps:to_list(Funs) ]).
|
||||
|
||||
format_fexpr(E) ->
|
||||
prettypr:format(pp_fexpr(E)).
|
||||
@ -2153,7 +2158,9 @@ pp_fexpr({set_state, R, A}) ->
|
||||
pp_call(pp_text("set_state"), [{lit, {int, R}}, A]);
|
||||
pp_fexpr({get_state, R}) ->
|
||||
pp_call(pp_text("get_state"), [{lit, {int, R}}]);
|
||||
pp_fexpr({switch, Split}) -> pp_split(Split).
|
||||
pp_fexpr({switch, Split}) -> pp_split(Split);
|
||||
pp_fexpr({contract_code, Contract}) ->
|
||||
pp_beside(pp_text("contract "), pp_text(Contract)).
|
||||
|
||||
pp_call(Fun, Args) ->
|
||||
pp_beside(Fun, pp_fexpr({tuple, Args})).
|
||||
|
@ -11,7 +11,7 @@
|
||||
-export([format/1, pos/1]).
|
||||
|
||||
format({last_declaration_must_be_contract, Decl = {Kind, _, {con, _, C}, _}}) ->
|
||||
Msg = io_lib:format("Expected a contract as the last declaration instead of the ~p '~s'\n",
|
||||
Msg = io_lib:format("Expected a main contract as the last declaration instead of the ~p '~s'\n",
|
||||
[Kind, C]),
|
||||
mk_err(pos(Decl), Msg);
|
||||
format({missing_init_function, Con}) ->
|
||||
|
@ -180,7 +180,7 @@ string_to_code(ContractString, Options) ->
|
||||
, type_env => TypeEnv
|
||||
, ast => Ast };
|
||||
fate ->
|
||||
{Env, Fcode} = aeso_ast_to_fcode:ast_to_fcode(UnfoldedTypedAst, Options),
|
||||
{Env, Fcode} = aeso_ast_to_fcode:ast_to_fcode(UnfoldedTypedAst, [{original_src, ContractString}|Options]),
|
||||
#{ fcode => Fcode
|
||||
, fcode_env => Env
|
||||
, unfolded_typed_ast => UnfoldedTypedAst
|
||||
|
@ -184,15 +184,16 @@ lit_to_fate(Env, L) ->
|
||||
{oracle_pubkey, K} -> aeb_fate_data:make_oracle(K);
|
||||
{oracle_query_id, H} -> aeb_fate_data:make_oracle_query(H);
|
||||
{contract_code, C} ->
|
||||
Options = Env#env.options,
|
||||
FCode = maps:get(C, Env#env.child_contracts),
|
||||
SCode = compile(Env#env.child_contracts, FCode, Env#env.options),
|
||||
ByteCode = aeb_fate_code:serialize(SCode, []),
|
||||
FateCode = compile(Env#env.child_contracts, FCode, Options),
|
||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
||||
{ok, Version} = aeso_compiler:version(),
|
||||
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
||||
Code = #{byte_code => ByteCode,
|
||||
compiler_version => Version,
|
||||
contract_source => "child_contract_src_placeholder",
|
||||
source_hash => crypto:hash(sha256, OriginalSourceCode ++ [0] ++ C),
|
||||
type_info => [],
|
||||
fate_code => SCode,
|
||||
abi_version => aeb_fate_abi:abi_version(),
|
||||
payable => maps:get(payable, FCode)
|
||||
},
|
||||
@ -586,7 +587,6 @@ builtin_to_scode(Env, chain_clone,
|
||||
[Contract, TypeRep, Value, Prot | InitArgs]
|
||||
);
|
||||
_ ->
|
||||
io:format("\n\n************* GAS CAP: ~p\n\n", [GasCap]),
|
||||
call_to_scode(Env, aeb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a),
|
||||
[Contract, TypeRep, Value, GasCap, Prot | InitArgs]
|
||||
)
|
||||
@ -985,7 +985,7 @@ attributes(I) ->
|
||||
{'CREATE', A, B, C} -> Impure(?a, [A, B, C]);
|
||||
{'CLONE', A, B, C, D} -> Impure(?a, [A, B, C, D]);
|
||||
{'CLONE_G', A, B, C, D, E} -> Impure(?a, [A, B, C, D, E]);
|
||||
{'BYTECODE_HASH', A, B} -> Pure(A, [B]);
|
||||
{'BYTECODE_HASH', A, B} -> Impure(A, [B]);
|
||||
{'ABORT', A} -> Impure(pc, A);
|
||||
{'EXIT', A} -> Impure(pc, A);
|
||||
'NOP' -> Pure(none, [])
|
||||
|
@ -26,7 +26,7 @@
|
||||
-type ann_format() :: '?:' | hex | infix | prefix | elif.
|
||||
|
||||
-type ann() :: [ {line, ann_line()} | {col, ann_col()} | {format, ann_format()} | {origin, ann_origin()}
|
||||
| stateful | private] | payable | main | interface.
|
||||
| stateful | private | payable | main | interface].
|
||||
|
||||
-type name() :: string().
|
||||
-type id() :: {id, ann(), name()}.
|
||||
|
@ -103,17 +103,24 @@ aci_test_contract(Name) ->
|
||||
true -> [debug_mode];
|
||||
false -> []
|
||||
end ++ [{include, {file_system, [aeso_test_utils:contract_path()]}}],
|
||||
{ok, JSON} = aeso_aci:contract_interface(json, String, Opts),
|
||||
{ok, #{aci := JSON1}} = aeso_compiler:from_string(String, [{aci, json}, {backend, fate} | Opts]),
|
||||
JSON = case aeso_aci:contract_interface(json, String, Opts) of
|
||||
{ok, J} -> J;
|
||||
{error, ErrorStringJ} when is_binary(ErrorStringJ) -> error(ErrorStringJ);
|
||||
{error, ErrorJ} -> aeso_compiler_tests:print_and_throw(ErrorJ)
|
||||
end,
|
||||
case aeso_compiler:from_string(String, [{aci, json}, {backend, fate} | Opts]) of
|
||||
{ok, #{aci := JSON1}} ->
|
||||
?assertEqual(JSON, JSON1),
|
||||
|
||||
io:format("JSON:\n~p\n", [JSON]),
|
||||
{ok, ContractStub} = aeso_aci:render_aci_json(JSON),
|
||||
|
||||
io:format("STUB:\n~s\n", [ContractStub]),
|
||||
check_stub(ContractStub, [{src_file, Name}]),
|
||||
|
||||
ok.
|
||||
ok;
|
||||
{error, ErrorString} when is_binary(ErrorString) -> error(ErrorString);
|
||||
{error, Error} -> aeso_compiler_tests:print_and_throw(Error)
|
||||
end.
|
||||
|
||||
check_stub(Stub, Options) ->
|
||||
try aeso_parser:string(binary_to_list(Stub), Options) of
|
||||
|
@ -34,9 +34,7 @@ simple_compile_test_() ->
|
||||
#{fate_code := Code} when Backend == fate ->
|
||||
Code1 = aeb_fate_code:deserialize(aeb_fate_code:serialize(Code)),
|
||||
?assertMatch({X, X}, {Code1, Code});
|
||||
ErrBin ->
|
||||
io:format("\n~s", [ErrBin]),
|
||||
error(ErrBin)
|
||||
Error -> print_and_throw(Error)
|
||||
end
|
||||
end} || ContractName <- compilable_contracts(), Backend <- [aevm, fate],
|
||||
not lists:member(ContractName, not_compilable_on(Backend))] ++
|
||||
@ -878,7 +876,8 @@ validation_fails() ->
|
||||
"Byte code contract is not payable, but source code contract is.">>]}].
|
||||
|
||||
validate(Contract1, Contract2) ->
|
||||
ByteCode = #{ fate_code := FCode } = compile(fate, Contract1),
|
||||
case compile(fate, Contract1) of
|
||||
ByteCode = #{ fate_code := FCode } ->
|
||||
FCode1 = aeb_fate_code:serialize(aeb_fate_code:strip_init_function(FCode)),
|
||||
Source = aeso_test_utils:read_contract(Contract2),
|
||||
aeso_compiler:validate_byte_code(
|
||||
@ -887,5 +886,16 @@ validate(Contract1, Contract2) ->
|
||||
true -> [debug_mode];
|
||||
false -> []
|
||||
end ++
|
||||
[{backend, fate}, {include, {file_system, [aeso_test_utils:contract_path()]}}]).
|
||||
[{backend, fate}, {include, {file_system, [aeso_test_utils:contract_path()]}}]);
|
||||
Error -> print_and_throw(Error)
|
||||
end.
|
||||
|
||||
print_and_throw(Err) ->
|
||||
case Err of
|
||||
ErrBin when is_binary(ErrBin) ->
|
||||
io:format("\n~s", [ErrBin]),
|
||||
error(ErrBin);
|
||||
Errors ->
|
||||
io:format("Compilation error:\n~s", [string:join([aeso_errors:pp(E) || E <- Errors], "\n\n")]),
|
||||
error(compilation_error)
|
||||
end.
|
||||
|
@ -14,7 +14,7 @@ main contract C =
|
||||
let s1 = Chain.clone(ref=s)
|
||||
let Some(s2) = Chain.clone(ref=s, protected=true)
|
||||
let None = Chain.clone(ref=s, protected=true, gas=1)
|
||||
let None = Chain.clone(ref=l, protected=true, 123)
|
||||
let None = Chain.clone(ref=l, protected=true, 123) // since it should be HigherOrderState underneath
|
||||
let s3 = Chain.clone(ref=s1)
|
||||
require(s1.apply(2137) == 2137, "APPLY_S1_0")
|
||||
require(s2.apply(2137) == 2137, "APPLY_S2_0")
|
||||
|
@ -1,3 +1,6 @@
|
||||
// This is a custom test file if you need to run a compiler without
|
||||
// changing aeso_compiler_tests.erl
|
||||
|
||||
include "List.aes"
|
||||
|
||||
contract IntegerHolder =
|
||||
@ -5,10 +8,5 @@ contract IntegerHolder =
|
||||
entrypoint init(x) = x
|
||||
entrypoint get() = state
|
||||
|
||||
main contract IntegerCollection =
|
||||
record state = {template: IntegerHolder, payload: list(IntegerHolder)}
|
||||
stateful entrypoint init() = {template = Chain.create(0), payload = []}
|
||||
stateful entrypoint add(x) =
|
||||
put(state{payload @ p = Chain.clone(ref=state.template, x) :: p})
|
||||
x
|
||||
entrypoint sum() = List.sum(List.map((h) => h.get(), state.payload))
|
||||
main contract Test =
|
||||
stateful entrypoint f(c) = Chain.clone(ref=c, 123)
|
Loading…
x
Reference in New Issue
Block a user