Pattern guards for functions and switch statements #830
@ -56,37 +56,36 @@ encode_decode_test() ->
|
|||||||
0 = encode_decode(word, 0),
|
0 = encode_decode(word, 0),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
encode_decode_sophia_test() -> ok.
|
encode_decode_sophia_test() ->
|
||||||
%encode_decode_sophia_test() ->
|
Check = fun(Type, Str) -> case {encode_decode_sophia_string(Type, Str), Str} of
|
||||||
% Check = fun(Type, Str) -> case {encode_decode_sophia_string(Type, Str), Str} of
|
{X, X} -> ok;
|
||||||
% {X, X} -> ok;
|
Other -> Other
|
||||||
% Other -> Other
|
end end,
|
||||||
% end end,
|
ok = Check("int", "42"),
|
||||||
% ok = Check("int", "42"),
|
ok = Check("int", "- 42"),
|
||||||
% ok = Check("int", "- 42"),
|
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}"),
|
ok.
|
||||||
% ok.
|
|
||||||
%
|
to_sophia_value_neg_test() ->
|
||||||
%to_sophia_value_neg_test() ->
|
Code = [ "contract Foo =\n"
|
||||||
% Code = [ "contract Foo =\n"
|
" entrypoint x(y : int) : string = \"hello\"\n" ],
|
||||||
% " entrypoint x(y : int) : string = \"hello\"\n" ],
|
|
||||||
%
|
{error, [Err1]} = aeso_compiler:to_sophia_value(Code, "x", ok, encode(12)),
|
||||||
% {error, [Err1]} = aeso_compiler:to_sophia_value(Code, "x", ok, encode(12)),
|
?assertEqual("Data error:\nFailed to decode binary as type string\n", aeso_errors:pp(Err1)),
|
||||||
% ?assertEqual("Data error:\nFailed to decode binary as type string\n", aeso_errors:pp(Err1)),
|
{error, [Err2]} = aeso_compiler:to_sophia_value(Code, "x", ok, encode(12), [{backend, fate}]),
|
||||||
% {error, [Err2]} = aeso_compiler:to_sophia_value(Code, "x", ok, encode(12), [{backend, fate}]),
|
?assertEqual("Data error:\nFailed to decode binary as type string\n", aeso_errors:pp(Err2)),
|
||||||
% ?assertEqual("Data error:\nFailed to decode binary as type string\n", aeso_errors:pp(Err2)),
|
|
||||||
%
|
{error, [Err3]} = aeso_compiler:to_sophia_value(Code, "x", revert, encode(12)),
|
||||||
% {error, [Err3]} = aeso_compiler:to_sophia_value(Code, "x", revert, encode(12)),
|
?assertEqual("Data error:\nCould not interpret the revert message\n", aeso_errors:pp(Err3)),
|
||||||
% ?assertEqual("Data error:\nCould not interpret the revert message\n", aeso_errors:pp(Err3)),
|
{error, [Err4]} = aeso_compiler:to_sophia_value(Code, "x", revert, encode(12), [{backend, fate}]),
|
||||||
% {error, [Err4]} = aeso_compiler:to_sophia_value(Code, "x", revert, encode(12), [{backend, fate}]),
|
?assertEqual("Data error:\nCould not deserialize the revert message\n", aeso_errors:pp(Err4)),
|
||||||
% ?assertEqual("Data error:\nCould not deserialize the revert message\n", aeso_errors:pp(Err4)),
|
ok.
|
||||||
% ok.
|
|
||||||
|
|
||||||
encode_calldata_neg_test() ->
|
encode_calldata_neg_test() ->
|
||||||
Code = [ "contract Foo =\n"
|
Code = [ "contract Foo =\n"
|
||||||
@ -102,28 +101,27 @@ encode_calldata_neg_test() ->
|
|||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
decode_calldata_neg_test() -> ok.
|
decode_calldata_neg_test() ->
|
||||||
%decode_calldata_neg_test() ->
|
Code1 = [ "contract Foo =\n"
|
||||||
% Code1 = [ "contract Foo =\n"
|
" entrypoint x(y : int) : string = \"hello\"\n" ],
|
||||||
% " entrypoint x(y : int) : string = \"hello\"\n" ],
|
Code2 = [ "contract Foo =\n"
|
||||||
% Code2 = [ "contract Foo =\n"
|
" entrypoint x(y : string) : int = 42\n" ],
|
||||||
% " entrypoint x(y : string) : int = 42\n" ],
|
|
||||||
%
|
{ok, CallDataAEVM} = aeso_compiler:create_calldata(Code1, "x", ["42"]),
|
||||||
% {ok, CallDataAEVM} = aeso_compiler:create_calldata(Code1, "x", ["42"]),
|
{ok, CallDataFATE} = aeso_compiler:create_calldata(Code1, "x", ["42"], [{backend, fate}]),
|
||||||
% {ok, CallDataFATE} = aeso_compiler:create_calldata(Code1, "x", ["42"], [{backend, fate}]),
|
|
||||||
%
|
{error, [Err1]} = aeso_compiler:decode_calldata(Code2, "x", CallDataAEVM),
|
||||||
% {error, [Err1]} = aeso_compiler:decode_calldata(Code2, "x", CallDataAEVM),
|
?assertEqual("Data error:\nFailed to decode calldata as type {tuple,[string]}\n", aeso_errors:pp(Err1)),
|
||||||
% ?assertEqual("Data error:\nFailed to decode calldata as type {tuple,[string]}\n", aeso_errors:pp(Err1)),
|
{error, [Err2]} = aeso_compiler:decode_calldata(Code2, "x", <<1,2,3>>, [{backend, fate}]),
|
||||||
% {error, [Err2]} = aeso_compiler:decode_calldata(Code2, "x", <<1,2,3>>, [{backend, fate}]),
|
?assertEqual("Data error:\nFailed to decode calldata binary\n", aeso_errors:pp(Err2)),
|
||||||
% ?assertEqual("Data error:\nFailed to decode calldata binary\n", aeso_errors:pp(Err2)),
|
{error, [Err3]} = aeso_compiler:decode_calldata(Code2, "x", CallDataFATE, [{backend, fate}]),
|
||||||
% {error, [Err3]} = aeso_compiler:decode_calldata(Code2, "x", CallDataFATE, [{backend, fate}]),
|
?assertEqual("Data error:\nCannot translate FATE value \"*\"\n to Sophia type (string)\n", aeso_errors:pp(Err3)),
|
||||||
% ?assertEqual("Data error:\nCannot translate FATE value \"*\"\n to Sophia type (string)\n", aeso_errors:pp(Err3)),
|
|
||||||
%
|
{error, [Err4]} = aeso_compiler:decode_calldata(Code2, "y", CallDataAEVM),
|
||||||
% {error, [Err4]} = aeso_compiler:decode_calldata(Code2, "y", CallDataAEVM),
|
?assertEqual("Data error at line 1, col 1:\nFunction 'y' is missing in contract\n", aeso_errors:pp(Err4)),
|
||||||
% ?assertEqual("Data error at line 1, col 1:\nFunction 'y' is missing in contract\n", aeso_errors:pp(Err4)),
|
{error, [Err5]} = aeso_compiler:decode_calldata(Code2, "y", CallDataFATE, [{backend, fate}]),
|
||||||
% {error, [Err5]} = aeso_compiler:decode_calldata(Code2, "y", CallDataFATE, [{backend, fate}]),
|
?assertEqual("Data error at line 1, col 1:\nFunction 'y' is missing in contract\n", aeso_errors:pp(Err5)),
|
||||||
% ?assertEqual("Data error at line 1, col 1:\nFunction 'y' is missing in contract\n", aeso_errors:pp(Err5)),
|
ok.
|
||||||
% ok.
|
|
||||||
|
|
||||||
|
|
||||||
encode_decode_sophia_string(SophiaType, String) ->
|
encode_decode_sophia_string(SophiaType, String) ->
|
||||||
@ -150,43 +148,40 @@ encode_decode_sophia_string(SophiaType, String) ->
|
|||||||
{error, Err}
|
{error, Err}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
calldata_test() -> ok.
|
calldata_test() ->
|
||||||
%calldata_test() ->
|
[42, <<"foobar">>] = encode_decode_calldata("foo", ["int", "string"], ["42", "\"foobar\""]),
|
||||||
% [42, <<"foobar">>] = encode_decode_calldata("foo", ["int", "string"], ["42", "\"foobar\""]),
|
Map = #{ <<"a">> => 4 },
|
||||||
% Map = #{ <<"a">> => 4 },
|
[{variant, 1, [Map]}, {{<<"b">>, 5}, {variant, 0, []}}] =
|
||||||
% [{variant, 1, [Map]}, {{<<"b">>, 5}, {variant, 0, []}}] =
|
encode_decode_calldata("foo", ["variant", "r"], ["Blue({[\"a\"] = 4})", "{x = (\"b\", 5), y = Red}"]),
|
||||||
% encode_decode_calldata("foo", ["variant", "r"], ["Blue({[\"a\"] = 4})", "{x = (\"b\", 5), y = Red}"]),
|
[?DUMMY_HASH_WORD, 16#456] = encode_decode_calldata("foo", ["bytes(32)", "address"],
|
||||||
% [?DUMMY_HASH_WORD, 16#456] = encode_decode_calldata("foo", ["bytes(32)", "address"],
|
[?DUMMY_HASH_LIT, "ak_1111111111111111111111111111113AFEFpt5"]),
|
||||||
% [?DUMMY_HASH_LIT, "ak_1111111111111111111111111111113AFEFpt5"]),
|
[?DUMMY_HASH_WORD, ?DUMMY_HASH_WORD] =
|
||||||
% [?DUMMY_HASH_WORD, ?DUMMY_HASH_WORD] =
|
encode_decode_calldata("foo", ["bytes(32)", "hash"], [?DUMMY_HASH_LIT, ?DUMMY_HASH_LIT]),
|
||||||
% encode_decode_calldata("foo", ["bytes(32)", "hash"], [?DUMMY_HASH_LIT, ?DUMMY_HASH_LIT]),
|
|
||||||
%
|
|
||||||
% [119, {0, 0}] = encode_decode_calldata("foo", ["int", "signature"], ["119", [$# | lists:duplicate(128, $0)]]),
|
|
||||||
%
|
|
||||||
% [16#456] = encode_decode_calldata("foo", ["Remote"], ["ct_1111111111111111111111111111113AFEFpt5"]),
|
|
||||||
%
|
|
||||||
% ok.
|
|
||||||
|
|
||||||
calldata_init_test() -> ok.
|
[119, {0, 0}] = encode_decode_calldata("foo", ["int", "signature"], ["119", [$# | lists:duplicate(128, $0)]]),
|
||||||
%calldata_init_test() ->
|
|
||||||
% encode_decode_calldata("init", ["int"], ["42"], {tuple, [typerep, word]}),
|
|
||||||
%
|
|
||||||
% Code = parameterized_contract("foo", ["int"]),
|
|
||||||
% encode_decode_calldata_(Code, "init", [], {tuple, [typerep, {tuple, []}]}).
|
|
||||||
|
|
||||||
calldata_indent_test() -> ok.
|
[16#456] = encode_decode_calldata("foo", ["Remote"], ["ct_1111111111111111111111111111113AFEFpt5"]),
|
||||||
%calldata_indent_test() ->
|
|
||||||
% Test = fun(Extra) ->
|
ok.
|
||||||
% Code = parameterized_contract(Extra, "foo", ["int"]),
|
|
||||||
% encode_decode_calldata_(Code, "foo", ["42"], word)
|
calldata_init_test() ->
|
||||||
% end,
|
encode_decode_calldata("init", ["int"], ["42"], {tuple, [typerep, word]}),
|
||||||
% Test(" stateful entrypoint bla() = ()"),
|
|
||||||
% Test(" type x = int"),
|
Code = parameterized_contract("foo", ["int"]),
|
||||||
% Test(" stateful entrypoint bla(x : int) =\n"
|
encode_decode_calldata_(Code, "init", [], {tuple, [typerep, {tuple, []}]}).
|
||||||
% " x + 1"),
|
|
||||||
% Test(" stateful entrypoint bla(x : int) : int =\n"
|
calldata_indent_test() ->
|
||||||
% " x + 1"),
|
Test = fun(Extra) ->
|
||||||
% ok.
|
Code = parameterized_contract(Extra, "foo", ["int"]),
|
||||||
|
encode_decode_calldata_(Code, "foo", ["42"], word)
|
||||||
|
end,
|
||||||
|
Test(" stateful entrypoint bla() = ()"),
|
||||||
|
Test(" type x = int"),
|
||||||
|
Test(" stateful entrypoint bla(x : int) =\n"
|
||||||
|
" x + 1"),
|
||||||
|
Test(" stateful entrypoint bla(x : int) : int =\n"
|
||||||
|
" x + 1"),
|
||||||
|
ok.
|
||||||
|
|
||||||
parameterized_contract(FunName, Types) ->
|
parameterized_contract(FunName, Types) ->
|
||||||
parameterized_contract([], FunName, Types).
|
parameterized_contract([], FunName, Types).
|
||||||
@ -202,17 +197,16 @@ parameterized_contract(ExtraCode, FunName, Types) ->
|
|||||||
" 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" ]).
|
||||||
|
|
||||||
oracle_test() -> ok.
|
oracle_test() ->
|
||||||
%oracle_test() ->
|
Contract =
|
||||||
% Contract =
|
"contract OracleTest =\n"
|
||||||
% "contract OracleTest =\n"
|
" entrypoint question(o, q : oracle_query(list(string), option(int))) =\n"
|
||||||
% " entrypoint question(o, q : oracle_query(list(string), option(int))) =\n"
|
" Oracle.get_question(o, q)\n",
|
||||||
% " Oracle.get_question(o, q)\n",
|
{ok, _, {[word, word], {list, string}}, [16#123, 16#456]} =
|
||||||
% {ok, _, {[word, word], {list, string}}, [16#123, 16#456]} =
|
aeso_compiler:check_call(Contract, "question", ["ok_111111111111111111111111111111ZrdqRz9",
|
||||||
% aeso_compiler:check_call(Contract, "question", ["ok_111111111111111111111111111111ZrdqRz9",
|
"oq_1111111111111111111111111111113AFEFpt5"], [no_code]),
|
||||||
% "oq_1111111111111111111111111111113AFEFpt5"], [no_code]),
|
|
||||||
%
|
ok.
|
||||||
% ok.
|
|
||||||
|
|
||||||
permissive_literals_fail_test() ->
|
permissive_literals_fail_test() ->
|
||||||
Contract =
|
Contract =
|
||||||
|
@ -19,12 +19,18 @@ calldata_test_() ->
|
|||||||
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
[ {"Testing " ++ ContractName ++ " contract calling " ++ Fun,
|
||||||
fun() ->
|
fun() ->
|
||||||
ContractString = aeso_test_utils:read_contract(ContractName),
|
ContractString = aeso_test_utils:read_contract(ContractName),
|
||||||
|
AevmExprs =
|
||||||
|
case not lists:member(ContractName, not_yet_compilable(aevm)) of
|
||||||
|
true -> ast_exprs(ContractString, Fun, Args, [{backend, aevm}]);
|
||||||
|
false -> undefined
|
||||||
|
end,
|
||||||
FateExprs =
|
FateExprs =
|
||||||
case not lists:member(ContractName, not_yet_compilable(fate)) of
|
case not lists:member(ContractName, not_yet_compilable(fate)) of
|
||||||
true -> ast_exprs(ContractString, Fun, Args, [{backend, fate}]);
|
true -> ast_exprs(ContractString, Fun, Args, [{backend, fate}]);
|
||||||
false -> undefined
|
false -> undefined
|
||||||
end,
|
end,
|
||||||
ParsedExprs = parse_args(Fun, Args),
|
ParsedExprs = parse_args(Fun, Args),
|
||||||
|
[ ?assertEqual(ParsedExprs, AevmExprs) || AevmExprs /= undefined ],
|
||||||
[ ?assertEqual(ParsedExprs, FateExprs) || FateExprs /= undefined ],
|
[ ?assertEqual(ParsedExprs, FateExprs) || FateExprs /= undefined ],
|
||||||
ok
|
ok
|
||||||
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
||||||
@ -36,12 +42,18 @@ calldata_aci_test_() ->
|
|||||||
{ok, ContractACIBin} = aeso_aci:contract_interface(string, ContractString),
|
{ok, ContractACIBin} = aeso_aci:contract_interface(string, ContractString),
|
||||||
ContractACI = binary_to_list(ContractACIBin),
|
ContractACI = binary_to_list(ContractACIBin),
|
||||||
io:format("ACI:\n~s\n", [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 =
|
FateExprs =
|
||||||
case not lists:member(ContractName, not_yet_compilable(fate)) of
|
case not lists:member(ContractName, not_yet_compilable(fate)) of
|
||||||
true -> ast_exprs(ContractACI, Fun, Args, [{backend, fate}]);
|
true -> ast_exprs(ContractACI, Fun, Args, [{backend, fate}]);
|
||||||
false -> undefined
|
false -> undefined
|
||||||
end,
|
end,
|
||||||
ParsedExprs = parse_args(Fun, Args),
|
ParsedExprs = parse_args(Fun, Args),
|
||||||
|
[ ?assertEqual(ParsedExprs, AevmExprs) || AevmExprs /= undefined ],
|
||||||
[ ?assertEqual(ParsedExprs, FateExprs) || FateExprs /= undefined ],
|
[ ?assertEqual(ParsedExprs, FateExprs) || FateExprs /= undefined ],
|
||||||
ok
|
ok
|
||||||
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
end} || {ContractName, Fun, Args} <- compilable_contracts()].
|
||||||
|
@ -65,7 +65,7 @@ simple_compile_test_() ->
|
|||||||
check_errors(Expect, Errors)
|
check_errors(Expect, Errors)
|
||||||
end} ||
|
end} ||
|
||||||
{ContractName, ExpectedError} <- failing_code_gen_contracts(),
|
{ContractName, ExpectedError} <- failing_code_gen_contracts(),
|
||||||
Backend <- [fate] ] ++
|
Backend <- [aevm, fate] ] ++
|
||||||
[ {"Testing include with explicit files",
|
[ {"Testing include with explicit files",
|
||||||
fun() ->
|
fun() ->
|
||||||
FileSystem = maps:from_list(
|
FileSystem = maps:from_list(
|
||||||
@ -87,7 +87,7 @@ simple_compile_test_() ->
|
|||||||
Backend == fate -> 20 end,
|
Backend == fate -> 20 end,
|
||||||
?assertMatch({_, _, true}, {SizeDeadCode, SizeNoDeadCode, SizeDeadCode + Delta < SizeNoDeadCode}),
|
?assertMatch({_, _, true}, {SizeDeadCode, SizeNoDeadCode, SizeDeadCode + Delta < SizeNoDeadCode}),
|
||||||
ok
|
ok
|
||||||
end} || Backend <- [fate] ] ++
|
end} || Backend <- [aevm, fate] ] ++
|
||||||
[].
|
[].
|
||||||
|
|
||||||
%% Check if all modules in the standard library compile
|
%% Check if all modules in the standard library compile
|
||||||
|
Loading…
x
Reference in New Issue
Block a user