Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 451b3636ac | |||
| 514d80259e | |||
| df12f6af91 | |||
| 6aed5dfacb | |||
| cecc977898 | |||
| 74933b0616 | |||
| 6a27c4a68b | |||
| d526e55c26 | |||
| 6f7f5fa13c | |||
| 2d6381dc6f | |||
| 3663b4e5d0 | |||
| 4478fee6e6 | |||
| 79ae92a068 | |||
| eb968d3cb9 | |||
| 054a5a4867 | |||
| e198dd8311 | |||
| 46a996ead8 | |||
| 2bf6ab7655 | |||
| 5ff7aa5821 | |||
| 045df292be | |||
| c97eb99921 | |||
| 4c78ab3aee | |||
| 5ff983b0b3 | |||
| 4bf382a997 | |||
| 4c72045a86 | |||
| 7daf218b2a | |||
| 973850e6a6 | |||
| 19948c6aad | |||
| c4660fe0cf | |||
| e326908623 | |||
| 9be528a579 | |||
| f67d7354a2 | |||
| 6f873e45b8 |
@@ -19,3 +19,5 @@ rebar3.crashdump
|
|||||||
*.erl~
|
*.erl~
|
||||||
*.aes~
|
*.aes~
|
||||||
aesophia
|
aesophia
|
||||||
|
.qcci
|
||||||
|
current_counterexample.eqc
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{erl_opts, [debug_info]}.
|
{erl_opts, [debug_info]}.
|
||||||
|
|
||||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"c63ac88"}}}
|
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"adf3664"}}}
|
||||||
, {getopt, "1.0.1"}
|
, {getopt, "1.0.1"}
|
||||||
, {eblake2, "1.0.0"}
|
, {eblake2, "1.0.0"}
|
||||||
, {jsx, {git, "https://github.com/talentdeficit/jsx.git",
|
, {jsx, {git, "https://github.com/talentdeficit/jsx.git",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{"1.1.0",
|
{"1.1.0",
|
||||||
[{<<"aebytecode">>,
|
[{<<"aebytecode">>,
|
||||||
{git,"https://github.com/aeternity/aebytecode.git",
|
{git,"https://github.com/aeternity/aebytecode.git",
|
||||||
{ref,"c63ac888dd71c305cbc6d4f70953a176bf1f78f7"}},
|
{ref,"adf3664dd03626c115756f79fa0e602fda24318d"}},
|
||||||
0},
|
0},
|
||||||
{<<"aeserialization">>,
|
{<<"aeserialization">>,
|
||||||
{git,"https://github.com/aeternity/aeserialization.git",
|
{git,"https://github.com/aeternity/aeserialization.git",
|
||||||
|
|||||||
+4
-1
@@ -264,7 +264,10 @@ decode_types(Ets) ->
|
|||||||
|
|
||||||
decode_type(#{tuple := Ets}) ->
|
decode_type(#{tuple := Ets}) ->
|
||||||
Ts = decode_types(Ets),
|
Ts = decode_types(Ets),
|
||||||
[$(,lists:join(",", Ts),$)];
|
case Ts of
|
||||||
|
[] -> ["unit"];
|
||||||
|
_ -> [$(,lists:join(" * ", Ts),$)]
|
||||||
|
end;
|
||||||
decode_type(#{record := Efs}) ->
|
decode_type(#{record := Efs}) ->
|
||||||
Fs = decode_fields(Efs),
|
Fs = decode_fields(Efs),
|
||||||
[${,lists:join(",", Fs),$}];
|
[${,lists:join(",", Fs),$}];
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ bind_tvars(Xs, Env) ->
|
|||||||
check_tvar(#env{ typevars = TVars}, T = {tvar, _, X}) ->
|
check_tvar(#env{ typevars = TVars}, T = {tvar, _, X}) ->
|
||||||
case TVars == unrestricted orelse lists:member(X, TVars) of
|
case TVars == unrestricted orelse lists:member(X, TVars) of
|
||||||
true -> ok;
|
true -> ok;
|
||||||
false -> type_error({unbound_type_variable, T})
|
false -> type_error({unbound_type, T})
|
||||||
end,
|
end,
|
||||||
T.
|
T.
|
||||||
|
|
||||||
@@ -385,9 +385,10 @@ global_env() ->
|
|||||||
{"FixedTTL", Fun1(Int, TTL)},
|
{"FixedTTL", Fun1(Int, TTL)},
|
||||||
%% Abort
|
%% Abort
|
||||||
{"abort", Fun1(String, A)},
|
{"abort", Fun1(String, A)},
|
||||||
{"require", Fun([Bool, String], A)}])
|
{"require", Fun([Bool, String], Unit)}])
|
||||||
, types = MkDefs(
|
, types = MkDefs(
|
||||||
[{"int", 0}, {"bool", 0}, {"char", 0}, {"string", 0}, {"address", 0},
|
[{"int", 0}, {"bool", 0}, {"char", 0}, {"string", 0}, {"address", 0},
|
||||||
|
{"unit", {[], {alias_t, Unit}}},
|
||||||
{"hash", {[], {alias_t, Bytes(32)}}},
|
{"hash", {[], {alias_t, Bytes(32)}}},
|
||||||
{"signature", {[], {alias_t, Bytes(64)}}},
|
{"signature", {[], {alias_t, Bytes(64)}}},
|
||||||
{"bits", 0},
|
{"bits", 0},
|
||||||
@@ -440,9 +441,9 @@ global_env() ->
|
|||||||
{ funs = MkDefs(
|
{ funs = MkDefs(
|
||||||
[{"resolve", Fun([String, String], option_t(Ann, A))},
|
[{"resolve", Fun([String, String], option_t(Ann, A))},
|
||||||
{"preclaim", SignFun([Address, Hash], Unit)},
|
{"preclaim", SignFun([Address, Hash], Unit)},
|
||||||
{"claim", SignFun([Address, String, Int], Unit)},
|
{"claim", SignFun([Address, String, Int, Int], Unit)},
|
||||||
{"transfer", SignFun([Address, Address, Hash], Unit)},
|
{"transfer", SignFun([Address, Address, String], Unit)},
|
||||||
{"revoke", SignFun([Address, Hash], Unit)}]) },
|
{"revoke", SignFun([Address, String], Unit)}]) },
|
||||||
|
|
||||||
MapScope = #scope
|
MapScope = #scope
|
||||||
{ funs = MkDefs(
|
{ funs = MkDefs(
|
||||||
@@ -2159,6 +2160,8 @@ pp_error({contract_has_no_entrypoints, Con}) ->
|
|||||||
io_lib:format("The contract ~s (at ~s) has no entrypoints. Since Sophia version 3.2, public\n"
|
io_lib:format("The contract ~s (at ~s) has no entrypoints. Since Sophia version 3.2, public\n"
|
||||||
"contract functions must be declared with the 'entrypoint' keyword instead of\n"
|
"contract functions must be declared with the 'entrypoint' keyword instead of\n"
|
||||||
"'function'.\n", [pp_expr("", Con), pp_loc(Con)]);
|
"'function'.\n", [pp_expr("", Con), pp_loc(Con)]);
|
||||||
|
pp_error({unbound_type, Type}) ->
|
||||||
|
io_lib:format("Unbound type ~s (at ~s).\n", [pp_type("", Type), pp_loc(Type)]);
|
||||||
pp_error(Err) ->
|
pp_error(Err) ->
|
||||||
io_lib:format("Unknown error: ~p\n", [Err]).
|
io_lib:format("Unknown error: ~p\n", [Err]).
|
||||||
|
|
||||||
@@ -2320,8 +2323,10 @@ pp({uvar, _, Ref}) ->
|
|||||||
["?u" | integer_to_list(erlang:phash2(Ref, 16384)) ];
|
["?u" | integer_to_list(erlang:phash2(Ref, 16384)) ];
|
||||||
pp({tvar, _, Name}) ->
|
pp({tvar, _, Name}) ->
|
||||||
Name;
|
Name;
|
||||||
|
pp({tuple_t, _, []}) ->
|
||||||
|
"unit";
|
||||||
pp({tuple_t, _, Cpts}) ->
|
pp({tuple_t, _, Cpts}) ->
|
||||||
["(", pp(Cpts), ")"];
|
["(", string:join(lists:map(fun pp/1, Cpts), " * "), ")"];
|
||||||
pp({bytes_t, _, any}) -> "bytes(_)";
|
pp({bytes_t, _, any}) -> "bytes(_)";
|
||||||
pp({bytes_t, _, Len}) ->
|
pp({bytes_t, _, Len}) ->
|
||||||
["bytes(", integer_to_list(Len), ")"];
|
["bytes(", integer_to_list(Len), ")"];
|
||||||
|
|||||||
+45
-13
@@ -183,7 +183,7 @@ builtins() ->
|
|||||||
{["Oracle"], [{"register", 4}, {"query_fee", 1}, {"query", 5}, {"get_question", 2},
|
{["Oracle"], [{"register", 4}, {"query_fee", 1}, {"query", 5}, {"get_question", 2},
|
||||||
{"respond", 4}, {"extend", 3}, {"get_answer", 2},
|
{"respond", 4}, {"extend", 3}, {"get_answer", 2},
|
||||||
{"check", 1}, {"check_query", 2}]},
|
{"check", 1}, {"check_query", 2}]},
|
||||||
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 4}, {"transfer", 4},
|
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 5}, {"transfer", 4},
|
||||||
{"revoke", 3}]},
|
{"revoke", 3}]},
|
||||||
{["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2},
|
{["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2},
|
||||||
{"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]},
|
{"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]},
|
||||||
@@ -239,7 +239,8 @@ to_fcode(Env, [{contract, _, {con, _, Main}, Decls}]) ->
|
|||||||
#{ contract_name => Main,
|
#{ contract_name => Main,
|
||||||
state_type => StateType,
|
state_type => StateType,
|
||||||
event_type => EventType,
|
event_type => EventType,
|
||||||
functions => add_event_function(Env1, EventType, Funs) };
|
functions => add_init_function(Env1,
|
||||||
|
add_event_function(Env1, EventType, Funs)) };
|
||||||
to_fcode(Env, [{contract, _, {con, _, Con}, Decls} | Code]) ->
|
to_fcode(Env, [{contract, _, {con, _, Con}, Decls} | Code]) ->
|
||||||
Env1 = decls_to_fcode(Env#{ context => {abstract_contract, Con} }, Decls),
|
Env1 = decls_to_fcode(Env#{ context => {abstract_contract, Con} }, Decls),
|
||||||
to_fcode(Env1, Code);
|
to_fcode(Env1, Code);
|
||||||
@@ -261,6 +262,11 @@ decls_to_fcode(Env, Decls) ->
|
|||||||
|
|
||||||
-spec decl_to_fcode(env(), aeso_syntax:decl()) -> env().
|
-spec decl_to_fcode(env(), aeso_syntax:decl()) -> env().
|
||||||
decl_to_fcode(Env, {type_decl, _, _, _}) -> Env;
|
decl_to_fcode(Env, {type_decl, _, _, _}) -> Env;
|
||||||
|
decl_to_fcode(Env = #{context := {main_contract, _}}, {fun_decl, Ann, {id, _, Name}, _}) ->
|
||||||
|
case proplists:get_value(no_code, maps:get(options, Env, []), false) of
|
||||||
|
false -> fcode_error({missing_definition, Name, lists:keydelete(entrypoint, 1, Ann)});
|
||||||
|
true -> Env
|
||||||
|
end;
|
||||||
decl_to_fcode(Env, {fun_decl, _, _, _}) -> Env;
|
decl_to_fcode(Env, {fun_decl, _, _, _}) -> Env;
|
||||||
decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) ->
|
decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) ->
|
||||||
typedef_to_fcode(Env, Name, Args, Def);
|
typedef_to_fcode(Env, Name, Args, Def);
|
||||||
@@ -819,6 +825,19 @@ builtin_to_fcode(Builtin, Args) ->
|
|||||||
false -> {builtin, Builtin, Args}
|
false -> {builtin, Builtin, Args}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% -- Init function --
|
||||||
|
|
||||||
|
add_init_function(_Env, Funs) ->
|
||||||
|
InitName = {entrypoint, <<"init">>},
|
||||||
|
InitFun = #{ args := InitArgs } =
|
||||||
|
case maps:get(InitName, Funs, none) of
|
||||||
|
none -> #{ attrs => [], args => [], return => {tuple, []}, body => {tuple, []} };
|
||||||
|
Info -> Info
|
||||||
|
end,
|
||||||
|
Vars = [ {var, X} || {X, _} <- InitArgs ],
|
||||||
|
Funs#{ init => InitFun#{ return => {tuple, []},
|
||||||
|
body => {builtin, set_state, [{def, InitName, Vars}]} } }.
|
||||||
|
|
||||||
%% -- Event function --
|
%% -- Event function --
|
||||||
|
|
||||||
add_event_function(_Env, none, Funs) -> Funs;
|
add_event_function(_Env, none, Funs) -> Funs;
|
||||||
@@ -1001,6 +1020,8 @@ add_fun_env(Env = #{ context := {abstract_contract, _} }, _) -> Env; %% no func
|
|||||||
add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
add_fun_env(Env = #{ fun_env := FunEnv }, Decls) ->
|
||||||
Entry = fun({letfun, Ann, {id, _, Name}, Args, _, _}) ->
|
Entry = fun({letfun, Ann, {id, _, Name}, Args, _, _}) ->
|
||||||
[{qname(Env, Name), {make_fun_name(Env, Ann, Name), length(Args)}}];
|
[{qname(Env, Name), {make_fun_name(Env, Ann, Name), length(Args)}}];
|
||||||
|
({fun_decl, Ann, {id, _, Name}, {fun_t, _, _, ArgTypes, _}}) ->
|
||||||
|
[{qname(Env, Name), {make_fun_name(Env, Ann, Name), length(ArgTypes)}}];
|
||||||
(_) -> [] end,
|
(_) -> [] end,
|
||||||
FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)),
|
FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)),
|
||||||
Env#{ fun_env := maps:merge(FunEnv, FunEnv1) }.
|
Env#{ fun_env := maps:merge(FunEnv, FunEnv1) }.
|
||||||
@@ -1009,8 +1030,7 @@ make_fun_name(#{ context := Context }, Ann, Name) ->
|
|||||||
Entrypoint = proplists:get_value(entrypoint, Ann, false),
|
Entrypoint = proplists:get_value(entrypoint, Ann, false),
|
||||||
case Context of
|
case Context of
|
||||||
{main_contract, Main} ->
|
{main_contract, Main} ->
|
||||||
if Name == "init" -> init;
|
if Entrypoint -> {entrypoint, list_to_binary(Name)};
|
||||||
Entrypoint -> {entrypoint, list_to_binary(Name)};
|
|
||||||
true -> {local_fun, [Main, Name]}
|
true -> {local_fun, [Main, Name]}
|
||||||
end;
|
end;
|
||||||
{namespace, Lib} ->
|
{namespace, Lib} ->
|
||||||
@@ -1094,6 +1114,16 @@ pat_vars({tuple, Ps}) -> pat_vars(Ps);
|
|||||||
pat_vars({con, _, _, Ps}) -> pat_vars(Ps);
|
pat_vars({con, _, _, Ps}) -> pat_vars(Ps);
|
||||||
pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)].
|
pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)].
|
||||||
|
|
||||||
|
-spec fsplit_pat_vars(fsplit_pat()) -> [var_name()].
|
||||||
|
fsplit_pat_vars({var, X}) -> [X || X /= "_"];
|
||||||
|
fsplit_pat_vars({bool, _}) -> [];
|
||||||
|
fsplit_pat_vars({int, _}) -> [];
|
||||||
|
fsplit_pat_vars({string, _}) -> [];
|
||||||
|
fsplit_pat_vars(nil) -> [];
|
||||||
|
fsplit_pat_vars({'::', P, Q}) -> [P, Q];
|
||||||
|
fsplit_pat_vars({tuple, Ps}) -> Ps;
|
||||||
|
fsplit_pat_vars({con, _, _, Ps}) -> Ps.
|
||||||
|
|
||||||
free_vars(Xs) when is_list(Xs) ->
|
free_vars(Xs) when is_list(Xs) ->
|
||||||
lists:umerge([ free_vars(X) || X <- Xs ]);
|
lists:umerge([ free_vars(X) || X <- Xs ]);
|
||||||
free_vars(Expr) ->
|
free_vars(Expr) ->
|
||||||
@@ -1119,7 +1149,7 @@ free_vars(Expr) ->
|
|||||||
{switch, A} -> free_vars(A);
|
{switch, A} -> free_vars(A);
|
||||||
{split, _, X, As} -> free_vars([{var, X} | As]);
|
{split, _, X, As} -> free_vars([{var, X} | As]);
|
||||||
{nosplit, A} -> free_vars(A);
|
{nosplit, A} -> free_vars(A);
|
||||||
{'case', P, A} -> free_vars(A) -- lists:sort(pat_vars(P))
|
{'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_named_args(NamedArgsT, Args) ->
|
get_named_args(NamedArgsT, Args) ->
|
||||||
@@ -1278,14 +1308,17 @@ pp_fun(Name, #{ args := Args, return := Return, body := Body }) ->
|
|||||||
pp_text(" : "), pp_ftype(Return), pp_text(" =")]),
|
pp_text(" : "), pp_ftype(Return), pp_text(" =")]),
|
||||||
prettypr:nest(2, pp_fexpr(Body))).
|
prettypr:nest(2, pp_fexpr(Body))).
|
||||||
|
|
||||||
pp_fun_name(init) -> pp_text(init);
|
pp_fun_name(init) -> pp_text('INIT');
|
||||||
pp_fun_name(event) -> pp_text(event);
|
pp_fun_name(event) -> pp_text(event);
|
||||||
pp_fun_name({entrypoint, E}) -> pp_text(binary_to_list(E));
|
pp_fun_name({entrypoint, E}) -> pp_text(binary_to_list(E));
|
||||||
pp_fun_name({local_fun, Q}) -> pp_text(string:join(Q, ".")).
|
pp_fun_name({local_fun, Q}) -> pp_text(string:join(Q, ".")).
|
||||||
|
|
||||||
pp_text(<<>>) -> prettypr:text("\"\"");
|
pp_text(<<>>) -> prettypr:text("\"\"");
|
||||||
pp_text(Bin) when is_binary(Bin) -> prettypr:text(lists:flatten(io_lib:format("~p", [binary_to_list(Bin)])));
|
pp_text(Bin) when is_binary(Bin) -> prettypr:text(lists:flatten(io_lib:format("~p", [binary_to_list(Bin)])));
|
||||||
pp_text(S) -> prettypr:text(lists:concat([S])).
|
pp_text(S) when is_list(S) -> prettypr:text(lists:concat([S]));
|
||||||
|
pp_text(A) when is_atom(A) -> prettypr:text(atom_to_list(A)).
|
||||||
|
|
||||||
|
pp_int(I) -> prettypr:text(integer_to_list(I)).
|
||||||
|
|
||||||
pp_beside([]) -> prettypr:empty();
|
pp_beside([]) -> prettypr:empty();
|
||||||
pp_beside([X]) -> X;
|
pp_beside([X]) -> X;
|
||||||
@@ -1317,18 +1350,18 @@ pp_fexpr(nil) ->
|
|||||||
pp_fexpr({var, X}) -> pp_text(X);
|
pp_fexpr({var, X}) -> pp_text(X);
|
||||||
pp_fexpr({def, Fun}) -> pp_fun_name(Fun);
|
pp_fexpr({def, Fun}) -> pp_fun_name(Fun);
|
||||||
pp_fexpr({def_u, Fun, Ar}) ->
|
pp_fexpr({def_u, Fun, Ar}) ->
|
||||||
pp_beside([pp_fun_name(Fun), pp_text("/"), pp_text(Ar)]);
|
pp_beside([pp_fun_name(Fun), pp_text("/"), pp_int(Ar)]);
|
||||||
pp_fexpr({def, Fun, Args}) ->
|
pp_fexpr({def, Fun, Args}) ->
|
||||||
pp_call(pp_fun_name(Fun), Args);
|
pp_call(pp_fun_name(Fun), Args);
|
||||||
pp_fexpr({con, _, I, []}) ->
|
pp_fexpr({con, _, I, []}) ->
|
||||||
pp_beside(pp_text("C"), pp_text(I));
|
pp_beside(pp_text("C"), pp_int(I));
|
||||||
pp_fexpr({con, _, I, Es}) ->
|
pp_fexpr({con, _, I, Es}) ->
|
||||||
pp_beside(pp_fexpr({con, [], I, []}),
|
pp_beside(pp_fexpr({con, [], I, []}),
|
||||||
pp_fexpr({tuple, Es}));
|
pp_fexpr({tuple, Es}));
|
||||||
pp_fexpr({tuple, Es}) ->
|
pp_fexpr({tuple, Es}) ->
|
||||||
pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es])));
|
pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es])));
|
||||||
pp_fexpr({proj, E, I}) ->
|
pp_fexpr({proj, E, I}) ->
|
||||||
pp_beside([pp_fexpr(E), pp_text("."), pp_text(I)]);
|
pp_beside([pp_fexpr(E), pp_text("."), pp_int(I)]);
|
||||||
pp_fexpr({lam, Xs, A}) ->
|
pp_fexpr({lam, Xs, A}) ->
|
||||||
pp_par([pp_fexpr({tuple, [{var, X} || X <- Xs]}), pp_text("=>"),
|
pp_par([pp_fexpr({tuple, [{var, X} || X <- Xs]}), pp_text("=>"),
|
||||||
prettypr:nest(2, pp_fexpr(A))]);
|
prettypr:nest(2, pp_fexpr(A))]);
|
||||||
@@ -1339,7 +1372,7 @@ pp_fexpr({closure, Fun, ClEnv}) ->
|
|||||||
end,
|
end,
|
||||||
pp_call(pp_text("__CLOSURE__"), [{def, Fun} | FVs]);
|
pp_call(pp_text("__CLOSURE__"), [{def, Fun} | FVs]);
|
||||||
pp_fexpr({set_proj, E, I, A}) ->
|
pp_fexpr({set_proj, E, I, A}) ->
|
||||||
pp_beside(pp_fexpr(E), pp_braces(pp_beside([pp_text(I), pp_text(" = "), pp_fexpr(A)])));
|
pp_beside(pp_fexpr(E), pp_braces(pp_beside([pp_int(I), pp_text(" = "), pp_fexpr(A)])));
|
||||||
pp_fexpr({op, Op, [A, B] = Args}) ->
|
pp_fexpr({op, Op, [A, B] = Args}) ->
|
||||||
case is_infix(Op) of
|
case is_infix(Op) of
|
||||||
false -> pp_call(pp_text(Op), Args);
|
false -> pp_call(pp_text(Op), Args);
|
||||||
@@ -1360,7 +1393,7 @@ pp_fexpr({builtin_u, B, N}) ->
|
|||||||
pp_fexpr({builtin, B, As}) ->
|
pp_fexpr({builtin, B, As}) ->
|
||||||
pp_call(pp_text(B), As);
|
pp_call(pp_text(B), As);
|
||||||
pp_fexpr({remote_u, Ct, Fun, Ar}) ->
|
pp_fexpr({remote_u, Ct, Fun, Ar}) ->
|
||||||
pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text("/"), pp_text(Ar)]);
|
pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text("/"), pp_int(Ar)]);
|
||||||
pp_fexpr({remote, Ct, Fun, As}) ->
|
pp_fexpr({remote, Ct, Fun, As}) ->
|
||||||
pp_call(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun)]), As);
|
pp_call(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun)]), As);
|
||||||
pp_fexpr({funcall, Fun, As}) ->
|
pp_fexpr({funcall, Fun, As}) ->
|
||||||
@@ -1415,4 +1448,3 @@ pp_pat(Pat) -> pp_fexpr(Pat).
|
|||||||
is_infix(Op) ->
|
is_infix(Op) ->
|
||||||
C = hd(atom_to_list(Op)),
|
C = hd(atom_to_list(Op)),
|
||||||
C < $a orelse C > $z.
|
C < $a orelse C > $z.
|
||||||
|
|
||||||
|
|||||||
+19
-16
@@ -21,18 +21,19 @@ convert_typed(TypedTree, Options) ->
|
|||||||
{contract, _, {con, _, Con}, _} -> Con;
|
{contract, _, {con, _, Con}, _} -> Con;
|
||||||
_ -> gen_error(last_declaration_must_be_contract)
|
_ -> gen_error(last_declaration_must_be_contract)
|
||||||
end,
|
end,
|
||||||
Icode = code(TypedTree, aeso_icode:set_name(Name, aeso_icode:new(Options))),
|
NewIcode = aeso_icode:set_name(Name, aeso_icode:new(Options)),
|
||||||
|
Icode = code(TypedTree, NewIcode, Options),
|
||||||
deadcode_elimination(Icode).
|
deadcode_elimination(Icode).
|
||||||
|
|
||||||
code([{contract, _Attribs, Con, Code}|Rest], Icode) ->
|
code([{contract, _Attribs, Con, Code}|Rest], Icode, Options) ->
|
||||||
NewIcode = contract_to_icode(Code, aeso_icode:set_namespace(Con, Icode)),
|
NewIcode = contract_to_icode(Code, aeso_icode:set_namespace(Con, Icode)),
|
||||||
code(Rest, NewIcode);
|
code(Rest, NewIcode, Options);
|
||||||
code([{namespace, _Ann, Name, Code}|Rest], Icode) ->
|
code([{namespace, _Ann, Name, Code}|Rest], Icode, Options) ->
|
||||||
%% TODO: nested namespaces
|
%% TODO: nested namespaces
|
||||||
NewIcode = contract_to_icode(Code, aeso_icode:set_namespace(Name, Icode)),
|
NewIcode = contract_to_icode(Code, aeso_icode:set_namespace(Name, Icode)),
|
||||||
code(Rest, NewIcode);
|
code(Rest, NewIcode, Options);
|
||||||
code([], Icode) ->
|
code([], Icode, Options) ->
|
||||||
add_default_init_function(add_builtins(Icode)).
|
add_default_init_function(add_builtins(Icode), Options).
|
||||||
|
|
||||||
%% Generate error on correct format.
|
%% Generate error on correct format.
|
||||||
|
|
||||||
@@ -40,10 +41,12 @@ gen_error(Error) ->
|
|||||||
error({code_errors, [Error]}).
|
error({code_errors, [Error]}).
|
||||||
|
|
||||||
%% Create default init function (only if state is unit).
|
%% Create default init function (only if state is unit).
|
||||||
add_default_init_function(Icode = #{functions := Funs, state_type := State}) ->
|
add_default_init_function(Icode = #{functions := Funs, state_type := State}, Options) ->
|
||||||
|
NoCode = proplists:get_value(no_code, Options, false),
|
||||||
{_, _, QInit} = aeso_icode:qualify({id, [], "init"}, Icode),
|
{_, _, QInit} = aeso_icode:qualify({id, [], "init"}, Icode),
|
||||||
case lists:keymember(QInit, 1, Funs) of
|
case lists:keymember(QInit, 1, Funs) of
|
||||||
true -> Icode;
|
true -> Icode;
|
||||||
|
false when NoCode -> Icode;
|
||||||
false when State /= {tuple, []} ->
|
false when State /= {tuple, []} ->
|
||||||
gen_error(missing_init_function);
|
gen_error(missing_init_function);
|
||||||
false ->
|
false ->
|
||||||
@@ -260,21 +263,21 @@ ast_body(?qid_app(["AENS", "preclaim"], Args, _, _), Icode) ->
|
|||||||
[word, word, sign_t()], {tuple, []});
|
[word, word, sign_t()], {tuple, []});
|
||||||
|
|
||||||
ast_body(?qid_app(["AENS", "claim"], Args, _, _), Icode) ->
|
ast_body(?qid_app(["AENS", "claim"], Args, _, _), Icode) ->
|
||||||
{Sign, [Addr, Name, Salt]} = get_signature_arg(Args),
|
{Sign, [Addr, Name, Salt, NameFee]} = get_signature_arg(Args),
|
||||||
prim_call(?PRIM_CALL_AENS_CLAIM, #integer{value = 0},
|
prim_call(?PRIM_CALL_AENS_CLAIM, #integer{value = 0},
|
||||||
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Salt, Icode), ast_body(Sign, Icode)],
|
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Salt, Icode), ast_body(Sign, Icode), ast_body(NameFee, Icode)],
|
||||||
[word, string, word, sign_t()], {tuple, []});
|
[word, string, word, sign_t(), word], {tuple, []});
|
||||||
|
|
||||||
ast_body(?qid_app(["AENS", "transfer"], Args, _, _), Icode) ->
|
ast_body(?qid_app(["AENS", "transfer"], Args, _, _), Icode) ->
|
||||||
{Sign, [FromAddr, ToAddr, NameHash]} = get_signature_arg(Args),
|
{Sign, [FromAddr, ToAddr, Name]} = get_signature_arg(Args),
|
||||||
prim_call(?PRIM_CALL_AENS_TRANSFER, #integer{value = 0},
|
prim_call(?PRIM_CALL_AENS_TRANSFER, #integer{value = 0},
|
||||||
[ast_body(FromAddr, Icode), ast_body(ToAddr, Icode), ast_body(NameHash, Icode), ast_body(Sign, Icode)],
|
[ast_body(FromAddr, Icode), ast_body(ToAddr, Icode), ast_body(Name, Icode), ast_body(Sign, Icode)],
|
||||||
[word, word, word, sign_t()], {tuple, []});
|
[word, word, word, sign_t()], {tuple, []});
|
||||||
|
|
||||||
ast_body(?qid_app(["AENS", "revoke"], Args, _, _), Icode) ->
|
ast_body(?qid_app(["AENS", "revoke"], Args, _, _), Icode) ->
|
||||||
{Sign, [Addr, NameHash]} = get_signature_arg(Args),
|
{Sign, [Addr, Name]} = get_signature_arg(Args),
|
||||||
prim_call(?PRIM_CALL_AENS_REVOKE, #integer{value = 0},
|
prim_call(?PRIM_CALL_AENS_REVOKE, #integer{value = 0},
|
||||||
[ast_body(Addr, Icode), ast_body(NameHash, Icode), ast_body(Sign, Icode)],
|
[ast_body(Addr, Icode), ast_body(Name, Icode), ast_body(Sign, Icode)],
|
||||||
[word, word, sign_t()], {tuple, []});
|
[word, word, sign_t()], {tuple, []});
|
||||||
|
|
||||||
ast_body({qid, _, ["AENS", "resolve"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.resolve'});
|
ast_body({qid, _, ["AENS", "resolve"]}, _Icode) -> gen_error({underapplied_primitive, 'AENS.resolve'});
|
||||||
@@ -728,7 +731,7 @@ ast_typerep({con, _, _}, _) ->
|
|||||||
word; %% Contract type
|
word; %% Contract type
|
||||||
ast_typerep({bytes_t, _, Len}, _) ->
|
ast_typerep({bytes_t, _, Len}, _) ->
|
||||||
bytes_t(Len);
|
bytes_t(Len);
|
||||||
ast_typerep({app_t, _, {id, _, Name}, Args}, Icode) ->
|
ast_typerep({app_t, _, {I, _, Name}, Args}, Icode) when I =:= id; I =:= qid ->
|
||||||
ArgReps = [ ast_typerep(Arg, Icode) || Arg <- Args ],
|
ArgReps = [ ast_typerep(Arg, Icode) || Arg <- Args ],
|
||||||
lookup_type_id(Name, ArgReps, Icode);
|
lookup_type_id(Name, ArgReps, Icode);
|
||||||
ast_typerep({tvar,_,A}, #{ type_vars := TypeVars }) ->
|
ast_typerep({tvar,_,A}, #{ type_vars := TypeVars }) ->
|
||||||
|
|||||||
+19
-7
@@ -35,6 +35,7 @@
|
|||||||
| pp_icode
|
| pp_icode
|
||||||
| pp_assembler
|
| pp_assembler
|
||||||
| pp_bytecode
|
| pp_bytecode
|
||||||
|
| no_code
|
||||||
| {backend, aevm | fate}
|
| {backend, aevm | fate}
|
||||||
| {include, {file_system, [string()]} |
|
| {include, {file_system, [string()]} |
|
||||||
{explicit_files, #{string() => binary()}}}
|
{explicit_files, #{string() => binary()}}}
|
||||||
@@ -120,7 +121,8 @@ from_string1(aevm, ContractString, Options) ->
|
|||||||
{ok, #{byte_code => ByteCode,
|
{ok, #{byte_code => ByteCode,
|
||||||
compiler_version => Version,
|
compiler_version => Version,
|
||||||
contract_source => ContractString,
|
contract_source => ContractString,
|
||||||
type_info => TypeInfo
|
type_info => TypeInfo,
|
||||||
|
abi_version => aeb_aevm_abi:abi_version()
|
||||||
}};
|
}};
|
||||||
from_string1(fate, ContractString, Options) ->
|
from_string1(fate, ContractString, Options) ->
|
||||||
#{fcode := FCode} = string_to_code(ContractString, Options),
|
#{fcode := FCode} = string_to_code(ContractString, Options),
|
||||||
@@ -131,10 +133,11 @@ from_string1(fate, ContractString, Options) ->
|
|||||||
compiler_version => Version,
|
compiler_version => Version,
|
||||||
contract_source => ContractString,
|
contract_source => ContractString,
|
||||||
type_info => [],
|
type_info => [],
|
||||||
fate_code => FateCode
|
fate_code => FateCode,
|
||||||
|
abi_version => aeb_fate_abi:abi_version()
|
||||||
}}.
|
}}.
|
||||||
|
|
||||||
-spec string_to_code(string(), [option()]) -> map().
|
-spec string_to_code(string(), options()) -> map().
|
||||||
string_to_code(ContractString, Options) ->
|
string_to_code(ContractString, Options) ->
|
||||||
Ast = parse(ContractString, Options),
|
Ast = parse(ContractString, Options),
|
||||||
pp_sophia_code(Ast, Options),
|
pp_sophia_code(Ast, Options),
|
||||||
@@ -290,12 +293,19 @@ to_sophia_value(ContractString, Fun, ResType, Data) ->
|
|||||||
{ok, aeso_syntax:expr()} | {error, term()}.
|
{ok, aeso_syntax:expr()} | {error, term()}.
|
||||||
to_sophia_value(_, _, error, Err, _Options) ->
|
to_sophia_value(_, _, error, Err, _Options) ->
|
||||||
{ok, {app, [], {id, [], "error"}, [{string, [], Err}]}};
|
{ok, {app, [], {id, [], "error"}, [{string, [], Err}]}};
|
||||||
to_sophia_value(_, _, revert, Data, _Options) ->
|
to_sophia_value(_, _, revert, Data, Options) ->
|
||||||
|
case proplists:get_value(backend, Options, aevm) of
|
||||||
|
aevm ->
|
||||||
case aeb_heap:from_binary(string, Data) of
|
case aeb_heap:from_binary(string, Data) of
|
||||||
{ok, Err} -> {ok, {app, [], {id, [], "abort"}, [{string, [], Err}]}};
|
{ok, Err} -> {ok, {app, [], {id, [], "abort"}, [{string, [], Err}]}};
|
||||||
{error, _} = Err -> Err
|
{error, _} = Err -> Err
|
||||||
end;
|
end;
|
||||||
to_sophia_value(ContractString, FunName, ok, Data, Options) ->
|
fate ->
|
||||||
|
Err = aeb_fate_encoding:deserialize(Data),
|
||||||
|
{ok, {app, [], {id, [], "abort"}, [{string, [], Err}]}}
|
||||||
|
end;
|
||||||
|
to_sophia_value(ContractString, FunName, ok, Data, Options0) ->
|
||||||
|
Options = [no_code | Options0],
|
||||||
try
|
try
|
||||||
Code = string_to_code(ContractString, Options),
|
Code = string_to_code(ContractString, Options),
|
||||||
#{ typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
#{ typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
||||||
@@ -355,7 +365,8 @@ create_calldata(Code, Fun, Args) ->
|
|||||||
-spec create_calldata(string(), string(), [string()], [{atom(), any()}]) ->
|
-spec create_calldata(string(), string(), [string()], [{atom(), any()}]) ->
|
||||||
{ok, binary()}
|
{ok, binary()}
|
||||||
| {error, term()}.
|
| {error, term()}.
|
||||||
create_calldata(Code, Fun, Args, Options) ->
|
create_calldata(Code, Fun, Args, Options0) ->
|
||||||
|
Options = [no_code | Options0],
|
||||||
case proplists:get_value(backend, Options, aevm) of
|
case proplists:get_value(backend, Options, aevm) of
|
||||||
aevm ->
|
aevm ->
|
||||||
case check_call(Code, Fun, Args, Options) of
|
case check_call(Code, Fun, Args, Options) of
|
||||||
@@ -377,7 +388,8 @@ create_calldata(Code, Fun, Args, Options) ->
|
|||||||
decode_calldata(ContractString, FunName, Calldata) ->
|
decode_calldata(ContractString, FunName, Calldata) ->
|
||||||
decode_calldata(ContractString, FunName, Calldata, [{backend, aevm}]).
|
decode_calldata(ContractString, FunName, Calldata, [{backend, aevm}]).
|
||||||
|
|
||||||
decode_calldata(ContractString, FunName, Calldata, Options) ->
|
decode_calldata(ContractString, FunName, Calldata, Options0) ->
|
||||||
|
Options = [no_code | Options0],
|
||||||
try
|
try
|
||||||
Code = string_to_code(ContractString, Options),
|
Code = string_to_code(ContractString, Options),
|
||||||
#{ typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
#{ typed_ast := TypedAst, type_env := TypeEnv} = Code,
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ compile(FCode, Options) ->
|
|||||||
make_function_id(X) ->
|
make_function_id(X) ->
|
||||||
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
||||||
|
|
||||||
make_function_name(init) -> <<"init">>;
|
make_function_name(init) -> <<"INIT">>;
|
||||||
make_function_name(event) -> <<"Chain.event">>;
|
make_function_name(event) -> <<"Chain.event">>;
|
||||||
make_function_name({entrypoint, Name}) -> Name;
|
make_function_name({entrypoint, Name}) -> Name;
|
||||||
make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs, ".")).
|
make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs, ".")).
|
||||||
@@ -196,7 +196,7 @@ add_default_init_function(SFuns, StateType) when StateType /= {tuple, []} ->
|
|||||||
SFuns;
|
SFuns;
|
||||||
add_default_init_function(SFuns, {tuple, []}) ->
|
add_default_init_function(SFuns, {tuple, []}) ->
|
||||||
%% Only add default if the init function is not present
|
%% Only add default if the init function is not present
|
||||||
InitName = make_function_name(init),
|
InitName = make_function_name({entrypoint, <<"init">>}),
|
||||||
case maps:find(InitName, SFuns) of
|
case maps:find(InitName, SFuns) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
SFuns;
|
SFuns;
|
||||||
@@ -547,8 +547,8 @@ builtin_to_scode(Env, aens_resolve, [_Name, _Key, _Type] = Args) ->
|
|||||||
builtin_to_scode(Env, aens_preclaim, [_Sign, _Account, _Hash] = Args) ->
|
builtin_to_scode(Env, aens_preclaim, [_Sign, _Account, _Hash] = Args) ->
|
||||||
call_to_scode(Env, [aeb_fate_ops:aens_preclaim(?a, ?a, ?a),
|
call_to_scode(Env, [aeb_fate_ops:aens_preclaim(?a, ?a, ?a),
|
||||||
tuple(0)], Args);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_claim, [_Sign, _Account, _NameString, _Salt] = Args) ->
|
builtin_to_scode(Env, aens_claim, [_Sign, _Account, _NameString, _Salt, _NameFee] = Args) ->
|
||||||
call_to_scode(Env, [aeb_fate_ops:aens_claim(?a, ?a, ?a, ?a),
|
call_to_scode(Env, [aeb_fate_ops:aens_claim(?a, ?a, ?a, ?a, ?a),
|
||||||
tuple(0)], Args);
|
tuple(0)], Args);
|
||||||
builtin_to_scode(Env, aens_transfer, [_Sign, _From, _To, _Name] = Args) ->
|
builtin_to_scode(Env, aens_transfer, [_Sign, _From, _To, _Name] = Args) ->
|
||||||
call_to_scode(Env, [aeb_fate_ops:aens_transfer(?a, ?a, ?a, ?a),
|
call_to_scode(Env, [aeb_fate_ops:aens_transfer(?a, ?a, ?a, ?a),
|
||||||
@@ -866,7 +866,7 @@ attributes(I) ->
|
|||||||
{'ORACLE_QUERY_FEE', A, B} -> Impure(A, [B]);
|
{'ORACLE_QUERY_FEE', A, B} -> Impure(A, [B]);
|
||||||
{'AENS_RESOLVE', A, B, C, D} -> Impure(A, [B, C, D]);
|
{'AENS_RESOLVE', A, B, C, D} -> Impure(A, [B, C, D]);
|
||||||
{'AENS_PRECLAIM', A, B, C} -> Impure(none, [A, B, C]);
|
{'AENS_PRECLAIM', A, B, C} -> Impure(none, [A, B, C]);
|
||||||
{'AENS_CLAIM', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
{'AENS_CLAIM', A, B, C, D, E} -> Impure(none, [A, B, C, D, E]);
|
||||||
'AENS_UPDATE' -> Impure(none, []);%% TODO
|
'AENS_UPDATE' -> Impure(none, []);%% TODO
|
||||||
{'AENS_TRANSFER', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
{'AENS_TRANSFER', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
||||||
{'AENS_REVOKE', A, B, C} -> Impure(none, [A, B, C]);
|
{'AENS_REVOKE', A, B, C} -> Impure(none, [A, B, C]);
|
||||||
@@ -1340,7 +1340,7 @@ block(Blk = #blk{code = [{switch, Arg, Type, Alts, Default} | Code],
|
|||||||
{DefRef, DefBlk} =
|
{DefRef, DefBlk} =
|
||||||
case Default of
|
case Default of
|
||||||
missing when Catchall == none ->
|
missing when Catchall == none ->
|
||||||
FreshBlk([aeb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
FreshBlk([aeb_fate_ops:exit(?i(<<"Incomplete patterns">>))], none);
|
||||||
missing -> {Catchall, []};
|
missing -> {Catchall, []};
|
||||||
_ -> FreshBlk(Default ++ [{jump, RestRef}], Catchall)
|
_ -> FreshBlk(Default ++ [{jump, RestRef}], Catchall)
|
||||||
%% ^ fall-through to the outer catchall
|
%% ^ fall-through to the outer catchall
|
||||||
@@ -1415,6 +1415,7 @@ reorder_blocks(Ref, Code, Blocks, Acc) ->
|
|||||||
[{'CALL_T', _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{'CALL_T', _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{'CALL_TR', _, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{'CALL_TR', _, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{'CALL_GTR', _, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{'CALL_GTR', _, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
|
[{'EXIT', _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{'ABORT', _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{'ABORT', _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{switch, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
[{switch, _, _}|_] -> reorder_blocks(Blocks, Acc1);
|
||||||
[{jump, L}|_] ->
|
[{jump, L}|_] ->
|
||||||
@@ -1459,6 +1460,7 @@ tweak_returns(['RETURN' | Code = [{'CALL_TR', _, _, _} | _]]) -> Code;
|
|||||||
tweak_returns(['RETURN' | Code = [{'CALL_GT', _} | _]]) -> Code;
|
tweak_returns(['RETURN' | Code = [{'CALL_GT', _} | _]]) -> Code;
|
||||||
tweak_returns(['RETURN' | Code = [{'CALL_GTR', _, _, _, _} | _]]) -> Code;
|
tweak_returns(['RETURN' | Code = [{'CALL_GTR', _, _, _, _} | _]]) -> Code;
|
||||||
tweak_returns(['RETURN' | Code = [{'ABORT', _} | _]]) -> Code;
|
tweak_returns(['RETURN' | Code = [{'ABORT', _} | _]]) -> Code;
|
||||||
|
tweak_returns(['RETURN' | Code = [{'EXIT', _} | _]]) -> Code;
|
||||||
tweak_returns(Code) -> Code.
|
tweak_returns(Code) -> Code.
|
||||||
|
|
||||||
%% -- Split basic blocks at CALL instructions --
|
%% -- Split basic blocks at CALL instructions --
|
||||||
@@ -1476,6 +1478,8 @@ split_calls(Ref, [I | Code], Acc, Blocks) when element(1, I) == 'CALL';
|
|||||||
split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]);
|
split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]);
|
||||||
split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) ->
|
split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) ->
|
||||||
lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]);
|
lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]);
|
||||||
|
split_calls(Ref, [{'EXIT', _} = I | _Code], Acc, Blocks) ->
|
||||||
|
lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]);
|
||||||
split_calls(Ref, [I | Code], Acc, Blocks) ->
|
split_calls(Ref, [I | Code], Acc, Blocks) ->
|
||||||
split_calls(Ref, Code, [I | Acc], Blocks).
|
split_calls(Ref, Code, [I | Acc], Blocks).
|
||||||
|
|
||||||
@@ -1497,4 +1501,3 @@ set_labels(_, I) -> I.
|
|||||||
|
|
||||||
with_ixs(Xs) ->
|
with_ixs(Xs) ->
|
||||||
lists:zip(lists:seq(0, length(Xs) - 1), Xs).
|
lists:zip(lists:seq(0, length(Xs) - 1), Xs).
|
||||||
|
|
||||||
|
|||||||
+12
-8
@@ -140,7 +140,8 @@ type100() -> type200().
|
|||||||
type200() ->
|
type200() ->
|
||||||
?RULE(many({fun_domain(), keyword('=>')}), type300(), fun_t(_1, _2)).
|
?RULE(many({fun_domain(), keyword('=>')}), type300(), fun_t(_1, _2)).
|
||||||
|
|
||||||
type300() -> type400().
|
type300() ->
|
||||||
|
?RULE(sep1(type400(), tok('*')), tuple_t(get_ann(lists:nth(1, _1)), _1)).
|
||||||
|
|
||||||
type400() ->
|
type400() ->
|
||||||
choice(
|
choice(
|
||||||
@@ -155,11 +156,18 @@ type400() ->
|
|||||||
|
|
||||||
typeAtom() ->
|
typeAtom() ->
|
||||||
?LAZY_P(choice(
|
?LAZY_P(choice(
|
||||||
[ id(), token(con), token(qcon), token(qid), tvar()
|
[ parens(type())
|
||||||
, ?RULE(keyword('('), comma_sep(type()), tok(')'), tuple_t(_1, _2))
|
, id(), token(con), token(qcon), token(qid), tvar()
|
||||||
])).
|
])).
|
||||||
|
|
||||||
fun_domain() -> ?RULE(?LAZY_P(type300()), fun_domain(_1)).
|
fun_domain() -> ?LAZY_P(choice(
|
||||||
|
[ ?RULE(tok('('), tok(')'), [])
|
||||||
|
%% Note avoidance of ambiguity: `(int)` can be treated as:
|
||||||
|
%% - literally `int`
|
||||||
|
%% - list of arguments with just one element – int. This approach is dropped.
|
||||||
|
, ?RULE(tok('('), type(), tok(','), sep1(type(), tok(',')), tok(')'), [_2|_4])
|
||||||
|
, ?RULE(type300(), [_1])
|
||||||
|
])).
|
||||||
|
|
||||||
%% -- Statements -------------------------------------------------------------
|
%% -- Statements -------------------------------------------------------------
|
||||||
|
|
||||||
@@ -473,10 +481,6 @@ fun_t(Domains, Type) ->
|
|||||||
tuple_e(_Ann, [Expr]) -> Expr; %% Not a tuple
|
tuple_e(_Ann, [Expr]) -> Expr; %% Not a tuple
|
||||||
tuple_e(Ann, Exprs) -> {tuple, Ann, Exprs}.
|
tuple_e(Ann, Exprs) -> {tuple, Ann, Exprs}.
|
||||||
|
|
||||||
%% TODO: not nice
|
|
||||||
fun_domain({tuple_t, _, Args}) -> Args;
|
|
||||||
fun_domain(T) -> [T].
|
|
||||||
|
|
||||||
-spec parse_pattern(aeso_syntax:expr()) -> aeso_parse_lib:parser(aeso_syntax:pat()).
|
-spec parse_pattern(aeso_syntax:expr()) -> aeso_parse_lib:parser(aeso_syntax:pat()).
|
||||||
parse_pattern({app, Ann, Con = {'::', _}, Es}) ->
|
parse_pattern({app, Ann, Con = {'::', _}, Es}) ->
|
||||||
{app, Ann, Con, lists:map(fun parse_pattern/1, Es)};
|
{app, Ann, Con, lists:map(fun parse_pattern/1, Es)};
|
||||||
|
|||||||
+15
-5
@@ -222,7 +222,7 @@ typedef({variant_t, Constructors}) ->
|
|||||||
|
|
||||||
-spec constructor_t(aeso_syntax:constructor_t()) -> doc().
|
-spec constructor_t(aeso_syntax:constructor_t()) -> doc().
|
||||||
constructor_t({constr_t, _, C, []}) -> name(C);
|
constructor_t({constr_t, _, C, []}) -> name(C);
|
||||||
constructor_t({constr_t, _, C, Args}) -> beside(name(C), tuple_type(Args)).
|
constructor_t({constr_t, _, C, Args}) -> beside(name(C), args_type(Args)).
|
||||||
|
|
||||||
-spec field_t(aeso_syntax:field_t()) -> doc().
|
-spec field_t(aeso_syntax:field_t()) -> doc().
|
||||||
field_t({field_t, _, Name, Type}) ->
|
field_t({field_t, _, Name, Type}) ->
|
||||||
@@ -234,11 +234,11 @@ type(Type, Options) ->
|
|||||||
|
|
||||||
-spec type(aeso_syntax:type()) -> doc().
|
-spec type(aeso_syntax:type()) -> doc().
|
||||||
type({fun_t, _, Named, Args, Ret}) ->
|
type({fun_t, _, Named, Args, Ret}) ->
|
||||||
follow(hsep(tuple_type(Named ++ Args), text("=>")), type(Ret));
|
follow(hsep(args_type(Named ++ Args), text("=>")), type(Ret));
|
||||||
type({app_t, _, Type, []}) ->
|
type({app_t, _, Type, []}) ->
|
||||||
type(Type);
|
type(Type);
|
||||||
type({app_t, _, Type, Args}) ->
|
type({app_t, _, Type, Args}) ->
|
||||||
beside(type(Type), tuple_type(Args));
|
beside(type(Type), args_type(Args));
|
||||||
type({tuple_t, _, Args}) ->
|
type({tuple_t, _, Args}) ->
|
||||||
tuple_type(Args);
|
tuple_type(Args);
|
||||||
type({bytes_t, _, any}) -> text("bytes(_)");
|
type({bytes_t, _, any}) -> text("bytes(_)");
|
||||||
@@ -256,10 +256,20 @@ type(T = {con, _, _}) -> name(T);
|
|||||||
type(T = {qcon, _, _}) -> name(T);
|
type(T = {qcon, _, _}) -> name(T);
|
||||||
type(T = {tvar, _, _}) -> name(T).
|
type(T = {tvar, _, _}) -> name(T).
|
||||||
|
|
||||||
-spec tuple_type([aeso_syntax:type()]) -> doc().
|
-spec args_type([aeso_syntax:type()]) -> doc().
|
||||||
tuple_type(Args) ->
|
args_type(Args) ->
|
||||||
tuple(lists:map(fun type/1, Args)).
|
tuple(lists:map(fun type/1, Args)).
|
||||||
|
|
||||||
|
-spec tuple_type([aeso_syntax:type()]) -> doc().
|
||||||
|
tuple_type([]) ->
|
||||||
|
text("unit");
|
||||||
|
tuple_type(Factors) ->
|
||||||
|
beside(
|
||||||
|
[ text("(")
|
||||||
|
, par(punctuate(text(" *"), lists:map(fun type/1, Factors)), 0)
|
||||||
|
, text(")")
|
||||||
|
]).
|
||||||
|
|
||||||
-spec arg_expr(aeso_syntax:arg_expr()) -> doc().
|
-spec arg_expr(aeso_syntax:arg_expr()) -> doc().
|
||||||
arg_expr({named_arg, _, Name, E}) ->
|
arg_expr({named_arg, _, Name, E}) ->
|
||||||
follow(hsep(expr(Name), text("=")), expr(E));
|
follow(hsep(expr(Name), text("=")), expr(E));
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ encode_decode_sophia_test() ->
|
|||||||
ok = Check("bool", "true"),
|
ok = Check("bool", "true"),
|
||||||
ok = Check("bool", "false"),
|
ok = Check("bool", "false"),
|
||||||
ok = Check("string", "\"Hello\""),
|
ok = Check("string", "\"Hello\""),
|
||||||
ok = Check("(string, list(int), option(bool))",
|
ok = Check("string * list(int) * option(bool)",
|
||||||
"(\"Hello\", [1, 2, 3], Some(true))"),
|
"(\"Hello\", [1, 2, 3], Some(true))"),
|
||||||
ok = Check("variant", "Blue({[\"x\"] = 1})"),
|
ok = Check("variant", "Blue({[\"x\"] = 1})"),
|
||||||
ok = Check("r", "{x = (\"foo\", 0), y = Red}"),
|
ok = Check("r", "{x = (\"foo\", 0), y = Red}"),
|
||||||
@@ -76,7 +76,7 @@ encode_decode_sophia_string(SophiaType, String) ->
|
|||||||
io:format("String ~p~n", [String]),
|
io:format("String ~p~n", [String]),
|
||||||
Code = [ "contract MakeCall =\n"
|
Code = [ "contract MakeCall =\n"
|
||||||
, " type arg_type = ", SophiaType, "\n"
|
, " type arg_type = ", SophiaType, "\n"
|
||||||
, " type an_alias('a) = (string, 'a)\n"
|
, " type an_alias('a) = string * 'a\n"
|
||||||
, " record r = {x : an_alias(int), y : variant}\n"
|
, " record r = {x : an_alias(int), y : variant}\n"
|
||||||
, " datatype variant = Red | Blue(map(string, int))\n"
|
, " datatype variant = Red | Blue(map(string, int))\n"
|
||||||
, " entrypoint foo : arg_type => arg_type\n" ],
|
, " entrypoint foo : arg_type => arg_type\n" ],
|
||||||
@@ -137,10 +137,10 @@ parameterized_contract(FunName, Types) ->
|
|||||||
parameterized_contract(ExtraCode, FunName, Types) ->
|
parameterized_contract(ExtraCode, FunName, Types) ->
|
||||||
lists:flatten(
|
lists:flatten(
|
||||||
["contract Remote =\n"
|
["contract Remote =\n"
|
||||||
" entrypoint bla : () => ()\n\n"
|
" entrypoint bla : () => unit\n\n"
|
||||||
"contract Dummy =\n",
|
"contract Dummy =\n",
|
||||||
ExtraCode, "\n",
|
ExtraCode, "\n",
|
||||||
" type an_alias('a) = (string, 'a)\n"
|
" type an_alias('a) = string * 'a\n"
|
||||||
" record r = {x : an_alias(int), y : variant}\n"
|
" record r = {x : an_alias(int), y : variant}\n"
|
||||||
" datatype variant = Red | Blue(map(string, int))\n"
|
" datatype variant = Red | Blue(map(string, int))\n"
|
||||||
" entrypoint ", FunName, " : (", string:join(Types, ", "), ") => int\n" ]).
|
" entrypoint ", FunName, " : (", string:join(Types, ", "), ") => int\n" ]).
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ test_cases(2) ->
|
|||||||
{Contract,MapACI,DecACI};
|
{Contract,MapACI,DecACI};
|
||||||
test_cases(3) ->
|
test_cases(3) ->
|
||||||
Contract = <<"contract C =\n"
|
Contract = <<"contract C =\n"
|
||||||
" type state = ()\n"
|
" type state = unit\n"
|
||||||
" datatype event = SingleEventDefined\n"
|
" datatype event = SingleEventDefined\n"
|
||||||
" datatype bert('a) = Bin('a)\n"
|
" datatype bert('a) = Bin('a)\n"
|
||||||
" entrypoint a(i : bert(string)) = 1\n">>,
|
" entrypoint a(i : bert(string)) = 1\n">>,
|
||||||
@@ -67,7 +67,7 @@ test_cases(3) ->
|
|||||||
stateful => false}],
|
stateful => false}],
|
||||||
name => <<"C">>,
|
name => <<"C">>,
|
||||||
event => #{variant => [#{<<"SingleEventDefined">> => []}]},
|
event => #{variant => [#{<<"SingleEventDefined">> => []}]},
|
||||||
state => #{tuple => []},
|
state => <<"unit">>,
|
||||||
type_defs =>
|
type_defs =>
|
||||||
[#{name => <<"bert">>,
|
[#{name => <<"bert">>,
|
||||||
typedef =>
|
typedef =>
|
||||||
@@ -75,7 +75,7 @@ test_cases(3) ->
|
|||||||
[#{<<"Bin">> => [<<"'a">>]}]},
|
[#{<<"Bin">> => [<<"'a">>]}]},
|
||||||
vars => [#{name => <<"'a">>}]}]}},
|
vars => [#{name => <<"'a">>}]}]}},
|
||||||
DecACI = <<"contract C =\n"
|
DecACI = <<"contract C =\n"
|
||||||
" type state = ()\n"
|
" type state = unit\n"
|
||||||
" datatype event = SingleEventDefined\n"
|
" datatype event = SingleEventDefined\n"
|
||||||
" datatype bert('a) = Bin('a)\n"
|
" datatype bert('a) = Bin('a)\n"
|
||||||
" entrypoint a : (C.bert(string)) => int\n">>,
|
" entrypoint a : (C.bert(string)) => int\n">>,
|
||||||
|
|||||||
@@ -36,10 +36,34 @@ calldata_test_() ->
|
|||||||
end
|
end
|
||||||
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
||||||
|
|
||||||
|
calldata_aci_test_() ->
|
||||||
|
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
||||||
|
fun() ->
|
||||||
|
ContractString = aeso_test_utils:read_contract(ContractName),
|
||||||
|
{ok, ContractACIBin} = aeso_aci:contract_interface(string, ContractString),
|
||||||
|
ContractACI = binary_to_list(ContractACIBin),
|
||||||
|
io:format("ACI:\n~s\n", [ContractACIBin]),
|
||||||
|
AevmExprs =
|
||||||
|
case not lists:member(ContractName, not_yet_compilable(aevm)) of
|
||||||
|
true -> ast_exprs(ContractACI, Fun, Args, [{backend, aevm}]);
|
||||||
|
false -> undefined
|
||||||
|
end,
|
||||||
|
FateExprs =
|
||||||
|
case not lists:member(ContractName, not_yet_compilable(fate)) of
|
||||||
|
true -> ast_exprs(ContractACI, Fun, Args, [{backend, fate}]);
|
||||||
|
false -> undefined
|
||||||
|
end,
|
||||||
|
case FateExprs == undefined orelse AevmExprs == undefined of
|
||||||
|
true -> ok;
|
||||||
|
false ->
|
||||||
|
?assertEqual(FateExprs, AevmExprs)
|
||||||
|
end
|
||||||
|
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
||||||
|
|
||||||
|
|
||||||
ast_exprs(ContractString, Fun, Args, Opts) ->
|
ast_exprs(ContractString, Fun, Args, Opts) ->
|
||||||
{ok, Data} = aeso_compiler:create_calldata(ContractString, Fun, Args, Opts),
|
{ok, Data} = (catch aeso_compiler:create_calldata(ContractString, Fun, Args, Opts)),
|
||||||
{ok, _Types, Exprs} = aeso_compiler:decode_calldata(ContractString, Fun, Data, Opts),
|
{ok, _Types, Exprs} = (catch aeso_compiler:decode_calldata(ContractString, Fun, Data, Opts)),
|
||||||
?assert(is_list(Exprs)),
|
?assert(is_list(Exprs)),
|
||||||
Exprs.
|
Exprs.
|
||||||
|
|
||||||
@@ -93,10 +117,12 @@ compilable_contracts() ->
|
|||||||
{"complex_types", "init", ["ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ"]},
|
{"complex_types", "init", ["ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ"]},
|
||||||
{"__call" "init", []},
|
{"__call" "init", []},
|
||||||
{"bitcoin_auth", "authorize", ["1", "#0102030405060708090a0b0c0d0e0f101718192021222324252627282930313233343536373839401a1b1c1d1e1f202122232425262728293031323334353637"]},
|
{"bitcoin_auth", "authorize", ["1", "#0102030405060708090a0b0c0d0e0f101718192021222324252627282930313233343536373839401a1b1c1d1e1f202122232425262728293031323334353637"]},
|
||||||
{"bitcoin_auth", "to_sign", ["#0102030405060708090a0b0c0d0e0f1017181920212223242526272829303132", "2"]}
|
{"bitcoin_auth", "to_sign", ["#0102030405060708090a0b0c0d0e0f1017181920212223242526272829303132", "2"]},
|
||||||
|
{"stub", "foo", ["42"]},
|
||||||
|
{"stub", "foo", ["-42"]}
|
||||||
].
|
].
|
||||||
|
|
||||||
not_yet_compilable(fate) ->
|
not_yet_compilable(fate) ->
|
||||||
["address_chain"];
|
[];
|
||||||
not_yet_compilable(aevm) ->
|
not_yet_compilable(aevm) ->
|
||||||
["__call"].
|
[].
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ compilable_contracts() ->
|
|||||||
"address_chain",
|
"address_chain",
|
||||||
"namespace_bug",
|
"namespace_bug",
|
||||||
"bytes_to_x",
|
"bytes_to_x",
|
||||||
"aens"
|
"aens",
|
||||||
|
"tuple_match"
|
||||||
].
|
].
|
||||||
|
|
||||||
not_yet_compilable(fate) -> [];
|
not_yet_compilable(fate) -> [];
|
||||||
@@ -220,7 +221,7 @@ failing_contracts() ->
|
|||||||
"when checking that 'init' returns a value of type 'state' at line 7, column 3">>]}
|
"when checking that 'init' returns a value of type 'state' at line 7, column 3">>]}
|
||||||
, {"missing_state_type",
|
, {"missing_state_type",
|
||||||
[<<"Cannot unify string\n"
|
[<<"Cannot unify string\n"
|
||||||
" and ()\n"
|
" and unit\n"
|
||||||
"when checking that 'init' returns a value of type 'state' at line 5, column 3">>]}
|
"when checking that 'init' returns a value of type 'state' at line 5, column 3">>]}
|
||||||
, {"missing_fields_in_record_expression",
|
, {"missing_fields_in_record_expression",
|
||||||
[<<"The field x is missing when constructing an element of type r('a) (at line 7, column 42)">>,
|
[<<"The field x is missing when constructing an element of type r('a) (at line 7, column 42)">>,
|
||||||
@@ -325,7 +326,7 @@ failing_contracts() ->
|
|||||||
<<"Cannot reference stateful function local_spend (at line 14, column 35)\nin the definition of non-stateful function fail2.">>,
|
<<"Cannot reference stateful function local_spend (at line 14, column 35)\nin the definition of non-stateful function fail2.">>,
|
||||||
<<"Cannot reference stateful function Chain.spend (at line 16, column 15)\nin the definition of non-stateful function fail3.">>,
|
<<"Cannot reference stateful function Chain.spend (at line 16, column 15)\nin the definition of non-stateful function fail3.">>,
|
||||||
<<"Cannot reference stateful function Chain.spend (at line 20, column 31)\nin the definition of non-stateful function fail4.">>,
|
<<"Cannot reference stateful function Chain.spend (at line 20, column 31)\nin the definition of non-stateful function fail4.">>,
|
||||||
<<"Cannot reference stateful function Chain.spend (at line 35, column 45)\nin the definition of non-stateful function fail5.">>,
|
<<"Cannot reference stateful function Chain.spend (at line 35, column 47)\nin the definition of non-stateful function fail5.">>,
|
||||||
<<"Cannot pass non-zero value argument 1000 (at line 48, column 57)\nin the definition of non-stateful function fail6.">>,
|
<<"Cannot pass non-zero value argument 1000 (at line 48, column 57)\nin the definition of non-stateful function fail6.">>,
|
||||||
<<"Cannot pass non-zero value argument 1000 (at line 49, column 56)\nin the definition of non-stateful function fail7.">>,
|
<<"Cannot pass non-zero value argument 1000 (at line 49, column 56)\nin the definition of non-stateful function fail7.">>,
|
||||||
<<"Cannot pass non-zero value argument 1000 (at line 52, column 17)\nin the definition of non-stateful function fail8.">>]}
|
<<"Cannot pass non-zero value argument 1000 (at line 52, column 17)\nin the definition of non-stateful function fail8.">>]}
|
||||||
@@ -350,7 +351,7 @@ failing_contracts() ->
|
|||||||
<<"Namespaces cannot contain entrypoints (at line 3, column 3). Use 'function' instead.">>,
|
<<"Namespaces cannot contain entrypoints (at line 3, column 3). Use 'function' instead.">>,
|
||||||
<<"The contract Remote (at line 5, column 10) has no entrypoints. Since Sophia version 3.2, public\ncontract functions must be declared with the 'entrypoint' keyword instead of\n'function'.">>,
|
<<"The contract Remote (at line 5, column 10) has no entrypoints. Since Sophia version 3.2, public\ncontract functions must be declared with the 'entrypoint' keyword instead of\n'function'.">>,
|
||||||
<<"The entrypoint wha (at line 12, column 3) cannot be private. Use 'function' instead.">>,
|
<<"The entrypoint wha (at line 12, column 3) cannot be private. Use 'function' instead.">>,
|
||||||
<<"Use 'entrypoint' for declaration of foo (at line 6, column 3):\n entrypoint foo : () => ()">>,
|
<<"Use 'entrypoint' for declaration of foo (at line 6, column 3):\n entrypoint foo : () => unit">>,
|
||||||
<<"Use 'entrypoint' instead of 'function' for public function foo (at line 10, column 3):\n entrypoint foo() = ()">>,
|
<<"Use 'entrypoint' instead of 'function' for public function foo (at line 10, column 3):\n entrypoint foo() = ()">>,
|
||||||
<<"Use 'entrypoint' instead of 'function' for public function foo (at line 6, column 3):\n entrypoint foo : () => ()">>]}
|
<<"Use 'entrypoint' instead of 'function' for public function foo (at line 6, column 3):\n entrypoint foo : () => unit">>]}
|
||||||
].
|
].
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ contract AbortTest =
|
|||||||
{ value = v }
|
{ value = v }
|
||||||
|
|
||||||
// Aborting
|
// Aborting
|
||||||
public function do_abort(v : int, s : string) : () =
|
public function do_abort(v : int, s : string) : unit =
|
||||||
put_value(v)
|
put_value(v)
|
||||||
revert_abort(s)
|
revert_abort(s)
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
contract Interface =
|
contract Interface =
|
||||||
function do_abort : (int, string) => ()
|
function do_abort : (int, string) => unit
|
||||||
function get_value : () => int
|
function get_value : () => int
|
||||||
function put_value : (int) => ()
|
function put_value : (int) => unit
|
||||||
function get_values : () => list(int)
|
function get_values : () => list(int)
|
||||||
function put_values : (int) => ()
|
function put_values : (int) => unit
|
||||||
|
|
||||||
contract AbortTestInt =
|
contract AbortTestInt =
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
contract Remote =
|
contract Remote =
|
||||||
entrypoint main : (int) => ()
|
entrypoint main : (int) => unit
|
||||||
|
|
||||||
contract AddrChain =
|
contract AddrChain =
|
||||||
type o_type = oracle(string, map(string, int))
|
type o_type = oracle(string, map(string, int))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
contract Remote =
|
contract Remote =
|
||||||
entrypoint foo : () => ()
|
entrypoint foo : () => unit
|
||||||
|
|
||||||
contract AddressLiterals =
|
contract AddressLiterals =
|
||||||
entrypoint addr() : address =
|
entrypoint addr() : address =
|
||||||
|
|||||||
+18
-17
@@ -12,44 +12,45 @@ contract AENSTest =
|
|||||||
// Transactions
|
// Transactions
|
||||||
|
|
||||||
stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
|
stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
|
||||||
chash : hash) : () = // Commitment hash
|
chash : hash) : unit = // Commitment hash
|
||||||
AENS.preclaim(addr, chash)
|
AENS.preclaim(addr, chash)
|
||||||
|
|
||||||
stateful entrypoint signedPreclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
|
stateful entrypoint signedPreclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
|
||||||
chash : hash, // Commitment hash
|
chash : hash, // Commitment hash
|
||||||
sign : signature) : () = // Signed by addr (if not Contract.address)
|
sign : signature) : unit = // Signed by addr (if not Contract.address)
|
||||||
AENS.preclaim(addr, chash, signature = sign)
|
AENS.preclaim(addr, chash, signature = sign)
|
||||||
|
|
||||||
stateful entrypoint claim(addr : address,
|
stateful entrypoint claim(addr : address,
|
||||||
name : string,
|
name : string,
|
||||||
salt : int) : () =
|
salt : int,
|
||||||
AENS.claim(addr, name, salt)
|
name_fee : int) : unit =
|
||||||
|
AENS.claim(addr, name, salt, name_fee)
|
||||||
|
|
||||||
stateful entrypoint signedClaim(addr : address,
|
stateful entrypoint signedClaim(addr : address,
|
||||||
name : string,
|
name : string,
|
||||||
salt : int,
|
salt : int,
|
||||||
sign : signature) : () =
|
name_fee : int,
|
||||||
AENS.claim(addr, name, salt, signature = sign)
|
sign : signature) : unit =
|
||||||
|
AENS.claim(addr, name, salt, name_fee, signature = sign)
|
||||||
|
|
||||||
// TODO: update() -- how to handle pointers?
|
// TODO: update() -- how to handle pointers?
|
||||||
|
|
||||||
stateful entrypoint transfer(owner : address,
|
stateful entrypoint transfer(owner : address,
|
||||||
new_owner : address,
|
new_owner : address,
|
||||||
name_hash : hash) : () =
|
name : string) : unit =
|
||||||
AENS.transfer(owner, new_owner, name_hash)
|
AENS.transfer(owner, new_owner, name)
|
||||||
|
|
||||||
stateful entrypoint signedTransfer(owner : address,
|
stateful entrypoint signedTransfer(owner : address,
|
||||||
new_owner : address,
|
new_owner : address,
|
||||||
name_hash : hash,
|
name : string,
|
||||||
sign : signature) : () =
|
sign : signature) : unit =
|
||||||
AENS.transfer(owner, new_owner, name_hash, signature = sign)
|
AENS.transfer(owner, new_owner, name, signature = sign)
|
||||||
|
|
||||||
stateful entrypoint revoke(owner : address,
|
stateful entrypoint revoke(owner : address,
|
||||||
name_hash : hash) : () =
|
name : string) : unit =
|
||||||
AENS.revoke(owner, name_hash)
|
AENS.revoke(owner, name)
|
||||||
|
|
||||||
stateful entrypoint signedRevoke(owner : address,
|
stateful entrypoint signedRevoke(owner : address,
|
||||||
name_hash : hash,
|
name : string,
|
||||||
sign : signature) : () =
|
sign : signature) : unit =
|
||||||
AENS.revoke(owner, name_hash, signature = sign)
|
AENS.revoke(owner, name, signature = sign)
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ contract AllSyntax =
|
|||||||
if(valWithType(Map.empty) == None)
|
if(valWithType(Map.empty) == None)
|
||||||
print(42 mod 10 * 5 / 3)
|
print(42 mod 10 * 5 / 3)
|
||||||
|
|
||||||
function funWithType(x : int, y) : (int, list(int)) = (x, 0 :: [y] ++ [])
|
function funWithType(x : int, y) : int * list(int) = (x, 0 :: [y] ++ [])
|
||||||
function funNoType() =
|
function funNoType() =
|
||||||
let foo = (x, y : bool) =>
|
let foo = (x, y : bool) =>
|
||||||
if (! (y && x =< 0x0b || true)) [x]
|
if (! (y && x =< 0x0b || true)) [x]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
contract Remote =
|
contract Remote =
|
||||||
entrypoint foo : () => ()
|
entrypoint foo : () => unit
|
||||||
|
|
||||||
contract AddressLiterals =
|
contract AddressLiterals =
|
||||||
entrypoint addr1() : bytes(32) =
|
entrypoint addr1() : bytes(32) =
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ contract Remote =
|
|||||||
entrypoint up_to : (int) => list(int)
|
entrypoint up_to : (int) => list(int)
|
||||||
entrypoint sum : (list(int)) => int
|
entrypoint sum : (list(int)) => int
|
||||||
entrypoint some_string : () => string
|
entrypoint some_string : () => string
|
||||||
entrypoint pair : (int, string) => (int, string)
|
entrypoint pair : (int, string) => int * string
|
||||||
entrypoint squares : (int) => list((int, int))
|
entrypoint squares : (int) => list(int * int)
|
||||||
entrypoint filter_some : (list(option(int))) => list(int)
|
entrypoint filter_some : (list(option(int))) => list(int)
|
||||||
entrypoint all_some : (list(option(int))) => option(list(int))
|
entrypoint all_some : (list(option(int))) => option(list(int))
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ contract ComplexTypes =
|
|||||||
|
|
||||||
entrypoint pair(x : int, y : string) = (x, y)
|
entrypoint pair(x : int, y : string) = (x, y)
|
||||||
|
|
||||||
entrypoint remote_pair(n : int, s : string) : (int, string) =
|
entrypoint remote_pair(n : int, s : string) : int * string =
|
||||||
state.worker.pair(gas = 10000, n, s)
|
state.worker.pair(gas = 10000, n, s)
|
||||||
|
|
||||||
entrypoint map(f, xs) =
|
entrypoint map(f, xs) =
|
||||||
@@ -58,7 +58,7 @@ contract ComplexTypes =
|
|||||||
entrypoint squares(n) =
|
entrypoint squares(n) =
|
||||||
map((i) => (i, i * i), up_to(n))
|
map((i) => (i, i * i), up_to(n))
|
||||||
|
|
||||||
entrypoint remote_squares(n) : list((int, int)) =
|
entrypoint remote_squares(n) : list(int * int) =
|
||||||
state.worker.squares(n)
|
state.worker.squares(n)
|
||||||
|
|
||||||
// option types
|
// option types
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
contract Remote =
|
contract Remote =
|
||||||
entrypoint dummy : () => ()
|
entrypoint dummy : () => unit
|
||||||
|
|
||||||
contract Events =
|
contract Events =
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ contract FunctionArguments =
|
|||||||
entrypoint traffic_light(c : colour) =
|
entrypoint traffic_light(c : colour) =
|
||||||
Red
|
Red
|
||||||
|
|
||||||
entrypoint tuples(t : ()) =
|
entrypoint tuples(t : unit) =
|
||||||
t
|
t
|
||||||
|
|
||||||
entrypoint due(t : Chain.ttl) =
|
entrypoint due(t : Chain.ttl) =
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ contract Maps =
|
|||||||
entrypoint tolist_state_s() = tolist_s(state.map_s)
|
entrypoint tolist_state_s() = tolist_s(state.map_s)
|
||||||
|
|
||||||
// Map.from_list
|
// Map.from_list
|
||||||
entrypoint fromlist_i(xs : list((int, pt))) = Map.from_list(xs)
|
entrypoint fromlist_i(xs : list(int * pt)) = Map.from_list(xs)
|
||||||
entrypoint fromlist_s(xs : list((string, pt))) = Map.from_list(xs)
|
entrypoint fromlist_s(xs : list(string * pt)) = Map.from_list(xs)
|
||||||
stateful entrypoint fromlist_state_i(xs) = put(state{ map_i = fromlist_i(xs) })
|
stateful entrypoint fromlist_state_i(xs) = put(state{ map_i = fromlist_i(xs) })
|
||||||
stateful entrypoint fromlist_state_s(xs) = put(state{ map_s = fromlist_s(xs) })
|
stateful entrypoint fromlist_state_s(xs) = put(state{ map_s = fromlist_s(xs) })
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ namespace Lib =
|
|||||||
entrypoint foo() = ()
|
entrypoint foo() = ()
|
||||||
|
|
||||||
contract Remote =
|
contract Remote =
|
||||||
public function foo : () => ()
|
public function foo : () => unit
|
||||||
function bla() = ()
|
function bla() = ()
|
||||||
|
|
||||||
contract Contract =
|
contract Contract =
|
||||||
|
|||||||
@@ -60,23 +60,23 @@ contract Oracles =
|
|||||||
res
|
res
|
||||||
|
|
||||||
stateful entrypoint extendOracle(o : oracle_id,
|
stateful entrypoint extendOracle(o : oracle_id,
|
||||||
ttl : ttl) : () =
|
ttl : ttl) : unit =
|
||||||
Oracle.extend(o, ttl)
|
Oracle.extend(o, ttl)
|
||||||
|
|
||||||
stateful entrypoint signedExtendOracle(o : oracle_id,
|
stateful entrypoint signedExtendOracle(o : oracle_id,
|
||||||
sign : signature, // Signed oracle address
|
sign : signature, // Signed oracle address
|
||||||
ttl : ttl) : () =
|
ttl : ttl) : unit =
|
||||||
Oracle.extend(o, signature = sign, ttl)
|
Oracle.extend(o, signature = sign, ttl)
|
||||||
|
|
||||||
stateful entrypoint respond(o : oracle_id,
|
stateful entrypoint respond(o : oracle_id,
|
||||||
q : query_id,
|
q : query_id,
|
||||||
r : answer_t) : () =
|
r : answer_t) : unit =
|
||||||
Oracle.respond(o, q, r)
|
Oracle.respond(o, q, r)
|
||||||
|
|
||||||
stateful entrypoint signedRespond(o : oracle_id,
|
stateful entrypoint signedRespond(o : oracle_id,
|
||||||
q : query_id,
|
q : query_id,
|
||||||
sign : signature,
|
sign : signature,
|
||||||
r : answer_t) : () =
|
r : answer_t) : unit =
|
||||||
Oracle.respond(o, q, signature = sign, r)
|
Oracle.respond(o, q, signature = sign, r)
|
||||||
|
|
||||||
entrypoint getQuestion(o : oracle_id,
|
entrypoint getQuestion(o : oracle_id,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ contract Oracles =
|
|||||||
function respond(o : oracle_id,
|
function respond(o : oracle_id,
|
||||||
q : query_id,
|
q : query_id,
|
||||||
sign : signature,
|
sign : signature,
|
||||||
r : answer_t) : () =
|
r : answer_t) : unit =
|
||||||
Oracle.respond(o, q, signature = sign, r)
|
Oracle.respond(o, q, signature = sign, r)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ contract Remote2 =
|
|||||||
|
|
||||||
contract Remote3 =
|
contract Remote3 =
|
||||||
entrypoint get : () => int
|
entrypoint get : () => int
|
||||||
entrypoint tick : () => ()
|
entrypoint tick : () => unit
|
||||||
|
|
||||||
contract RemoteCall =
|
contract RemoteCall =
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
contract Remote =
|
contract Remote =
|
||||||
record rstate = { i : int, s : string, m : map(int, int) }
|
record rstate = { i : int, s : string, m : map(int, int) }
|
||||||
|
|
||||||
entrypoint look_at : (rstate) => ()
|
entrypoint look_at : (rstate) => unit
|
||||||
entrypoint return_s : (bool) => string
|
entrypoint return_s : (bool) => string
|
||||||
entrypoint return_m : (bool) => map(int, int)
|
entrypoint return_m : (bool) => map(int, int)
|
||||||
entrypoint get : (rstate) => rstate
|
entrypoint get : (rstate) => rstate
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
contract Remote =
|
contract Remote =
|
||||||
stateful entrypoint remote_spend : (address, int) => ()
|
stateful entrypoint remote_spend : (address, int) => unit
|
||||||
entrypoint remote_pure : int => int
|
entrypoint remote_pure : int => int
|
||||||
|
|
||||||
contract Stateful =
|
contract Stateful =
|
||||||
@@ -32,7 +32,7 @@ contract Stateful =
|
|||||||
entrypoint ok4(a : address) = fail4(a)
|
entrypoint ok4(a : address) = fail4(a)
|
||||||
|
|
||||||
// Lamdbas are checked at the construction site
|
// Lamdbas are checked at the construction site
|
||||||
function fail5() : address => () = (a) => Chain.spend(a, 1000)
|
function fail5() : address => unit = (a) => Chain.spend(a, 1000)
|
||||||
|
|
||||||
// .. so you can pass a stateful lambda to a non-stateful higher-order
|
// .. so you can pass a stateful lambda to a non-stateful higher-order
|
||||||
// function:
|
// function:
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
contract Stub =
|
||||||
|
entrypoint foo : (int) => int
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
contract TuplesMatch =
|
||||||
|
|
||||||
|
entrypoint tuplify3() = (t) => switch(t)
|
||||||
|
(x, y, z) => 3
|
||||||
|
|
||||||
|
entrypoint fst(p : int * string) =
|
||||||
|
switch(p)
|
||||||
|
(x, y) => x
|
||||||
|
entrypoint fst'(p : int * string) =
|
||||||
|
switch(p)
|
||||||
|
(x, _) => x
|
||||||
|
entrypoint snd(p : int * string) =
|
||||||
|
switch(p)
|
||||||
|
(x, y) => y
|
||||||
|
entrypoint snd'(p : int * string) =
|
||||||
|
switch(p)
|
||||||
|
(_, y) => y
|
||||||
|
entrypoint sum(p) =
|
||||||
|
switch(p)
|
||||||
|
(x, y) => x + y
|
||||||
|
entrypoint swap(p : int * string) =
|
||||||
|
switch(p)
|
||||||
|
(x, y) => (y, x)
|
||||||
|
entrypoint id(p : int * int * string) =
|
||||||
|
switch(p)
|
||||||
|
(x, y, z) => (x, y, z)
|
||||||
|
entrypoint nest(p : (int * int) * string) =
|
||||||
|
switch(p)
|
||||||
|
(xy, z) => switch(xy) (x, y) => (x, y, z)
|
||||||
|
entrypoint deep(p : (int * int) * (int * int)) =
|
||||||
|
switch(p)
|
||||||
|
((x, y), (z, w)) => (x, y, z, w)
|
||||||
|
entrypoint deep_sum(p : (int * int) * (int * int)) =
|
||||||
|
switch(p)
|
||||||
|
((x, y), (z, w)) => x + y + z + w
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ contract VotingType =
|
|||||||
function delegate : address => unit
|
function delegate : address => unit
|
||||||
function vote : int => unit
|
function vote : int => unit
|
||||||
function winnerName : unit => string
|
function winnerName : unit => string
|
||||||
function currentTally : unit => list((string, int))
|
function currentTally : unit => list(string * int)
|
||||||
|
|
||||||
/* Contract implementation */
|
/* Contract implementation */
|
||||||
contract Voting =
|
contract Voting =
|
||||||
|
|||||||
Reference in New Issue
Block a user