|
|
|
@ -23,7 +23,7 @@
|
|
|
|
|
| loop
|
|
|
|
|
| tuple() | atom(). %% FATE instruction
|
|
|
|
|
|
|
|
|
|
-type arg() :: tuple(). %% Not exported: aeb_fate_ops:fate_arg().
|
|
|
|
|
-type arg() :: tuple(). %% Not exported: gmb_fate_ops:fate_arg().
|
|
|
|
|
|
|
|
|
|
%% Annotated scode
|
|
|
|
|
-type scode_a() :: [sinstr_a()].
|
|
|
|
@ -87,14 +87,14 @@ compile(ChildContracts, FCode, SavedFreshNames, Options) ->
|
|
|
|
|
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options),
|
|
|
|
|
SFuns1 = optimize_scode(SFuns, Options),
|
|
|
|
|
FateCode = to_basic_blocks(SFuns1),
|
|
|
|
|
?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]),
|
|
|
|
|
?debug(compile, Options, "~s\n", [gmb_fate_asm:pp(FateCode)]),
|
|
|
|
|
case proplists:get_value(include_child_contract_symbols, Options, false) of
|
|
|
|
|
false -> FateCode;
|
|
|
|
|
true -> add_child_symbols(ChildContracts, FateCode)
|
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
make_function_id(X) ->
|
|
|
|
|
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
|
|
|
|
gmb_fate_code:symbol_identifier(make_function_name(X)).
|
|
|
|
|
|
|
|
|
|
make_function_name(event) -> <<"Chain.event">>;
|
|
|
|
|
make_function_name({entrypoint, Name}) -> Name;
|
|
|
|
@ -103,7 +103,7 @@ make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs,
|
|
|
|
|
add_child_symbols(ChildContracts, FateCode) ->
|
|
|
|
|
Funs = lists:flatten([ maps:keys(ChildFuns) || {_, #{functions := ChildFuns}} <- maps:to_list(ChildContracts) ]),
|
|
|
|
|
Symbols = maps:from_list([ {make_function_id(FName), make_function_name(FName)} || FName <- Funs ]),
|
|
|
|
|
aeb_fate_code:update_symbols(FateCode, Symbols).
|
|
|
|
|
gmb_fate_code:update_symbols(FateCode, Symbols).
|
|
|
|
|
|
|
|
|
|
functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options) ->
|
|
|
|
|
FunNames = maps:keys(Functions),
|
|
|
|
@ -212,14 +212,14 @@ serialize_contract_code(Env, C) ->
|
|
|
|
|
SavedFreshNames = Env#env.saved_fresh_names,
|
|
|
|
|
FCode = maps:get(C, Env#env.child_contracts),
|
|
|
|
|
FateCode = compile(Env#env.child_contracts, FCode, SavedFreshNames, Options),
|
|
|
|
|
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
|
|
|
|
ByteCode = gmb_fate_code:serialize(FateCode, []),
|
|
|
|
|
{ok, Version} = aeso_compiler:version(),
|
|
|
|
|
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
|
|
|
|
Code = #{byte_code => ByteCode,
|
|
|
|
|
compiler_version => Version,
|
|
|
|
|
source_hash => crypto:hash(sha256, OriginalSourceCode ++ [0] ++ C),
|
|
|
|
|
type_info => [],
|
|
|
|
|
abi_version => aeb_fate_abi:abi_version(),
|
|
|
|
|
abi_version => gmb_fate_abi:abi_version(),
|
|
|
|
|
payable => maps:get(payable, FCode)
|
|
|
|
|
},
|
|
|
|
|
Serialized = aeser_contract_code:serialize(Code),
|
|
|
|
@ -230,17 +230,17 @@ serialize_contract_code(Env, C) ->
|
|
|
|
|
|
|
|
|
|
lit_to_fate(Env, L) ->
|
|
|
|
|
case L of
|
|
|
|
|
{int, N} -> aeb_fate_data:make_integer(N);
|
|
|
|
|
{string, S} -> aeb_fate_data:make_string(S);
|
|
|
|
|
{bytes, B} -> aeb_fate_data:make_bytes(B);
|
|
|
|
|
{bool, B} -> aeb_fate_data:make_boolean(B);
|
|
|
|
|
{account_pubkey, K} -> aeb_fate_data:make_address(K);
|
|
|
|
|
{signature, S} -> aeb_fate_data:make_bytes(S);
|
|
|
|
|
{contract_pubkey, K} -> aeb_fate_data:make_contract(K);
|
|
|
|
|
{oracle_pubkey, K} -> aeb_fate_data:make_oracle(K);
|
|
|
|
|
{oracle_query_id, H} -> aeb_fate_data:make_oracle_query(H);
|
|
|
|
|
{contract_code, C} -> aeb_fate_data:make_contract_bytearray(serialize_contract_code(Env, C));
|
|
|
|
|
{typerep, T} -> aeb_fate_data:make_typerep(type_to_scode(T))
|
|
|
|
|
{int, N} -> gmb_fate_data:make_integer(N);
|
|
|
|
|
{string, S} -> gmb_fate_data:make_string(S);
|
|
|
|
|
{bytes, B} -> gmb_fate_data:make_bytes(B);
|
|
|
|
|
{bool, B} -> gmb_fate_data:make_boolean(B);
|
|
|
|
|
{account_pubkey, K} -> gmb_fate_data:make_address(K);
|
|
|
|
|
{signature, S} -> gmb_fate_data:make_bytes(S);
|
|
|
|
|
{contract_pubkey, K} -> gmb_fate_data:make_contract(K);
|
|
|
|
|
{oracle_pubkey, K} -> gmb_fate_data:make_oracle(K);
|
|
|
|
|
{oracle_query_id, H} -> gmb_fate_data:make_oracle_query(H);
|
|
|
|
|
{contract_code, C} -> gmb_fate_data:make_contract_bytearray(serialize_contract_code(Env, C));
|
|
|
|
|
{typerep, T} -> gmb_fate_data:make_typerep(type_to_scode(T))
|
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
term_to_fate(E) -> term_to_fate(#env{}, #{}, E).
|
|
|
|
@ -250,21 +250,21 @@ term_to_fate(GlobEnv, _Env, {lit, _, L}) ->
|
|
|
|
|
lit_to_fate(GlobEnv, L);
|
|
|
|
|
%% negative literals are parsed as 0 - N
|
|
|
|
|
term_to_fate(_GlobEnv, _Env, {op, _, '-', [{lit, _, {int, 0}}, {lit, _, {int, N}}]}) ->
|
|
|
|
|
aeb_fate_data:make_integer(-N);
|
|
|
|
|
gmb_fate_data:make_integer(-N);
|
|
|
|
|
term_to_fate(_GlobEnv, _Env, {nil, _}) ->
|
|
|
|
|
aeb_fate_data:make_list([]);
|
|
|
|
|
gmb_fate_data:make_list([]);
|
|
|
|
|
term_to_fate(GlobEnv, Env, {op, _, '::', [Hd, Tl]}) ->
|
|
|
|
|
%% The Tl will translate into a list, because FATE lists are just lists
|
|
|
|
|
[term_to_fate(GlobEnv, Env, Hd) | term_to_fate(GlobEnv, Env, Tl)];
|
|
|
|
|
term_to_fate(GlobEnv, Env, {tuple, _, As}) ->
|
|
|
|
|
aeb_fate_data:make_tuple(list_to_tuple([ term_to_fate(GlobEnv, Env, A) || A<-As]));
|
|
|
|
|
gmb_fate_data:make_tuple(list_to_tuple([ term_to_fate(GlobEnv, Env, A) || A<-As]));
|
|
|
|
|
term_to_fate(GlobEnv, Env, {con, _, Ar, I, As}) ->
|
|
|
|
|
FateAs = [ term_to_fate(GlobEnv, Env, A) || A <- As ],
|
|
|
|
|
aeb_fate_data:make_variant(Ar, I, list_to_tuple(FateAs));
|
|
|
|
|
gmb_fate_data:make_variant(Ar, I, list_to_tuple(FateAs));
|
|
|
|
|
term_to_fate(_GlobEnv, _Env, {builtin, _, bits_all, []}) ->
|
|
|
|
|
aeb_fate_data:make_bits(-1);
|
|
|
|
|
gmb_fate_data:make_bits(-1);
|
|
|
|
|
term_to_fate(_GlobEnv, _Env, {builtin, _, bits_none, []}) ->
|
|
|
|
|
aeb_fate_data:make_bits(0);
|
|
|
|
|
gmb_fate_data:make_bits(0);
|
|
|
|
|
term_to_fate(GlobEnv, _Env, {op, _, bits_set, [B, I]}) ->
|
|
|
|
|
{bits, N} = term_to_fate(GlobEnv, B),
|
|
|
|
|
J = term_to_fate(GlobEnv, I),
|
|
|
|
@ -282,7 +282,7 @@ term_to_fate(_GlobEnv, Env, {var, _, X}) ->
|
|
|
|
|
V -> V
|
|
|
|
|
end;
|
|
|
|
|
term_to_fate(_GlobEnv, _Env, {builtin, _, map_empty, []}) ->
|
|
|
|
|
aeb_fate_data:make_map(#{});
|
|
|
|
|
gmb_fate_data:make_map(#{});
|
|
|
|
|
term_to_fate(GlobEnv, Env, {op, _, map_set, [M, K, V]}) ->
|
|
|
|
|
Map = term_to_fate(GlobEnv, Env, M),
|
|
|
|
|
Map#{term_to_fate(GlobEnv, Env, K) => term_to_fate(GlobEnv, Env, V)};
|
|
|
|
@ -304,7 +304,7 @@ to_scode1(Env, {lit, Ann, L}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann), push(?i(lit_to_fate(Env, L))) ];
|
|
|
|
|
|
|
|
|
|
to_scode1(Env, {nil, Ann}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann), aeb_fate_ops:nil(?a) ];
|
|
|
|
|
[ dbg_loc(Env, Ann), gmb_fate_ops:nil(?a) ];
|
|
|
|
|
|
|
|
|
|
to_scode1(Env, {var, Ann, X}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann), push(lookup_var(Env, X)) ];
|
|
|
|
@ -313,7 +313,7 @@ to_scode1(Env, {con, Ann, Ar, I, As}) ->
|
|
|
|
|
N = length(As),
|
|
|
|
|
[ dbg_loc(Env, Ann),
|
|
|
|
|
[to_scode(notail(Env), A) || A <- As],
|
|
|
|
|
aeb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N)) ];
|
|
|
|
|
gmb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N)) ];
|
|
|
|
|
|
|
|
|
|
to_scode1(Env, {tuple, Ann, As}) ->
|
|
|
|
|
N = length(As),
|
|
|
|
@ -324,13 +324,13 @@ to_scode1(Env, {tuple, Ann, As}) ->
|
|
|
|
|
to_scode1(Env, {proj, Ann, E, I}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann),
|
|
|
|
|
to_scode(notail(Env), E),
|
|
|
|
|
aeb_fate_ops:element_op(?a, ?i(I), ?a) ];
|
|
|
|
|
gmb_fate_ops:element_op(?a, ?i(I), ?a) ];
|
|
|
|
|
|
|
|
|
|
to_scode1(Env, {set_proj, Ann, R, I, E}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann),
|
|
|
|
|
to_scode(notail(Env), E),
|
|
|
|
|
to_scode(notail(Env), R),
|
|
|
|
|
aeb_fate_ops:setelement(?a, ?i(I), ?a, ?a) ];
|
|
|
|
|
gmb_fate_ops:setelement(?a, ?i(I), ?a, ?a) ];
|
|
|
|
|
|
|
|
|
|
to_scode1(Env, {op, Ann, Op, Args}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ];
|
|
|
|
@ -341,7 +341,7 @@ to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) ->
|
|
|
|
|
to_scode1(Env, {'let', Ann, X, Expr, Body}) ->
|
|
|
|
|
{I, Env1} = bind_local(X, Env),
|
|
|
|
|
SCode = [ to_scode(notail(Env), Expr),
|
|
|
|
|
aeb_fate_ops:store({var, I}, {stack, 0}),
|
|
|
|
|
gmb_fate_ops:store({var, I}, {stack, 0}),
|
|
|
|
|
to_scode(Env1, Body) ],
|
|
|
|
|
[ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], SCode) ];
|
|
|
|
|
|
|
|
|
@ -355,18 +355,18 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug_info = false
|
|
|
|
|
{I, Env2} = bind_local("_", Env1),
|
|
|
|
|
ArgCode = to_scode(notail(Env2), Arg),
|
|
|
|
|
Acc1 = [Acc, ArgCode,
|
|
|
|
|
aeb_fate_ops:store({var, I}, ?a)],
|
|
|
|
|
gmb_fate_ops:store({var, I}, ?a)],
|
|
|
|
|
{[I | Is], Acc1, Env2}
|
|
|
|
|
end, {[], [], Env}, Args),
|
|
|
|
|
[ dbg_loc(Env, Ann),
|
|
|
|
|
Code,
|
|
|
|
|
[ aeb_fate_ops:store({arg, I}, {var, J})
|
|
|
|
|
[ gmb_fate_ops:store({arg, I}, {var, J})
|
|
|
|
|
|| {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1),
|
|
|
|
|
lists:reverse(Vars)) ],
|
|
|
|
|
loop ];
|
|
|
|
|
to_scode1(Env, {def, Ann, Fun, Args}) ->
|
|
|
|
|
FName = make_function_id(Fun),
|
|
|
|
|
Lbl = aeb_fate_data:make_string(FName),
|
|
|
|
|
Lbl = gmb_fate_data:make_string(FName),
|
|
|
|
|
[ dbg_loc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ];
|
|
|
|
|
to_scode1(Env, {funcall, Ann, Fun, Args}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ];
|
|
|
|
@ -377,23 +377,23 @@ to_scode1(Env, {builtin, Ann, B, Args}) ->
|
|
|
|
|
to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) ->
|
|
|
|
|
Lbl = make_function_id(Fun),
|
|
|
|
|
{ArgTypes, RetType0} = typesig_to_scode([{"_", T} || T <- ArgsT], RetT),
|
|
|
|
|
ArgType = ?i(aeb_fate_data:make_typerep({tuple, ArgTypes})),
|
|
|
|
|
RetType = ?i(aeb_fate_data:make_typerep(RetType0)),
|
|
|
|
|
ArgType = ?i(gmb_fate_data:make_typerep({tuple, ArgTypes})),
|
|
|
|
|
RetType = ?i(gmb_fate_data:make_typerep(RetType0)),
|
|
|
|
|
SCode = case Protected of
|
|
|
|
|
{lit, _, {bool, false}} ->
|
|
|
|
|
case Gas of
|
|
|
|
|
{builtin, _, call_gas_left, _} ->
|
|
|
|
|
Call = aeb_fate_ops:call_r(?a, Lbl, ArgType, RetType, ?a),
|
|
|
|
|
Call = gmb_fate_ops:call_r(?a, Lbl, ArgType, RetType, ?a),
|
|
|
|
|
call_to_scode(Env, Call, [Ct, Value | Args]);
|
|
|
|
|
_ ->
|
|
|
|
|
Call = aeb_fate_ops:call_gr(?a, Lbl, ArgType, RetType, ?a, ?a),
|
|
|
|
|
Call = gmb_fate_ops:call_gr(?a, Lbl, ArgType, RetType, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, Call, [Ct, Value, Gas | Args])
|
|
|
|
|
end;
|
|
|
|
|
{lit, _, {bool, true}} ->
|
|
|
|
|
Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?i(true)),
|
|
|
|
|
Call = gmb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?i(true)),
|
|
|
|
|
call_to_scode(Env, Call, [Ct, Value, Gas | Args]);
|
|
|
|
|
_ ->
|
|
|
|
|
Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a),
|
|
|
|
|
Call = gmb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args])
|
|
|
|
|
end,
|
|
|
|
|
[ dbg_loc(Env, Ann) | SCode ];
|
|
|
|
@ -409,8 +409,8 @@ to_scode1(Env, {closure, Ann, Fun, FVs}) ->
|
|
|
|
|
to_scode1(Env, {switch, Ann, Case}) ->
|
|
|
|
|
[ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ].
|
|
|
|
|
|
|
|
|
|
local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun);
|
|
|
|
|
local_call(_Env, Fun) -> aeb_fate_ops:call(Fun).
|
|
|
|
|
local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> gmb_fate_ops:call_t(Fun);
|
|
|
|
|
local_call(_Env, Fun) -> gmb_fate_ops:call(Fun).
|
|
|
|
|
|
|
|
|
|
split_to_scode(Env, {nosplit, Renames, Expr}) ->
|
|
|
|
|
[switch_body, dbg_scoped_vars(Env, Renames, to_scode(Env, Expr))];
|
|
|
|
@ -448,13 +448,13 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) ->
|
|
|
|
|
[{'case', {'::', Y, Z}, S} | _] ->
|
|
|
|
|
{I, Env1} = bind_local(Y, Env),
|
|
|
|
|
{J, Env2} = bind_local(Z, Env1),
|
|
|
|
|
[aeb_fate_ops:hd({var, I}, Arg),
|
|
|
|
|
aeb_fate_ops:tl({var, J}, Arg),
|
|
|
|
|
[gmb_fate_ops:hd({var, I}, Arg),
|
|
|
|
|
gmb_fate_ops:tl({var, J}, Arg),
|
|
|
|
|
split_to_scode(Env2, S)]
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
SAlts = [GetAlt('::'), GetAlt(nil)],
|
|
|
|
|
[aeb_fate_ops:is_nil(?a, Arg),
|
|
|
|
|
[gmb_fate_ops:is_nil(?a, Arg),
|
|
|
|
|
{switch, ?a, boolean, SAlts, Def}];
|
|
|
|
|
split_to_scode(Env, {split, Type, X, Alts}) when Type == integer; Type == string ->
|
|
|
|
|
{Def, Alts1} = catchall_to_scode(Env, X, Alts),
|
|
|
|
@ -488,9 +488,9 @@ literal_split_to_scode(Env, Type, Arg, [{'case', Lit, Body} | Alts], Def) when T
|
|
|
|
|
end,
|
|
|
|
|
SLit = case Lit of
|
|
|
|
|
{int, N} -> N;
|
|
|
|
|
{string, S} -> aeb_fate_data:make_string(S)
|
|
|
|
|
{string, S} -> gmb_fate_data:make_string(S)
|
|
|
|
|
end,
|
|
|
|
|
[aeb_fate_ops:eq(?a, Arg, ?i(SLit)),
|
|
|
|
|
[gmb_fate_ops:eq(?a, Arg, ?i(SLit)),
|
|
|
|
|
{switch, ?a, boolean, [False, True], Def}].
|
|
|
|
|
|
|
|
|
|
catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []).
|
|
|
|
@ -504,10 +504,10 @@ catchall_to_scode(_, _, [], Acc) -> {missing, lists:reverse(Acc)}.
|
|
|
|
|
|
|
|
|
|
%% Tuple is in the accumulator. Arguments are the variable names.
|
|
|
|
|
match_tuple(Env, Arg, Xs) ->
|
|
|
|
|
match_tuple(Env, 0, fun aeb_fate_ops:element_op/3, Arg, Xs).
|
|
|
|
|
match_tuple(Env, 0, fun gmb_fate_ops:element_op/3, Arg, Xs).
|
|
|
|
|
|
|
|
|
|
match_variant(Env, Arg, Xs) ->
|
|
|
|
|
Elem = fun(Dst, I, Val) -> aeb_fate_ops:variant_element(Dst, Val, I) end,
|
|
|
|
|
Elem = fun(Dst, I, Val) -> gmb_fate_ops:variant_element(Dst, Val, I) end,
|
|
|
|
|
match_tuple(Env, 0, Elem, Arg, Xs).
|
|
|
|
|
|
|
|
|
|
match_tuple(Env, I, Elem, Arg, ["_" | Xs]) ->
|
|
|
|
@ -526,239 +526,239 @@ call_to_scode(Env, CallCode, Args) ->
|
|
|
|
|
CallCode].
|
|
|
|
|
|
|
|
|
|
builtin_to_scode(Env, chain_event, Args) ->
|
|
|
|
|
call_to_scode(Env, [erlang:apply(aeb_fate_ops, log, lists:duplicate(length(Args), ?a)),
|
|
|
|
|
call_to_scode(Env, [erlang:apply(gmb_fate_ops, log, lists:duplicate(length(Args), ?a)),
|
|
|
|
|
tuple(0)], Args);
|
|
|
|
|
builtin_to_scode(_Env, map_empty, []) ->
|
|
|
|
|
[aeb_fate_ops:map_empty(?a)];
|
|
|
|
|
[gmb_fate_ops:map_empty(?a)];
|
|
|
|
|
builtin_to_scode(_Env, bits_none, []) ->
|
|
|
|
|
[aeb_fate_ops:bits_none(?a)];
|
|
|
|
|
[gmb_fate_ops:bits_none(?a)];
|
|
|
|
|
builtin_to_scode(_Env, bits_all, []) ->
|
|
|
|
|
[aeb_fate_ops:bits_all(?a)];
|
|
|
|
|
[gmb_fate_ops:bits_all(?a)];
|
|
|
|
|
builtin_to_scode(Env, bytes_to_int, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_to_int(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_to_int(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, bytes_to_str, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_to_str(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_to_str(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, bytes_concat, [_, _] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_concat(?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_concat(?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, bytes_split, [_, _] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_split(?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_split(?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, bytes_split_any, [_, _] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_split_any(?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_split_any(?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, bytes_to_fixed_size, [_, _] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_to_fixed_size(?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_to_fixed_size(?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, bytes_to_any_size, [A]) ->
|
|
|
|
|
[to_scode(Env, A)]; %% no_op!
|
|
|
|
|
builtin_to_scode(Env, bytes_size, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytes_size(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytes_size(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, abort, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:abort(?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:abort(?a), Args);
|
|
|
|
|
builtin_to_scode(Env, exit, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:exit(?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:exit(?a), Args);
|
|
|
|
|
builtin_to_scode(Env, chain_spend, [_, _] = Args) ->
|
|
|
|
|
call_to_scode(Env, [aeb_fate_ops:spend(?a, ?a),
|
|
|
|
|
call_to_scode(Env, [gmb_fate_ops:spend(?a, ?a),
|
|
|
|
|
tuple(0)], Args);
|
|
|
|
|
builtin_to_scode(Env, chain_balance, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:balance_other(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:balance_other(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, chain_block_hash, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:blockhash(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:blockhash(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(_Env, chain_coinbase, []) ->
|
|
|
|
|
[aeb_fate_ops:beneficiary(?a)];
|
|
|
|
|
[gmb_fate_ops:beneficiary(?a)];
|
|
|
|
|
builtin_to_scode(_Env, chain_timestamp, []) ->
|
|
|
|
|
[aeb_fate_ops:timestamp(?a)];
|
|
|
|
|
[gmb_fate_ops:timestamp(?a)];
|
|
|
|
|
builtin_to_scode(_Env, chain_block_height, []) ->
|
|
|
|
|
[aeb_fate_ops:generation(?a)];
|
|
|
|
|
[gmb_fate_ops:generation(?a)];
|
|
|
|
|
builtin_to_scode(_Env, chain_difficulty, []) ->
|
|
|
|
|
[aeb_fate_ops:difficulty(?a)];
|
|
|
|
|
[gmb_fate_ops:difficulty(?a)];
|
|
|
|
|
builtin_to_scode(_Env, chain_gas_limit, []) ->
|
|
|
|
|
[aeb_fate_ops:gaslimit(?a)];
|
|
|
|
|
[gmb_fate_ops:gaslimit(?a)];
|
|
|
|
|
builtin_to_scode(_Env, chain_network_id, []) ->
|
|
|
|
|
[aeb_fate_ops:network_id(?a)];
|
|
|
|
|
[gmb_fate_ops:network_id(?a)];
|
|
|
|
|
builtin_to_scode(_Env, contract_balance, []) ->
|
|
|
|
|
[aeb_fate_ops:balance(?a)];
|
|
|
|
|
[gmb_fate_ops:balance(?a)];
|
|
|
|
|
builtin_to_scode(_Env, contract_address, []) ->
|
|
|
|
|
[aeb_fate_ops:address(?a)];
|
|
|
|
|
[gmb_fate_ops:address(?a)];
|
|
|
|
|
builtin_to_scode(_Env, contract_creator, []) ->
|
|
|
|
|
[aeb_fate_ops:contract_creator(?a)];
|
|
|
|
|
[gmb_fate_ops:contract_creator(?a)];
|
|
|
|
|
builtin_to_scode(_Env, call_origin, []) ->
|
|
|
|
|
[aeb_fate_ops:origin(?a)];
|
|
|
|
|
[gmb_fate_ops:origin(?a)];
|
|
|
|
|
builtin_to_scode(_Env, call_caller, []) ->
|
|
|
|
|
[aeb_fate_ops:caller(?a)];
|
|
|
|
|
[gmb_fate_ops:caller(?a)];
|
|
|
|
|
builtin_to_scode(_Env, call_value, []) ->
|
|
|
|
|
[aeb_fate_ops:call_value(?a)];
|
|
|
|
|
[gmb_fate_ops:call_value(?a)];
|
|
|
|
|
builtin_to_scode(_Env, call_gas_price, []) ->
|
|
|
|
|
[aeb_fate_ops:gasprice(?a)];
|
|
|
|
|
[gmb_fate_ops:gasprice(?a)];
|
|
|
|
|
builtin_to_scode(_Env, call_fee, []) ->
|
|
|
|
|
[aeb_fate_ops:fee(?a)];
|
|
|
|
|
[gmb_fate_ops:fee(?a)];
|
|
|
|
|
builtin_to_scode(_Env, call_gas_left, []) ->
|
|
|
|
|
[aeb_fate_ops:gas(?a)];
|
|
|
|
|
[gmb_fate_ops:gas(?a)];
|
|
|
|
|
builtin_to_scode(Env, oracle_register, [_Sign,_Account,_QFee,_TTL,_QType,_RType] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:oracle_register(?a, ?a, ?a, ?a, ?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:oracle_register(?a, ?a, ?a, ?a, ?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, oracle_expiry, [_Oracle] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:oracle_expiry(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:oracle_expiry(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, oracle_query_fee, [_Oracle] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:oracle_query_fee(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:oracle_query_fee(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, oracle_query, [_Oracle, _Question, _QFee, _QTTL, _RTTL, _QType, _RType] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:oracle_query(?a, ?a, ?a, ?a, ?a, ?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:oracle_query(?a, ?a, ?a, ?a, ?a, ?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, oracle_get_question, [_Oracle, _QueryId, _QType, _RType] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:oracle_get_question(?a, ?a, ?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:oracle_get_question(?a, ?a, ?a, ?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, oracle_respond, [_Sign, _Oracle, _QueryId, _Response, _QType, _RType] = Args) ->
|
|
|
|
|
call_to_scode(Env, [aeb_fate_ops:oracle_respond(?a, ?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, [gmb_fate_ops:oracle_respond(?a, ?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
tuple(0)], Args);
|
|
|
|
|
builtin_to_scode(Env, oracle_extend, [_Sign, _Oracle, _TTL] = Args) ->
|
|
|
|
|
call_to_scode(Env, [aeb_fate_ops:oracle_extend(?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, [gmb_fate_ops:oracle_extend(?a, ?a, ?a),
|
|
|
|
|
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);
|
|
|
|
|
call_to_scode(Env, gmb_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);
|
|
|
|
|
call_to_scode(Env, gmb_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);
|
|
|
|
|
call_to_scode(Env, gmb_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);
|
|
|
|
|
call_to_scode(Env, gmb_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);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:is_contract(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, address_is_payable, [_] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:is_payable(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:is_payable(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, aens_resolve, [_Name, _Key, _Type] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:aens_resolve(?a, ?a, ?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:aens_resolve(?a, ?a, ?a, ?a), 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, [gmb_fate_ops:aens_preclaim(?a, ?a, ?a),
|
|
|
|
|
tuple(0)], 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, ?a),
|
|
|
|
|
call_to_scode(Env, [gmb_fate_ops:aens_claim(?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
tuple(0)], 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, [gmb_fate_ops:aens_transfer(?a, ?a, ?a, ?a),
|
|
|
|
|
tuple(0)], Args);
|
|
|
|
|
builtin_to_scode(Env, aens_revoke, [_Sign, _Account, _Name] = Args) ->
|
|
|
|
|
call_to_scode(Env, [aeb_fate_ops:aens_revoke(?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, [gmb_fate_ops:aens_revoke(?a, ?a, ?a),
|
|
|
|
|
tuple(0)], Args);
|
|
|
|
|
builtin_to_scode(Env, aens_update, [_Sign, _Account, _NameString, _TTL, _ClientTTL, _Pointers] = Args) ->
|
|
|
|
|
call_to_scode(Env, [aeb_fate_ops:aens_update(?a, ?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, [gmb_fate_ops:aens_update(?a, ?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
tuple(0)], Args);
|
|
|
|
|
builtin_to_scode(Env, aens_lookup, [_Name] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:aens_lookup(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:aens_lookup(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(_Env, auth_tx_hash, []) ->
|
|
|
|
|
[aeb_fate_ops:auth_tx_hash(?a)];
|
|
|
|
|
[gmb_fate_ops:auth_tx_hash(?a)];
|
|
|
|
|
builtin_to_scode(_Env, auth_tx, []) ->
|
|
|
|
|
[aeb_fate_ops:auth_tx(?a)];
|
|
|
|
|
[gmb_fate_ops:auth_tx(?a)];
|
|
|
|
|
builtin_to_scode(Env, chain_bytecode_hash, [_Addr] = Args) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:bytecode_hash(?a, ?a), Args);
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:bytecode_hash(?a, ?a), Args);
|
|
|
|
|
builtin_to_scode(Env, chain_clone,
|
|
|
|
|
[InitArgsT, GasCap, Value, Prot, Contract | InitArgs]) ->
|
|
|
|
|
case GasCap of
|
|
|
|
|
{builtin, _, call_gas_left, _} ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:clone(?a, ?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:clone(?a, ?a, ?a, ?a),
|
|
|
|
|
[Contract, InitArgsT, Value, Prot | InitArgs]
|
|
|
|
|
);
|
|
|
|
|
_ ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a),
|
|
|
|
|
[Contract, InitArgsT, Value, GasCap, Prot | InitArgs]
|
|
|
|
|
)
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
builtin_to_scode(Env, chain_create,
|
|
|
|
|
[ Code, InitArgsT, Value | InitArgs]) ->
|
|
|
|
|
call_to_scode(Env, aeb_fate_ops:create(?a, ?a, ?a),
|
|
|
|
|
call_to_scode(Env, gmb_fate_ops:create(?a, ?a, ?a),
|
|
|
|
|
[Code, InitArgsT, Value | InitArgs]
|
|
|
|
|
).
|
|
|
|
|
|
|
|
|
|
%% -- Operators --
|
|
|
|
|
|
|
|
|
|
op_to_scode('+') -> aeb_fate_ops:add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('-') -> aeb_fate_ops:sub(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('*') -> aeb_fate_ops:mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('/') -> aeb_fate_ops:divide(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mod) -> aeb_fate_ops:modulo(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('^') -> aeb_fate_ops:pow(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('++') -> aeb_fate_ops:append(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('::') -> aeb_fate_ops:cons(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('<') -> aeb_fate_ops:lt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('>') -> aeb_fate_ops:gt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('=<') -> aeb_fate_ops:elt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('>=') -> aeb_fate_ops:egt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('==') -> aeb_fate_ops:eq(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('!=') -> aeb_fate_ops:neq(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('!') -> aeb_fate_ops:not_op(?a, ?a);
|
|
|
|
|
op_to_scode('bnot') -> aeb_fate_ops:bin_not(?a, ?a);
|
|
|
|
|
op_to_scode('band') -> aeb_fate_ops:bin_and(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('bor') -> aeb_fate_ops:bin_or(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('bxor') -> aeb_fate_ops:bin_xor(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('<<') -> aeb_fate_ops:bin_sl(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('>>') -> aeb_fate_ops:bin_sr(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_get) -> aeb_fate_ops:map_lookup(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_get_d) -> aeb_fate_ops:map_lookup(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_set) -> aeb_fate_ops:map_update(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_from_list) -> aeb_fate_ops:map_from_list(?a, ?a);
|
|
|
|
|
op_to_scode(map_to_list) -> aeb_fate_ops:map_to_list(?a, ?a);
|
|
|
|
|
op_to_scode(map_delete) -> aeb_fate_ops:map_delete(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_member) -> aeb_fate_ops:map_member(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_size) -> aeb_fate_ops:map_size_(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_length) -> aeb_fate_ops:str_length(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_concat) -> aeb_fate_ops:str_join(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_bytes) -> aeb_fate_ops:str_to_bytes(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_list) -> aeb_fate_ops:str_to_list(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_from_list) -> aeb_fate_ops:str_from_list(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_lower) -> aeb_fate_ops:str_to_lower(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_upper) -> aeb_fate_ops:str_to_upper(?a, ?a);
|
|
|
|
|
op_to_scode(char_to_int) -> aeb_fate_ops:char_to_int(?a, ?a);
|
|
|
|
|
op_to_scode(char_from_int) -> aeb_fate_ops:char_from_int(?a, ?a);
|
|
|
|
|
op_to_scode(bits_set) -> aeb_fate_ops:bits_set(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_clear) -> aeb_fate_ops:bits_clear(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_test) -> aeb_fate_ops:bits_test(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_sum) -> aeb_fate_ops:bits_sum(?a, ?a);
|
|
|
|
|
op_to_scode(bits_intersection) -> aeb_fate_ops:bits_and(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_union) -> aeb_fate_ops:bits_or(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_difference) -> aeb_fate_ops:bits_diff(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(address_to_str) -> aeb_fate_ops:addr_to_str(?a, ?a);
|
|
|
|
|
op_to_scode(address_to_bytes) -> aeb_fate_ops:addr_to_bytes(?a, ?a);
|
|
|
|
|
op_to_scode(int_to_str) -> aeb_fate_ops:int_to_str(?a, ?a);
|
|
|
|
|
op_to_scode(int_to_bytes) -> aeb_fate_ops:int_to_bytes(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(int_mulmod) -> aeb_fate_ops:mulmod(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(contract_to_address) -> aeb_fate_ops:contract_to_address(?a, ?a);
|
|
|
|
|
op_to_scode(address_to_contract) -> aeb_fate_ops:address_to_contract(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_verify_sig) -> aeb_fate_ops:verify_sig(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_verify_sig_secp256k1) -> aeb_fate_ops:verify_sig_secp256k1(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_ecverify_secp256k1) -> aeb_fate_ops:ecverify_secp256k1(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_ecrecover_secp256k1) -> aeb_fate_ops:ecrecover_secp256k1(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_sha3) -> aeb_fate_ops:sha3(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_sha256) -> aeb_fate_ops:sha256(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_poseidon) -> aeb_fate_ops:poseidon(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_sha3) -> aeb_fate_ops:sha3(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_sha256) -> aeb_fate_ops:sha256(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_neg) -> aeb_fate_ops:bls12_381_g1_neg(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_norm) -> aeb_fate_ops:bls12_381_g1_norm(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_valid) -> aeb_fate_ops:bls12_381_g1_valid(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_is_zero) -> aeb_fate_ops:bls12_381_g1_is_zero(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_add) -> aeb_fate_ops:bls12_381_g1_add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_mul) -> aeb_fate_ops:bls12_381_g1_mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_neg) -> aeb_fate_ops:bls12_381_g2_neg(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_norm) -> aeb_fate_ops:bls12_381_g2_norm(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_valid) -> aeb_fate_ops:bls12_381_g2_valid(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_is_zero) -> aeb_fate_ops:bls12_381_g2_is_zero(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_add) -> aeb_fate_ops:bls12_381_g2_add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_mul) -> aeb_fate_ops:bls12_381_g2_mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_inv) -> aeb_fate_ops:bls12_381_gt_inv(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_add) -> aeb_fate_ops:bls12_381_gt_add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_mul) -> aeb_fate_ops:bls12_381_gt_mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_pow) -> aeb_fate_ops:bls12_381_gt_pow(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_is_one) -> aeb_fate_ops:bls12_381_gt_is_one(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_pairing) -> aeb_fate_ops:bls12_381_pairing(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_miller_loop) -> aeb_fate_ops:bls12_381_miller_loop(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_final_exp) -> aeb_fate_ops:bls12_381_final_exp(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_int_to_fr) -> aeb_fate_ops:bls12_381_int_to_fr(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_int_to_fp) -> aeb_fate_ops:bls12_381_int_to_fp(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_fr_to_int) -> aeb_fate_ops:bls12_381_fr_to_int(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_fp_to_int) -> aeb_fate_ops:bls12_381_fp_to_int(?a, ?a).
|
|
|
|
|
op_to_scode('+') -> gmb_fate_ops:add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('-') -> gmb_fate_ops:sub(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('*') -> gmb_fate_ops:mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('/') -> gmb_fate_ops:divide(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mod) -> gmb_fate_ops:modulo(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('^') -> gmb_fate_ops:pow(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('++') -> gmb_fate_ops:append(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('::') -> gmb_fate_ops:cons(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('<') -> gmb_fate_ops:lt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('>') -> gmb_fate_ops:gt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('=<') -> gmb_fate_ops:elt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('>=') -> gmb_fate_ops:egt(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('==') -> gmb_fate_ops:eq(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('!=') -> gmb_fate_ops:neq(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('!') -> gmb_fate_ops:not_op(?a, ?a);
|
|
|
|
|
op_to_scode('bnot') -> gmb_fate_ops:bin_not(?a, ?a);
|
|
|
|
|
op_to_scode('band') -> gmb_fate_ops:bin_and(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('bor') -> gmb_fate_ops:bin_or(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('bxor') -> gmb_fate_ops:bin_xor(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('<<') -> gmb_fate_ops:bin_sl(?a, ?a, ?a);
|
|
|
|
|
op_to_scode('>>') -> gmb_fate_ops:bin_sr(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_get) -> gmb_fate_ops:map_lookup(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_get_d) -> gmb_fate_ops:map_lookup(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_set) -> gmb_fate_ops:map_update(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_from_list) -> gmb_fate_ops:map_from_list(?a, ?a);
|
|
|
|
|
op_to_scode(map_to_list) -> gmb_fate_ops:map_to_list(?a, ?a);
|
|
|
|
|
op_to_scode(map_delete) -> gmb_fate_ops:map_delete(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_member) -> gmb_fate_ops:map_member(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(map_size) -> gmb_fate_ops:map_size_(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_length) -> gmb_fate_ops:str_length(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_concat) -> gmb_fate_ops:str_join(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_bytes) -> gmb_fate_ops:str_to_bytes(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_list) -> gmb_fate_ops:str_to_list(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_from_list) -> gmb_fate_ops:str_from_list(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_lower) -> gmb_fate_ops:str_to_lower(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_to_upper) -> gmb_fate_ops:str_to_upper(?a, ?a);
|
|
|
|
|
op_to_scode(char_to_int) -> gmb_fate_ops:char_to_int(?a, ?a);
|
|
|
|
|
op_to_scode(char_from_int) -> gmb_fate_ops:char_from_int(?a, ?a);
|
|
|
|
|
op_to_scode(bits_set) -> gmb_fate_ops:bits_set(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_clear) -> gmb_fate_ops:bits_clear(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_test) -> gmb_fate_ops:bits_test(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_sum) -> gmb_fate_ops:bits_sum(?a, ?a);
|
|
|
|
|
op_to_scode(bits_intersection) -> gmb_fate_ops:bits_and(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_union) -> gmb_fate_ops:bits_or(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(bits_difference) -> gmb_fate_ops:bits_diff(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(address_to_str) -> gmb_fate_ops:addr_to_str(?a, ?a);
|
|
|
|
|
op_to_scode(address_to_bytes) -> gmb_fate_ops:addr_to_bytes(?a, ?a);
|
|
|
|
|
op_to_scode(int_to_str) -> gmb_fate_ops:int_to_str(?a, ?a);
|
|
|
|
|
op_to_scode(int_to_bytes) -> gmb_fate_ops:int_to_bytes(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(int_mulmod) -> gmb_fate_ops:mulmod(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(contract_to_address) -> gmb_fate_ops:contract_to_address(?a, ?a);
|
|
|
|
|
op_to_scode(address_to_contract) -> gmb_fate_ops:address_to_contract(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_verify_sig) -> gmb_fate_ops:verify_sig(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_verify_sig_secp256k1) -> gmb_fate_ops:verify_sig_secp256k1(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_ecverify_secp256k1) -> gmb_fate_ops:ecverify_secp256k1(?a, ?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_ecrecover_secp256k1) -> gmb_fate_ops:ecrecover_secp256k1(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(crypto_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_blake2b) -> gmb_fate_ops:blake2b(?a, ?a);
|
|
|
|
|
op_to_scode(crypto_poseidon) -> gmb_fate_ops:poseidon(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_sha3) -> gmb_fate_ops:sha3(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_sha256) -> gmb_fate_ops:sha256(?a, ?a);
|
|
|
|
|
op_to_scode(stringinternal_blake2b) -> gmb_fate_ops:blake2b(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_neg) -> gmb_fate_ops:bls12_381_g1_neg(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_norm) -> gmb_fate_ops:bls12_381_g1_norm(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_valid) -> gmb_fate_ops:bls12_381_g1_valid(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_is_zero) -> gmb_fate_ops:bls12_381_g1_is_zero(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_add) -> gmb_fate_ops:bls12_381_g1_add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g1_mul) -> gmb_fate_ops:bls12_381_g1_mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_neg) -> gmb_fate_ops:bls12_381_g2_neg(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_norm) -> gmb_fate_ops:bls12_381_g2_norm(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_valid) -> gmb_fate_ops:bls12_381_g2_valid(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_is_zero) -> gmb_fate_ops:bls12_381_g2_is_zero(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_add) -> gmb_fate_ops:bls12_381_g2_add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_g2_mul) -> gmb_fate_ops:bls12_381_g2_mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_inv) -> gmb_fate_ops:bls12_381_gt_inv(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_add) -> gmb_fate_ops:bls12_381_gt_add(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_mul) -> gmb_fate_ops:bls12_381_gt_mul(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_pow) -> gmb_fate_ops:bls12_381_gt_pow(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_gt_is_one) -> gmb_fate_ops:bls12_381_gt_is_one(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_pairing) -> gmb_fate_ops:bls12_381_pairing(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_miller_loop) -> gmb_fate_ops:bls12_381_miller_loop(?a, ?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_final_exp) -> gmb_fate_ops:bls12_381_final_exp(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_int_to_fr) -> gmb_fate_ops:bls12_381_int_to_fr(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_int_to_fp) -> gmb_fate_ops:bls12_381_int_to_fp(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_fr_to_int) -> gmb_fate_ops:bls12_381_fr_to_int(?a, ?a);
|
|
|
|
|
op_to_scode(mcl_bls12_381_fp_to_int) -> gmb_fate_ops:bls12_381_fp_to_int(?a, ?a).
|
|
|
|
|
|
|
|
|
|
%% PUSH and STORE ?a are the same, so we use STORE to make optimizations
|
|
|
|
|
%% easier, and specialize to PUSH (which is cheaper) at the end.
|
|
|
|
|
push(A) -> {'STORE', ?a, A}.
|
|
|
|
|
|
|
|
|
|
tuple(0) -> push(?i({tuple, {}}));
|
|
|
|
|
tuple(N) -> aeb_fate_ops:tuple(?a, N).
|
|
|
|
|
tuple(N) -> gmb_fate_ops:tuple(?a, N).
|
|
|
|
|
|
|
|
|
|
%% -- Debug info functions --
|
|
|
|
|
|
|
|
|
@ -825,8 +825,8 @@ dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) ->
|
|
|
|
|
true -> tuple_to_list(SCode);
|
|
|
|
|
false -> [SCode]
|
|
|
|
|
end,
|
|
|
|
|
Op = aeb_fate_opcodes:m_to_op(Mnemonic),
|
|
|
|
|
case aeb_fate_opcodes:end_bb(Op) of
|
|
|
|
|
Op = gmb_fate_opcodes:m_to_op(Mnemonic),
|
|
|
|
|
case gmb_fate_opcodes:end_bb(Op) of
|
|
|
|
|
true -> [Undef, SCode];
|
|
|
|
|
false -> [SCode, Undef]
|
|
|
|
|
end.
|
|
|
|
@ -898,7 +898,7 @@ pp_ann(_, []) -> [].
|
|
|
|
|
pp_op(switch_body) -> "SWITCH-BODY";
|
|
|
|
|
pp_op(loop) -> "LOOP";
|
|
|
|
|
pp_op(I) ->
|
|
|
|
|
aeb_fate_pp:format_op(I, #{}).
|
|
|
|
|
gmb_fate_pp:format_op(I, #{}).
|
|
|
|
|
|
|
|
|
|
pp_arg(?i(I)) -> io_lib:format("~w", [I]);
|
|
|
|
|
pp_arg({arg, N}) -> io_lib:format("arg~p", [N]);
|
|
|
|
@ -1668,14 +1668,14 @@ unannotate(Code) when is_list(Code) ->
|
|
|
|
|
unannotate({i, _Ann, I}) -> [I].
|
|
|
|
|
|
|
|
|
|
%% Desugar and specialize
|
|
|
|
|
desugar({'ADD', ?a, ?i(1), ?a}) -> [aeb_fate_ops:inc()];
|
|
|
|
|
desugar({'ADD', A, ?i(1), A}) -> [aeb_fate_ops:inc(desugar_arg(A))];
|
|
|
|
|
desugar({'ADD', ?a, ?a, ?i(1)}) -> [aeb_fate_ops:inc()];
|
|
|
|
|
desugar({'ADD', A, A, ?i(1)}) -> [aeb_fate_ops:inc(desugar_arg(A))];
|
|
|
|
|
desugar({'SUB', ?a, ?a, ?i(1)}) -> [aeb_fate_ops:dec()];
|
|
|
|
|
desugar({'SUB', A, A, ?i(1)}) -> [aeb_fate_ops:dec(desugar_arg(A))];
|
|
|
|
|
desugar({'STORE', ?a, A}) -> [aeb_fate_ops:push(desugar_arg(A))];
|
|
|
|
|
desugar({'STORE', R, ?a}) -> [aeb_fate_ops:pop(desugar_arg(R))];
|
|
|
|
|
desugar({'ADD', ?a, ?i(1), ?a}) -> [gmb_fate_ops:inc()];
|
|
|
|
|
desugar({'ADD', A, ?i(1), A}) -> [gmb_fate_ops:inc(desugar_arg(A))];
|
|
|
|
|
desugar({'ADD', ?a, ?a, ?i(1)}) -> [gmb_fate_ops:inc()];
|
|
|
|
|
desugar({'ADD', A, A, ?i(1)}) -> [gmb_fate_ops:inc(desugar_arg(A))];
|
|
|
|
|
desugar({'SUB', ?a, ?a, ?i(1)}) -> [gmb_fate_ops:dec()];
|
|
|
|
|
desugar({'SUB', A, A, ?i(1)}) -> [gmb_fate_ops:dec(desugar_arg(A))];
|
|
|
|
|
desugar({'STORE', ?a, A}) -> [gmb_fate_ops:push(desugar_arg(A))];
|
|
|
|
|
desugar({'STORE', R, ?a}) -> [gmb_fate_ops:pop(desugar_arg(R))];
|
|
|
|
|
desugar({switch, Arg, Type, Alts, Def}) ->
|
|
|
|
|
[{switch, desugar_arg(Arg), Type, [desugar(A) || A <- Alts], desugar(Def)}];
|
|
|
|
|
desugar(missing) -> missing;
|
|
|
|
@ -1695,11 +1695,11 @@ desugar_arg(A) -> A.
|
|
|
|
|
%% Constructing basic blocks
|
|
|
|
|
|
|
|
|
|
to_basic_blocks(Funs) ->
|
|
|
|
|
to_basic_blocks(maps:to_list(Funs), aeb_fate_code:new()).
|
|
|
|
|
to_basic_blocks(maps:to_list(Funs), gmb_fate_code:new()).
|
|
|
|
|
|
|
|
|
|
to_basic_blocks([{Name, {Attrs, Sig, Code}}|Left], Acc) ->
|
|
|
|
|
BB = bb(Name, Code ++ [aeb_fate_ops:return()]),
|
|
|
|
|
to_basic_blocks(Left, aeb_fate_code:insert_fun(Name, Attrs, Sig, BB, Acc));
|
|
|
|
|
BB = bb(Name, Code ++ [gmb_fate_ops:return()]),
|
|
|
|
|
to_basic_blocks(Left, gmb_fate_code:insert_fun(Name, Attrs, Sig, BB, Acc));
|
|
|
|
|
to_basic_blocks([], Acc) ->
|
|
|
|
|
Acc.
|
|
|
|
|
|
|
|
|
@ -1770,7 +1770,7 @@ block(Blk = #blk{code = [{switch, Arg, Type, Alts, Default} | Code],
|
|
|
|
|
{DefRef, DefBlk} =
|
|
|
|
|
case Default of
|
|
|
|
|
missing when Catchall == none ->
|
|
|
|
|
FreshBlk([aeb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
|
|
|
|
FreshBlk([gmb_fate_ops:abort(?i(<<"Incomplete patterns">>))], none);
|
|
|
|
|
missing -> {Catchall, []};
|
|
|
|
|
_ -> FreshBlk(Default ++ [{jump, RestRef}], Catchall)
|
|
|
|
|
%% ^ fall-through to the outer catchall
|
|
|
|
@ -1945,14 +1945,14 @@ split_calls(Ref, [I | Code], Acc, Blocks) ->
|
|
|
|
|
|
|
|
|
|
set_labels(Labels, {Ref, Code}) when is_reference(Ref) ->
|
|
|
|
|
{maps:get(Ref, Labels), [ set_labels(Labels, I) || I <- Code ]};
|
|
|
|
|
set_labels(_Labels, loop) -> aeb_fate_ops:jump(0);
|
|
|
|
|
set_labels(Labels, {jump, Ref}) -> aeb_fate_ops:jump(maps:get(Ref, Labels));
|
|
|
|
|
set_labels(Labels, {jumpif, Arg, Ref}) -> aeb_fate_ops:jumpif(Arg, maps:get(Ref, Labels));
|
|
|
|
|
set_labels(_Labels, loop) -> gmb_fate_ops:jump(0);
|
|
|
|
|
set_labels(Labels, {jump, Ref}) -> gmb_fate_ops:jump(maps:get(Ref, Labels));
|
|
|
|
|
set_labels(Labels, {jumpif, Arg, Ref}) -> gmb_fate_ops:jumpif(Arg, maps:get(Ref, Labels));
|
|
|
|
|
set_labels(Labels, {switch, Arg, Refs}) ->
|
|
|
|
|
case [ maps:get(Ref, Labels) || Ref <- Refs ] of
|
|
|
|
|
[R1, R2] -> aeb_fate_ops:switch(Arg, R1, R2);
|
|
|
|
|
[R1, R2, R3] -> aeb_fate_ops:switch(Arg, R1, R2, R3);
|
|
|
|
|
Rs -> aeb_fate_ops:switch(Arg, Rs)
|
|
|
|
|
[R1, R2] -> gmb_fate_ops:switch(Arg, R1, R2);
|
|
|
|
|
[R1, R2, R3] -> gmb_fate_ops:switch(Arg, R1, R2, R3);
|
|
|
|
|
Rs -> gmb_fate_ops:switch(Arg, Rs)
|
|
|
|
|
end;
|
|
|
|
|
set_labels(_, I) -> I.
|
|
|
|
|
|
|
|
|
|