diff --git a/src/aeso_aci.erl b/src/aeso_aci.erl index ae696a4..ed8a44b 100644 --- a/src/aeso_aci.erl +++ b/src/aeso_aci.erl @@ -83,7 +83,7 @@ from_typed_ast(Type, TypedAst) -> string -> do_render_aci_json(JArray) end. -encode_contract(Contract = {Head, _, {con, _, Name}, _}) when ?IS_CONTRACT_HEAD(Head) -> +encode_contract(Contract = {Head, _, {con, _, Name}, _, _}) when ?IS_CONTRACT_HEAD(Head) -> C0 = #{name => encode_name(Name)}, Tdefs0 = [ encode_typedef(T) || T <- sort_decls(contract_types(Contract)) ], @@ -341,10 +341,12 @@ stateful(false) -> "". %% #contract{Ann, Con, [Declarations]}. -contract_funcs({C, _, _, Decls}) when ?IS_CONTRACT_HEAD(C); C == namespace -> +contract_funcs({C, _, _, _, Decls}) when ?IS_CONTRACT_HEAD(C) -> [ D || D <- Decls, is_fun(D)]. -contract_types({C, _, _, Decls}) when ?IS_CONTRACT_HEAD(C); C == namespace -> +contract_types({namespace, _, _, Decls}) -> + [ D || D <- Decls, is_type(D) ]; +contract_types({C, _, _, _, Decls}) when ?IS_CONTRACT_HEAD(C) -> [ D || D <- Decls, is_type(D) ]. is_fun({letfun, _, _, _, _, _}) -> true; diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 25802e0..d0328c9 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -326,7 +326,7 @@ get_option(Opt, Env, Default) -> %% -- Compilation ------------------------------------------------------------ -spec to_fcode(env(), aeso_syntax:ast()) -> {env(), fcode()}. -to_fcode(Env, [{Contract, Attrs, Con = {con, _, Name}, Decls}|Rest]) +to_fcode(Env, [{Contract, Attrs, Con = {con, _, Name}, _Impls, Decls}|Rest]) when ?IS_CONTRACT_HEAD(Contract) -> case Contract =:= contract_interface of false -> diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index 5580a7b..2982fd6 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -238,8 +238,8 @@ insert_init_function(Code, Options) -> last_contract_indent(Decls) -> case lists:last(Decls) of - {_, _, _, [Decl | _]} -> aeso_syntax:get_ann(col, Decl, 1) - 1; - _ -> 0 + {_, _, _, _, [Decl | _]} -> aeso_syntax:get_ann(col, Decl, 1) - 1; + _ -> 0 end. -spec to_sophia_value(string(), string(), ok | error | revert, binary()) -> @@ -338,7 +338,7 @@ decode_calldata(ContractString, FunName, Calldata, Options0) -> end. -dialyzer({nowarn_function, get_decode_type/2}). -get_decode_type(FunName, [{Contract, Ann, _, Defs}]) when ?IS_CONTRACT_HEAD(Contract) -> +get_decode_type(FunName, [{Contract, Ann, _, _, Defs}]) when ?IS_CONTRACT_HEAD(Contract) -> GetType = fun({letfun, _, {id, _, Name}, Args, Ret, _}) when Name == FunName -> [{Args, Ret}]; ({fun_decl, _, {id, _, Name}, {fun_t, _, _, Args, Ret}}) when Name == FunName -> [{Args, Ret}]; (_) -> [] end, diff --git a/test/aeso_calldata_tests.erl b/test/aeso_calldata_tests.erl index c897180..2fb7a36 100644 --- a/test/aeso_calldata_tests.erl +++ b/test/aeso_calldata_tests.erl @@ -39,7 +39,7 @@ calldata_aci_test_() -> end} || {ContractName, Fun, Args} <- compilable_contracts()]. parse_args(Fun, Args) -> - [{contract_main, _, _, [{letfun, _, _, _, _, [{guarded, _, [], {app, _, _, AST}}]}]}] = + [{contract_main, _, _, _, [{letfun, _, _, _, _, [{guarded, _, [], {app, _, _, AST}}]}]}] = aeso_parser:string("main contract Temp = function foo() = " ++ Fun ++ "(" ++ string:join(Args, ", ") ++ ")"), strip_ann(AST). diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index fd1c9a1..189d6ff 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -202,6 +202,8 @@ compilable_contracts() -> "assign_patterns", "patterns_guards", "pipe_operator", + "contract_polymorphism", + "contract_interface_polymorphism", "test" % Custom general-purpose test file. Keep it last on the list. ]. @@ -825,6 +827,26 @@ failing_contracts() -> <> ]) + , ?TYPE_ERROR(contract_interface_polymorphism_recursive, + [<> + ]) + , ?TYPE_ERROR(contract_interface_polymorphism_same_decl_multi_interface, + [<> + ]) + , ?TYPE_ERROR(contract_polymorphism_missing_implementation, + [<> + ]) + , ?TYPE_ERROR(contract_polymorphism_same_decl_multi_interface, + [<> + ]) + , ?TYPE_ERROR(contract_polymorphism_undefined_interface, + [<> + ]) ]. -define(Path(File), "code_errors/" ??File). diff --git a/test/aeso_parser_tests.erl b/test/aeso_parser_tests.erl index 6c577c8..e3b7598 100644 --- a/test/aeso_parser_tests.erl +++ b/test/aeso_parser_tests.erl @@ -15,7 +15,7 @@ simple_contracts_test_() -> Text = "main contract Identity =\n" " function id(x) = x\n", ?assertMatch( - [{contract_main, _, {con, _, "Identity"}, + [{contract_main, _, {con, _, "Identity"}, _, [{letfun, _, {id, _, "id"}, [{id, _, "x"}], {id, _, "_"}, [{guarded, _, [], {id, _, "x"}}]}]}], parse_string(Text)), ok diff --git a/test/contracts/contract_interface_polymorphism.aes b/test/contracts/contract_interface_polymorphism.aes new file mode 100644 index 0000000..6eb9ab7 --- /dev/null +++ b/test/contracts/contract_interface_polymorphism.aes @@ -0,0 +1,9 @@ +contract interface II = + entrypoint f : () => int + +contract interface I : II = + entrypoint g : () => int + +contract C : I = + entrypoint f() = 1 + entrypoint g() = 2 diff --git a/test/contracts/contract_interface_polymorphism_recursive.aes b/test/contracts/contract_interface_polymorphism_recursive.aes new file mode 100644 index 0000000..8e373d7 --- /dev/null +++ b/test/contracts/contract_interface_polymorphism_recursive.aes @@ -0,0 +1,13 @@ +contract interface X : Z = + entrypoint x : () => int + +contract interface Y : X = + entrypoint y : () => int + +contract interface Z : Y = + entrypoint z : () => int + +contract C : Z = + entrypoint x() = 1 + entrypoint y() = 1 + entrypoint z() = 1 diff --git a/test/contracts/contract_interface_polymorphism_same_decl_multi_interface.aes b/test/contracts/contract_interface_polymorphism_same_decl_multi_interface.aes new file mode 100644 index 0000000..9ad40a2 --- /dev/null +++ b/test/contracts/contract_interface_polymorphism_same_decl_multi_interface.aes @@ -0,0 +1,8 @@ +contract interface I = + entrypoint f : () => int + +contract interface II : I = + entrypoint f : () => int + +contract C : II = + entrypoint f() = 1 diff --git a/test/contracts/contract_polymorphism.aes b/test/contracts/contract_polymorphism.aes new file mode 100644 index 0000000..2982cd1 --- /dev/null +++ b/test/contracts/contract_polymorphism.aes @@ -0,0 +1,5 @@ +contract interface Strokable = + entrypoint stroke : () => string + +contract Cat : Strokable = + entrypoint stroke() = "Cat stroke" diff --git a/test/contracts/contract_polymorphism_missing_implementation.aes b/test/contracts/contract_polymorphism_missing_implementation.aes new file mode 100644 index 0000000..4e6639f --- /dev/null +++ b/test/contracts/contract_polymorphism_missing_implementation.aes @@ -0,0 +1,8 @@ +contract interface I1 = + entrypoint f : () => int + +contract interface I2 : I1 = + entrypoint g : () => int + +contract C : I2 = + entrypoint g() = 1 diff --git a/test/contracts/contract_polymorphism_same_decl_multi_interface.aes b/test/contracts/contract_polymorphism_same_decl_multi_interface.aes new file mode 100644 index 0000000..6df635d --- /dev/null +++ b/test/contracts/contract_polymorphism_same_decl_multi_interface.aes @@ -0,0 +1,8 @@ +contract interface I = + entrypoint f : () => int + +contract interface J = + entrypoint f : () => int + +contract C : I, J = + entrypoint f() = 1 diff --git a/test/contracts/contract_polymorphism_undefined_interface.aes b/test/contracts/contract_polymorphism_undefined_interface.aes new file mode 100644 index 0000000..0fc47ac --- /dev/null +++ b/test/contracts/contract_polymorphism_undefined_interface.aes @@ -0,0 +1,5 @@ +contract interface I : H = + entrypoint f : () => unit + +contract C = + entrypoint g() = ()