update changes from epoch master
This commit is contained in:
parent
66b1d2e98a
commit
4853d386e4
@ -8,24 +8,10 @@
|
||||
|
||||
-module(aeso_test_utils).
|
||||
|
||||
-include("apps/aecontract/src/aecontract.hrl").
|
||||
|
||||
-export([read_contract/1, contract_path/0, pp/1, pp/2,
|
||||
dump_words/1, show_heap/1, show_heap/2, show_heap_value/1, compile/1]).
|
||||
|
||||
-export([spend/3, get_balance/2, call_contract/6, get_store/1, set_store/2,
|
||||
aens_lookup/4]).
|
||||
-export([read_contract/1, contract_path/0]).
|
||||
|
||||
contract_path() ->
|
||||
{ok, Cwd} = file:get_cwd(),
|
||||
N = length(filename:split(Cwd)),
|
||||
Rel = ["apps", "aesophia", "test", "contracts"],
|
||||
%% Try the first matching directory (../)*Rel
|
||||
Cand = fun(I) -> filename:join(lists:duplicate(I, "..") ++ Rel) end,
|
||||
case [ Dir || Dir <- lists:map(Cand, lists:seq(0, N)), filelib:is_dir(Dir) ] of
|
||||
[Dir | _] -> Dir;
|
||||
[] -> error(failed_to_find_contract_dir)
|
||||
end.
|
||||
filename:join(code:lib_dir(aesophia, test), "contracts").
|
||||
|
||||
%% Read a contract file from the test/contracts directory.
|
||||
-spec read_contract(string() | atom()) -> string().
|
||||
@ -33,128 +19,3 @@ read_contract(Name) ->
|
||||
{ok, Bin} = file:read_file(filename:join(contract_path(), lists:concat([Name, ".aes"]))),
|
||||
binary_to_list(Bin).
|
||||
|
||||
pp(Name) -> pp(Name, []).
|
||||
|
||||
pp(Name, Options) ->
|
||||
case aeso_parser:string(read_contract(Name)) of
|
||||
{ok, AST} ->
|
||||
[ io:format("~s\n", [prettypr:format(aeso_pretty:decls(AST))]) || not lists:member(quiet, Options) ];
|
||||
{error, {{L, C}, parse_error, Err}} ->
|
||||
io:format("Parse error at ~p:~p:~p\n~s\n", [Name, L, C, Err])
|
||||
end.
|
||||
|
||||
compile(Name) ->
|
||||
aeso_compiler:from_string(read_contract(Name),
|
||||
[pp_sophia_code, pp_typed_ast, pp_icode]).
|
||||
|
||||
%% Stack simulator
|
||||
|
||||
simulate([],Stack) ->
|
||||
Stack;
|
||||
simulate(['PUSH1',X|More],S) ->
|
||||
simulate(More,[X|S]);
|
||||
simulate([Op|More],Stack) ->
|
||||
simulate(More,simulate(Op,Stack));
|
||||
simulate('MSIZE',S) ->
|
||||
A = new_atom(),
|
||||
io:format("~p = MSIZE\n",[A]),
|
||||
[A|S];
|
||||
simulate('DUP2',[A,B|S]) ->
|
||||
[B,A,B|S];
|
||||
simulate('DUP3',[A,B,C|S]) ->
|
||||
[C,A,B,C|S];
|
||||
simulate('ADD',[A,B|S]) ->
|
||||
[add(A,B)|S];
|
||||
simulate('MSTORE',[Addr,X|S]) ->
|
||||
io:format("mem(~p) <- ~p\n",[Addr,X]),
|
||||
S;
|
||||
simulate('MLOAD',[Addr|S]) ->
|
||||
A = new_atom(),
|
||||
io:format("~p = mem(~p)\n",[A,Addr]),
|
||||
[A|S];
|
||||
simulate('SWAP1',[A,B|S]) ->
|
||||
[B,A|S];
|
||||
simulate('SWAP2',[A,B,C|S]) ->
|
||||
[C,B,A|S];
|
||||
simulate('SUB',[A,B|S]) ->
|
||||
[{A,'-',B}|S];
|
||||
simulate('POP',[_|S]) ->
|
||||
S.
|
||||
|
||||
add(0,X) ->
|
||||
X;
|
||||
add(X,0) ->
|
||||
X;
|
||||
add(X,{A,'-',X}) ->
|
||||
A;
|
||||
add(X,{A,'+',B}) ->
|
||||
{A,'+',add(X,B)};
|
||||
add(A,B) ->
|
||||
{A,'+',B}.
|
||||
|
||||
new_atom() ->
|
||||
catch ets:new(names,[set,public,named_table]),
|
||||
case ets:lookup(names,index) of
|
||||
[] -> I = 0;
|
||||
[{index,I}] -> ok
|
||||
end,
|
||||
ets:insert(names,{index,I+1}),
|
||||
list_to_atom([$a+I]).
|
||||
|
||||
show_heap(Bin) ->
|
||||
show_heap(0, Bin).
|
||||
|
||||
show_heap(Offs, Bin) ->
|
||||
Words = dump_words(Bin),
|
||||
Addrs = lists:seq(0, (length(Words) - 1) * 32, 32),
|
||||
lists:flatten([io_lib:format("~4b ~p\n", [Addr + Offs, Word]) || {Addr, Word} <- lists:zip(Addrs, Words)]).
|
||||
|
||||
show_heap_value(HeapValue) ->
|
||||
Maps = aeso_heap:heap_value_maps(HeapValue),
|
||||
Offs = aeso_heap:heap_value_offset(HeapValue),
|
||||
Ptr = aeso_heap:heap_value_pointer(HeapValue),
|
||||
Mem = aeso_heap:heap_value_heap(HeapValue),
|
||||
Words = dump_words(Mem),
|
||||
Addrs = lists:seq(Offs, Offs + (length(Words) - 1) * 32, 32),
|
||||
lists:flatten(
|
||||
io_lib:format(" Maps: ~p\n Ptr: ~p\n Heap: ~p",
|
||||
[Maps, Ptr, lists:zip(Addrs, Words)])).
|
||||
|
||||
%% Translate a blob of 256-bit words into readable form. Does a bit of guessing
|
||||
%% to recover strings. TODO: strings longer than 32 bytes
|
||||
dump_words(Bin) -> dump_words(Bin, []).
|
||||
|
||||
dump_words(<<N:256, W:32/binary, Rest/binary>>, Acc) when N < 32 ->
|
||||
NotN = (32 - N) * 8,
|
||||
case W of
|
||||
<<S:N/binary, 0:NotN>> ->
|
||||
Str = binary_to_list(S),
|
||||
case lists:member(0, Str) of
|
||||
true -> dump_words(<<W/binary, Rest/binary>>, [N | Acc]); %% Not a string
|
||||
false -> dump_words(Rest, [binary_to_list(S), N | Acc])
|
||||
end;
|
||||
_ -> dump_words(<<W/binary, Rest/binary>>, [N | Acc])
|
||||
end;
|
||||
dump_words(<<N:256/signed, Rest/binary>>, Acc) ->
|
||||
dump_words(Rest, [N | Acc]);
|
||||
dump_words(<<>>, Acc) -> lists:reverse(Acc);
|
||||
dump_words(Rest, Acc) -> lists:reverse([{error, Rest} | Acc]).
|
||||
|
||||
%% -- Chain API for test -----------------------------------------------------
|
||||
|
||||
aens_lookup(Name, Key, Type, _S) ->
|
||||
io:format("aens_lookup(~p, ~p, ~p)\n", [Name, Key, Type]),
|
||||
{ok, {some, <<0:32/unit:8>>}}.
|
||||
|
||||
spend(Recipient, Amount, S) ->
|
||||
io:format("+++ SPEND(~p, ~p)\n", [Recipient, Amount]),
|
||||
{ok, S}.
|
||||
|
||||
get_balance(_, _) -> 1000000.
|
||||
|
||||
call_contract(Contract, Gas, Value, CallData, CallStack, S) ->
|
||||
io:format("+++ CALL(~p, ~p, ~p, ~p, ~p)\n", [Contract, Gas, Value, CallData, CallStack]),
|
||||
{ok, <<42:256>>, S}.
|
||||
|
||||
get_store(_) -> #{}.
|
||||
set_store(_, _) -> ok.
|
||||
|
Loading…
x
Reference in New Issue
Block a user