Merge pull request #95 from aeternity/PT-166233670-fate-events
PT-166233670 FATE events
This commit is contained in:
commit
cfb1605a76
@ -2,7 +2,7 @@
|
||||
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"bf05e14"}}}
|
||||
{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref,"677712b"}}}
|
||||
, {getopt, "1.0.1"}
|
||||
, {jsx, {git, "https://github.com/talentdeficit/jsx.git",
|
||||
{tag, "2.8.0"}}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{"1.1.0",
|
||||
[{<<"aebytecode">>,
|
||||
{git,"https://github.com/aeternity/aebytecode.git",
|
||||
{ref,"bf05e14661ae25905bd020bfc2dcbc074f8ad66b"}},
|
||||
{ref,"677712b0b857da6a747b674b4efb1e030937f5f3"}},
|
||||
0},
|
||||
{<<"aeserialization">>,
|
||||
{git,"https://github.com/aeternity/aeserialization.git",
|
||||
|
@ -772,11 +772,13 @@ is_word_type({id, _, Name}) ->
|
||||
lists:member(Name, ["int", "address", "hash", "bits", "bool"]);
|
||||
is_word_type({app_t, _, {id, _, Name}, [_, _]}) ->
|
||||
lists:member(Name, ["oracle", "oracle_query"]);
|
||||
is_word_type({bytes_t, _, N}) -> N =< 32;
|
||||
is_word_type({con, _, _}) -> true;
|
||||
is_word_type({qcon, _, _}) -> true;
|
||||
is_word_type(_) -> false.
|
||||
|
||||
is_string_type({id, _, "string"}) -> true;
|
||||
is_string_type({bytes_t, _, N}) -> N > 32;
|
||||
is_string_type(_) -> false.
|
||||
|
||||
-spec check_constructor_overlap(env(), aeso_syntax:con(), type()) -> ok | no_return().
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
-type option() :: term().
|
||||
|
||||
-type attribute() :: stateful | pure.
|
||||
-type attribute() :: stateful | pure | private.
|
||||
|
||||
-type fun_name() :: {entrypoint, binary()}
|
||||
| {local_fun, [string()]}
|
||||
| init.
|
||||
| init | event.
|
||||
-type var_name() :: string().
|
||||
-type sophia_name() :: [string()].
|
||||
|
||||
@ -130,6 +130,7 @@
|
||||
-type env() :: #{ type_env := type_env(),
|
||||
fun_env := fun_env(),
|
||||
con_env := con_env(),
|
||||
event_type => aeso_syntax:typedef(),
|
||||
builtins := builtins(),
|
||||
options := [option()],
|
||||
context => context(),
|
||||
@ -175,11 +176,12 @@ builtins() ->
|
||||
{["Chain"], [{"spend", 2}, {"balance", 1}, {"block_hash", 1}, {"coinbase", none},
|
||||
{"timestamp", none}, {"block_height", none}, {"difficulty", none},
|
||||
{"gas_limit", none}]},
|
||||
{["Contract"], [{"address", none}, {"balance", none}]},
|
||||
{["Contract"], [{"address", none}, {"balance", none}, {"creator", none}]},
|
||||
{["Call"], [{"origin", none}, {"caller", none}, {"value", none}, {"gas_price", none},
|
||||
{"gas_left", 0}]},
|
||||
{["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}]},
|
||||
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 4}, {"transfer", 4},
|
||||
{"revoke", 3}]},
|
||||
{["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2},
|
||||
@ -192,7 +194,7 @@ builtins() ->
|
||||
{"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]},
|
||||
{["Bytes"], [{"to_int", 1}, {"to_str", 1}]},
|
||||
{["Int"], [{"to_str", 1}]},
|
||||
{["Address"], [{"to_str", 1}]}
|
||||
{["Address"], [{"to_str", 1}, {"is_oracle", 1}, {"is_contract", 1}]}
|
||||
],
|
||||
maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}}
|
||||
|| {NS, Funs} <- Scopes,
|
||||
@ -228,7 +230,7 @@ to_fcode(Env, [{contract, _, {con, _, Main}, Decls}]) ->
|
||||
MainEnv = Env#{ context => {main_contract, Main},
|
||||
builtins => Builtins#{[Main, "state"] => {get_state, none},
|
||||
[Main, "put"] => {set_state, 1},
|
||||
[Main, "Chain", "event"] => {event, 1}} },
|
||||
[Main, "Chain", "event"] => {chain_event, 1}} },
|
||||
#{ functions := Funs } = Env1 =
|
||||
decls_to_fcode(MainEnv, Decls),
|
||||
StateType = lookup_type(Env1, [Main, "state"], [], {tuple, []}),
|
||||
@ -236,7 +238,7 @@ to_fcode(Env, [{contract, _, {con, _, Main}, Decls}]) ->
|
||||
#{ contract_name => Main,
|
||||
state_type => StateType,
|
||||
event_type => EventType,
|
||||
functions => Funs };
|
||||
functions => add_event_function(Env1, EventType, Funs) };
|
||||
to_fcode(Env, [{contract, _, {con, _, Con}, Decls} | Code]) ->
|
||||
Env1 = decls_to_fcode(Env#{ context => {abstract_contract, Con} }, Decls),
|
||||
to_fcode(Env1, Code);
|
||||
@ -302,7 +304,11 @@ typedef_to_fcode(Env, {id, _, Name}, Xs, Def) ->
|
||||
_ -> #{}
|
||||
end,
|
||||
Env1 = bind_constructors(Env, Constructors),
|
||||
bind_type(Env1, Q, FDef).
|
||||
Env2 = case Name of
|
||||
"event" -> Env1#{ event_type => Def };
|
||||
_ -> Env1
|
||||
end,
|
||||
bind_type(Env2, Q, FDef).
|
||||
|
||||
-spec type_to_fcode(env(), aeso_syntax:type()) -> ftype().
|
||||
type_to_fcode(Env, Type) ->
|
||||
@ -475,7 +481,9 @@ expr_to_fcode(Env, Type, {app, _Ann, Fun = {typed, _, _, {fun_t, _, NamedArgsT,
|
||||
B =:= oracle_get_question;
|
||||
B =:= oracle_get_answer;
|
||||
B =:= oracle_respond;
|
||||
B =:= oracle_register ->
|
||||
B =:= oracle_register;
|
||||
B =:= oracle_check;
|
||||
B =:= oracle_check_query ->
|
||||
%% Get the type of the oracle from the args or the expression itself
|
||||
OType = get_oracle_type(B, Type, Args1),
|
||||
{oracle, QType, RType} = type_to_fcode(Env, OType),
|
||||
@ -547,10 +555,12 @@ make_if(Cond, Then, Else) ->
|
||||
|
||||
|
||||
get_oracle_type(oracle_register, OType, _Args) -> OType;
|
||||
get_oracle_type(oracle_query, _Type, [{typed, _,_Expr, OType}|_]) -> OType;
|
||||
get_oracle_type(oracle_get_question, _Type, [{typed, _,_Expr, OType}|_]) -> OType;
|
||||
get_oracle_type(oracle_get_answer, _Type, [{typed, _,_Expr, OType}|_]) -> OType;
|
||||
get_oracle_type(oracle_respond, _Type, [_,{typed, _,_Expr, OType}|_]) -> OType.
|
||||
get_oracle_type(oracle_query, _Type, [{typed, _, _Expr, OType} | _]) -> OType;
|
||||
get_oracle_type(oracle_get_question, _Type, [{typed, _, _Expr, OType} | _]) -> OType;
|
||||
get_oracle_type(oracle_get_answer, _Type, [{typed, _, _Expr, OType} | _]) -> OType;
|
||||
get_oracle_type(oracle_check, _Type, [{typed, _, _Expr, OType}]) -> OType;
|
||||
get_oracle_type(oracle_check_query, _Type, [{typed, _, _Expr, OType} | _]) -> OType;
|
||||
get_oracle_type(oracle_respond, _Type, [_, {typed, _,_Expr, OType} | _]) -> OType.
|
||||
|
||||
%% -- Pattern matching --
|
||||
|
||||
@ -783,6 +793,8 @@ op_builtins() ->
|
||||
|
||||
builtin_to_fcode(require, [Cond, Msg]) ->
|
||||
make_if(Cond, {tuple, []}, {builtin, abort, [Msg]});
|
||||
builtin_to_fcode(chain_event, [Event]) ->
|
||||
{def, event, [Event]};
|
||||
builtin_to_fcode(map_delete, [Key, Map]) ->
|
||||
{op, map_delete, [Map, Key]};
|
||||
builtin_to_fcode(map_member, [Key, Map]) ->
|
||||
@ -801,6 +813,35 @@ builtin_to_fcode(Builtin, Args) ->
|
||||
false -> {builtin, Builtin, Args}
|
||||
end.
|
||||
|
||||
%% -- Event function --
|
||||
|
||||
add_event_function(_Env, none, Funs) -> Funs;
|
||||
add_event_function(Env, EventFType, Funs) ->
|
||||
Funs#{ event => event_function(Env, EventFType) }.
|
||||
|
||||
event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {variant, FCons}) ->
|
||||
Cons = [ {Name, I - 1, proplists:get_value(indices, Ann)}
|
||||
|| {I, {constr_t, Ann, {con, _, Name}, _}} <- indexed(EventCons) ],
|
||||
Arities = [length(Ts) || Ts <- FCons],
|
||||
Case = fun({Name, Tag, Ixs}) ->
|
||||
%% TODO: precompute (needs dependency)
|
||||
Hash = {op, crypto_sha3, [{lit, {string, list_to_binary(Name)}}]},
|
||||
Vars = [ "arg" ++ integer_to_list(I) || I <- lists:seq(1, length(Ixs)) ],
|
||||
IVars = lists:zip(Ixs, Vars),
|
||||
Payload =
|
||||
case [ V || {notindexed, V} <- IVars ] of
|
||||
[] -> {lit, {string, <<>>}};
|
||||
[V] -> {var, V}
|
||||
end,
|
||||
Indices = [ {var, V} || {indexed, V} <- IVars ],
|
||||
Body = {builtin, chain_event, [Payload, Hash | Indices]},
|
||||
{'case', {con, Arities, Tag, Vars}, {nosplit, Body}}
|
||||
end,
|
||||
#{ attrs => [private],
|
||||
args => [{"e", EventType}],
|
||||
return => {tuple, []},
|
||||
body => {switch, {split, EventType, "e", lists:map(Case, Cons)}} }.
|
||||
|
||||
%% -- Lambda lifting ---------------------------------------------------------
|
||||
%% The expr_to_fcode compiler lambda expressions to {lam, Xs, Body}, but in
|
||||
%% FATE we can only call top-level functions, so we need to lift the lambda to
|
||||
@ -1232,7 +1273,8 @@ pp_fun(Name, #{ args := Args, return := Return, body := Body }) ->
|
||||
pp_text(" : "), pp_ftype(Return), pp_text(" =")]),
|
||||
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({entrypoint, E}) -> pp_text(binary_to_list(E));
|
||||
pp_fun_name({local_fun, Q}) -> pp_text(string:join(Q, ".")).
|
||||
|
||||
@ -1261,6 +1303,8 @@ pp_punctuate(Sep, [X | Xs]) -> [pp_beside(X, Sep) | pp_punctuate(Sep, Xs)].
|
||||
|
||||
pp_par([]) -> prettypr:empty();
|
||||
pp_par(Xs) -> prettypr:par(Xs).
|
||||
pp_fexpr({lit, {typerep, T}}) ->
|
||||
pp_ftype(T);
|
||||
pp_fexpr({lit, {Tag, Lit}}) ->
|
||||
aeso_pretty:expr({Tag, [], Lit});
|
||||
pp_fexpr(nil) ->
|
||||
@ -1321,18 +1365,23 @@ pp_fexpr({switch, Split}) -> pp_split(Split).
|
||||
pp_call(Fun, Args) ->
|
||||
pp_beside(Fun, pp_fexpr({tuple, Args})).
|
||||
|
||||
pp_call_t(Fun, Args) ->
|
||||
pp_beside(pp_text(Fun), pp_ftype({tuple, Args})).
|
||||
|
||||
-spec pp_ftype(ftype()) -> any().
|
||||
pp_ftype(T) when is_atom(T) -> pp_text(T);
|
||||
pp_ftype(any) -> pp_text("_");
|
||||
pp_ftype({tvar, X}) -> pp_text(X);
|
||||
pp_ftype({bytes, N}) -> pp_text("bytes(" ++ integer_to_list(N) ++ ")");
|
||||
pp_ftype({bytes, N}) -> pp_call(pp_text("bytes"), [{lit, {int, N}}]);
|
||||
pp_ftype({oracle, Q, R}) -> pp_call_t("oracle", [Q, R]);
|
||||
pp_ftype({tuple, Ts}) ->
|
||||
pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_ftype(T) || T <- Ts])));
|
||||
pp_ftype({list, T}) ->
|
||||
pp_beside([pp_text("list("), pp_ftype(T), pp_text(")")]);
|
||||
pp_call_t("list", [T]);
|
||||
pp_ftype({function, Args, Res}) ->
|
||||
pp_par([pp_ftype({tuple, Args}), pp_text("=>"), pp_ftype(Res)]);
|
||||
pp_ftype({map, Key, Val}) ->
|
||||
pp_beside([pp_text("map"), pp_ftype({tuple, [Key, Val]})]);
|
||||
pp_call_t("map", [Key, Val]);
|
||||
pp_ftype({variant, Cons}) ->
|
||||
pp_par(
|
||||
pp_punctuate(pp_text(" |"),
|
||||
|
@ -119,11 +119,12 @@ check_event_type(EvtName, Ix, Type, Icode) ->
|
||||
catch _:_ ->
|
||||
error({EvtName, could_not_resolve_type, Type})
|
||||
end,
|
||||
case {Ix, VMType} of
|
||||
{indexed, word} -> ok;
|
||||
{notindexed, string} -> ok;
|
||||
{indexed, _} -> error({EvtName, indexed_field_should_be_word, is, VMType});
|
||||
{notindexed, _} -> error({EvtName, payload_should_be_string, is, VMType})
|
||||
case {Ix, VMType, Type} of
|
||||
{indexed, word, _} -> ok;
|
||||
{notindexed, string, _} -> ok;
|
||||
{notindexed, _, {bytes_t, _, N}} when N > 32 -> ok;
|
||||
{indexed, _, _} -> error({EvtName, indexed_field_should_be_word, is, VMType});
|
||||
{notindexed, _, _} -> error({EvtName, payload_should_be_string, is, VMType})
|
||||
end.
|
||||
|
||||
bfun(B, {IArgs, IExpr, IRet}) ->
|
||||
@ -178,15 +179,21 @@ builtin_event(EventT) ->
|
||||
ArgPats = fun(Ts) -> [ VIx(Ix) || Ix <- lists:seq(0, length(Ts) - 1) ] end,
|
||||
Payload = %% Should put data ptr, length on stack.
|
||||
fun([]) -> {inline_asm, [A(?PUSH1), 0, A(?PUSH1), 0]};
|
||||
([V]) -> {seq, [V, {inline_asm, [A(?DUP1), A(?MLOAD), %% length, ptr
|
||||
A(?SWAP1), A(?PUSH1), 32, A(?ADD)]}]} %% ptr+32, length
|
||||
([{{id, _, "string"}, V}]) ->
|
||||
{seq, [V, {inline_asm, [A(?DUP1), A(?MLOAD), %% length, ptr
|
||||
A(?SWAP1), A(?PUSH1), 32, A(?ADD)]}]}; %% ptr+32, length
|
||||
([{{bytes_t, _, N}, V}]) -> {seq, [V, {integer, N}, {inline_asm, A(?SWAP1)}]}
|
||||
end,
|
||||
Ix =
|
||||
fun({bytes_t, _, N}, V) when N < 32 -> ?BSR(V, 32 - N);
|
||||
(_, V) -> V end,
|
||||
Clause =
|
||||
fun(_Tag, {con, _, Con}, IxTypes) ->
|
||||
Types = [ T || {_Ix, T} <- IxTypes ],
|
||||
Indexed = [ Var || {Var, {indexed, _Type}} <- lists:zip(ArgPats(Types), IxTypes) ],
|
||||
Indexed = [ Ix(Type, Var) || {Var, {indexed, Type}} <- lists:zip(ArgPats(Types), IxTypes) ],
|
||||
Data = [ {Type, Var} || {Var, {notindexed, Type}} <- lists:zip(ArgPats(Types), IxTypes) ],
|
||||
EvtIndex = {unop, 'sha3', str_to_icode(Con)},
|
||||
{event, lists:reverse(Indexed) ++ [EvtIndex], Payload(ArgPats(Types) -- Indexed)}
|
||||
{event, lists:reverse(Indexed) ++ [EvtIndex], Payload(Data)}
|
||||
end,
|
||||
Pat = fun(Tag, Types) -> {tuple, [{integer, Tag} | ArgPats(Types)]} end,
|
||||
|
||||
|
@ -104,6 +104,11 @@
|
||||
Op =:= 'AUTH_TX_HASH' orelse
|
||||
Op =:= 'BYTES_TO_INT' orelse
|
||||
Op =:= 'BYTES_TO_STR' orelse
|
||||
Op =:= 'ORACLE_CHECK' orelse
|
||||
Op =:= 'ORACLE_CHECK_QUERY' orelse
|
||||
Op =:= 'IS_ORACLE' orelse
|
||||
Op =:= 'IS_CONTRACT' orelse
|
||||
Op =:= 'CREATOR' orelse
|
||||
false)).
|
||||
|
||||
-record(env, { contract, vars = [], locals = [], tailpos = true }).
|
||||
@ -135,6 +140,7 @@ make_function_id(X) ->
|
||||
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
||||
|
||||
make_function_name(init) -> <<"init">>;
|
||||
make_function_name(event) -> <<"Chain.event">>;
|
||||
make_function_name({entrypoint, Name}) -> Name;
|
||||
make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs, ".")).
|
||||
|
||||
@ -464,8 +470,9 @@ builtin_to_scode(_Env, get_state, []) ->
|
||||
builtin_to_scode(Env, set_state, [_] = Args) ->
|
||||
call_to_scode(Env, [aeb_fate_ops:store(?s, ?a),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(_Env, event, [_] = _Args) ->
|
||||
?TODO(fate_event_instruction);
|
||||
builtin_to_scode(Env, chain_event, Args) ->
|
||||
call_to_scode(Env, [erlang:apply(aeb_fate_ops, log, lists:duplicate(length(Args), ?a)),
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(_Env, map_empty, []) ->
|
||||
[aeb_fate_ops:map_empty(?a)];
|
||||
builtin_to_scode(_Env, bits_none, []) ->
|
||||
@ -499,6 +506,8 @@ builtin_to_scode(_Env, contract_balance, []) ->
|
||||
[aeb_fate_ops:balance(?a)];
|
||||
builtin_to_scode(_Env, contract_address, []) ->
|
||||
[aeb_fate_ops:address(?a)];
|
||||
builtin_to_scode(_Env, contract_creator, []) ->
|
||||
[aeb_fate_ops:contract_creator(?a)];
|
||||
builtin_to_scode(_Env, call_origin, []) ->
|
||||
[aeb_fate_ops:origin(?a)];
|
||||
builtin_to_scode(_Env, call_caller, []) ->
|
||||
@ -525,6 +534,14 @@ builtin_to_scode(Env, oracle_extend, [_Sign, _Oracle, _TTL] = Args) ->
|
||||
tuple(0)], Args);
|
||||
builtin_to_scode(Env, oracle_get_answer, [_Oracle, _QueryId, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_get_answer(?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_check, [_Oracle, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_check(?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, oracle_check_query, [_Oracle, _Query, _QType, _RType] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:oracle_check_query(?a, ?a, ?a, ?a, ?a), Args);
|
||||
builtin_to_scode(Env, address_is_oracle, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:is_oracle(?a, ?a), Args);
|
||||
builtin_to_scode(Env, address_is_contract, [_] = Args) ->
|
||||
call_to_scode(Env, aeb_fate_ops:is_contract(?a, ?a), Args);
|
||||
builtin_to_scode(_Env, aens_resolve, [_, _] = _Args) ->
|
||||
?TODO(fate_aens_resolve_instruction);
|
||||
builtin_to_scode(_Env, aens_preclaim, [_, _, _] = _Args) ->
|
||||
@ -810,6 +827,11 @@ attributes(I) ->
|
||||
{'AUTH_TX_HASH', A} -> Pure(A, []);
|
||||
{'BYTES_TO_INT', A, B} -> Pure(A, [B]);
|
||||
{'BYTES_TO_STR', A, B} -> Pure(A, [B]);
|
||||
{'ORACLE_CHECK', A, B, C, D} -> Impure(A, [B, C, D]);
|
||||
{'ORACLE_CHECK_QUERY', A, B, C, D, E} -> Impure(A, [B, C, D, E]);
|
||||
{'IS_ORACLE', A, B} -> Impure(A, [B]);
|
||||
{'IS_CONTRACT', A, B} -> Impure(A, [B]);
|
||||
{'CREATOR', A} -> Pure(A, []);
|
||||
{'ADDRESS', A} -> Pure(A, []);
|
||||
{'BALANCE', A} -> Impure(A, []);
|
||||
{'BALANCE_OTHER', A, B} -> Impure(A, [B]);
|
||||
@ -824,11 +846,11 @@ attributes(I) ->
|
||||
{'DIFFICULTY', A} -> Pure(A, []);
|
||||
{'GASLIMIT', A} -> Pure(A, []);
|
||||
{'GAS', A} -> Impure(?a, A);
|
||||
{'LOG0', A, B} -> Impure(none, [A, B]);
|
||||
{'LOG1', A, B, C} -> Impure(none, [A, B, C]);
|
||||
{'LOG2', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
||||
{'LOG3', A, B, C, D, E} -> Impure(none, [A, B, C, D, E]);
|
||||
{'LOG4', A, B, C, D, E, F} -> Impure(none, [A, B, C, D, E, F]);
|
||||
{'LOG0', A} -> Impure(none, [A]);
|
||||
{'LOG1', A, B} -> Impure(none, [A, B]);
|
||||
{'LOG2', A, B, C} -> Impure(none, [A, B, C]);
|
||||
{'LOG3', A, B, C, D} -> Impure(none, [A, B, C, D]);
|
||||
{'LOG4', A, B, C, D, E} -> Impure(none, [A, B, C, D, E]);
|
||||
'DEACTIVATE' -> Impure(none, []);
|
||||
{'SPEND', A, B} -> Impure(none, [A, B]);
|
||||
|
||||
|
@ -330,6 +330,7 @@ expr_p(_, {Type, _, Bin})
|
||||
Type == oracle_pubkey;
|
||||
Type == oracle_query_id ->
|
||||
text(binary_to_list(aeser_api_encoder:encode(Type, Bin)));
|
||||
expr_p(_, {string, _, <<>>}) -> text("\"\"");
|
||||
expr_p(_, {string, _, S}) -> term(binary_to_list(S));
|
||||
expr_p(_, {char, _, C}) ->
|
||||
case C of
|
||||
|
@ -119,11 +119,7 @@ compilable_contracts() ->
|
||||
"bytes_to_x"
|
||||
].
|
||||
|
||||
not_yet_compilable(fate) ->
|
||||
["events", %% events
|
||||
"address_literals", %% oracle_query_id literals
|
||||
"address_chain" %% Oracle.check_query
|
||||
];
|
||||
not_yet_compilable(fate) -> [];
|
||||
not_yet_compilable(aevm) -> [].
|
||||
|
||||
%% Contracts that should produce type errors
|
||||
|
@ -1,22 +1,40 @@
|
||||
contract Remote =
|
||||
function dummy : () => ()
|
||||
|
||||
contract Events =
|
||||
type alias_int = int
|
||||
type alias_address = address
|
||||
type alias_string = string
|
||||
|
||||
datatype event =
|
||||
Event1(indexed alias_int, indexed int, string)
|
||||
| Event2(alias_string, indexed alias_address)
|
||||
// | BadEvent1(indexed string, string)
|
||||
// | BadEvent2(indexed int, int)
|
||||
// Valid index types
|
||||
type ix1 = int
|
||||
type ix2 = bool
|
||||
type ix3 = bits
|
||||
type ix4 = bytes(12)
|
||||
type ix5 = hash // bytes(32)
|
||||
type ix6 = address
|
||||
type ix7 = Remote
|
||||
type ix8 = oracle(int, int)
|
||||
type ix9 = oracle_query(int, int)
|
||||
|
||||
function f1(x : int, y : string) =
|
||||
Chain.event(Event1(x, x+1, y))
|
||||
// Valid payload types
|
||||
type data1 = string
|
||||
type data2 = signature // bytes(64)
|
||||
type data3 = bytes(65)
|
||||
|
||||
function f2(s : string) =
|
||||
Chain.event(Event2(s, Call.caller))
|
||||
datatype event
|
||||
= Nodata0
|
||||
| Nodata1(ix1)
|
||||
| Nodata2(ix2, ix3)
|
||||
| Nodata3(ix4, ix5, ix6)
|
||||
| Data0(data1)
|
||||
| Data1(data2, ix7)
|
||||
| Data2(ix8, data3, ix9)
|
||||
| Data3(ix1, ix2, ix5, data1)
|
||||
|
||||
function f3(x : int) =
|
||||
Chain.event(Event1(x, x + 2, Int.to_str(x + 7)))
|
||||
function nodata0() = Chain.event(Nodata0)
|
||||
function nodata1(ix1) = Chain.event(Nodata1(ix1))
|
||||
function nodata2(ix2, ix3) = Chain.event(Nodata2(ix2, ix3))
|
||||
function nodata3(ix4, ix5, ix6) = Chain.event(Nodata3(ix4, ix5, ix6))
|
||||
function data0(data1) = Chain.event(Data0(data1))
|
||||
function data1(data2, ix7) = Chain.event(Data1(data2, ix7))
|
||||
function data2(ix8, data3, ix9) = Chain.event(Data2(ix8, data3, ix9))
|
||||
function data3(ix1, ix2, ix5, data1) = Chain.event(Data3(ix1, ix2, ix5, data1))
|
||||
|
||||
function i2s(i : int) = Int.to_str(i)
|
||||
function a2s(a : address) = Address.to_str(a)
|
||||
|
Loading…
x
Reference in New Issue
Block a user