Merge pull request #261 from aeternity/fixes
Ban empty contracts, ban function blocks with mismatched declarations
This commit is contained in:
commit
dd8eea0d55
@ -564,6 +564,10 @@ init_env(_Options) -> global_env().
|
|||||||
|
|
||||||
-spec infer(aeso_syntax:ast(), list(option())) ->
|
-spec infer(aeso_syntax:ast(), list(option())) ->
|
||||||
aeso_syntax:ast() | {env(), aeso_syntax:ast()}.
|
aeso_syntax:ast() | {env(), aeso_syntax:ast()}.
|
||||||
|
infer([], Options) ->
|
||||||
|
create_type_errors(),
|
||||||
|
type_error({no_decls, proplists:get_value(src_file, Options, no_file)}),
|
||||||
|
destroy_and_report_type_errors(init_env(Options));
|
||||||
infer(Contracts, Options) ->
|
infer(Contracts, Options) ->
|
||||||
ets_init(), %% Init the ETS table state
|
ets_init(), %% Init the ETS table state
|
||||||
try
|
try
|
||||||
@ -626,7 +630,9 @@ infer_contract_top(Env, Kind, Defs0, _Options) ->
|
|||||||
%% a list of definitions.
|
%% a list of definitions.
|
||||||
-spec infer_contract(env(), main_contract | contract | namespace, [aeso_syntax:decl()]) -> {env(), [aeso_syntax:decl()]}.
|
-spec infer_contract(env(), main_contract | contract | namespace, [aeso_syntax:decl()]) -> {env(), [aeso_syntax:decl()]}.
|
||||||
infer_contract(Env0, What, Defs0) ->
|
infer_contract(Env0, What, Defs0) ->
|
||||||
|
create_type_errors(),
|
||||||
Defs = process_blocks(Defs0),
|
Defs = process_blocks(Defs0),
|
||||||
|
destroy_and_report_type_errors(Env0),
|
||||||
Env = Env0#env{ what = What },
|
Env = Env0#env{ what = What },
|
||||||
Kind = fun({type_def, _, _, _, _}) -> type;
|
Kind = fun({type_def, _, _, _, _}) -> type;
|
||||||
({letfun, _, _, _, _, _}) -> function;
|
({letfun, _, _, _, _, _}) -> function;
|
||||||
@ -679,12 +685,12 @@ process_block(Ann, [Decl | Decls]) ->
|
|||||||
case Decl of
|
case Decl of
|
||||||
{fun_decl, Ann1, Id = {id, _, Name}, Type} ->
|
{fun_decl, Ann1, Id = {id, _, Name}, Type} ->
|
||||||
{Clauses, Rest} = lists:splitwith(IsThis(Name), Decls),
|
{Clauses, Rest} = lists:splitwith(IsThis(Name), Decls),
|
||||||
[{fun_clauses, Ann1, Id, Type, Clauses} |
|
[type_error({mismatched_decl_in_funblock, Name, D1}) || D1 <- Rest],
|
||||||
process_block(Ann, Rest)];
|
[{fun_clauses, Ann1, Id, Type, Clauses}];
|
||||||
{letfun, Ann1, Id = {id, _, Name}, _, _, _} ->
|
{letfun, Ann1, Id = {id, _, Name}, _, _, _} ->
|
||||||
{Clauses, Rest} = lists:splitwith(IsThis(Name), [Decl | Decls]),
|
{Clauses, Rest} = lists:splitwith(IsThis(Name), [Decl | Decls]),
|
||||||
[{fun_clauses, Ann1, Id, {id, [{origin, system} | Ann1], "_"}, Clauses} |
|
[type_error({mismatched_decl_in_funblock, Name, D1}) || D1 <- Rest],
|
||||||
process_block(Ann, Rest)]
|
[{fun_clauses, Ann1, Id, {id, [{origin, system} | Ann1], "_"}, Clauses}]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec check_typedefs(env(), [aeso_syntax:decl()]) -> {env(), [aeso_syntax:decl()]}.
|
-spec check_typedefs(env(), [aeso_syntax:decl()]) -> {env(), [aeso_syntax:decl()]}.
|
||||||
@ -2266,6 +2272,12 @@ mk_t_err(Pos, Msg) ->
|
|||||||
mk_t_err(Pos, Msg, Ctxt) ->
|
mk_t_err(Pos, Msg, Ctxt) ->
|
||||||
aeso_errors:new(type_error, Pos, lists:flatten(Msg), lists:flatten(Ctxt)).
|
aeso_errors:new(type_error, Pos, lists:flatten(Msg), lists:flatten(Ctxt)).
|
||||||
|
|
||||||
|
mk_error({no_decls, File}) ->
|
||||||
|
Pos = aeso_errors:pos(File, 0, 0),
|
||||||
|
mk_t_err(Pos, "Empty contract\n");
|
||||||
|
mk_error({mismatched_decl_in_funblock, Name, Decl}) ->
|
||||||
|
Msg = io_lib:format("Mismatch in the function block. Expected implementation/type declaration of ~s function\n", [Name]),
|
||||||
|
mk_t_err(pos(Decl), Msg);
|
||||||
mk_error({higher_kinded_typevar, T}) ->
|
mk_error({higher_kinded_typevar, T}) ->
|
||||||
Msg = io_lib:format("Type ~s is a higher kinded type variable\n"
|
Msg = io_lib:format("Type ~s is a higher kinded type variable\n"
|
||||||
"(takes another type as an argument)\n", [pp(instantiate(T))]
|
"(takes another type as an argument)\n", [pp(instantiate(T))]
|
||||||
|
@ -39,9 +39,9 @@
|
|||||||
| {pragma, ann(), pragma()}
|
| {pragma, ann(), pragma()}
|
||||||
| {type_decl, ann(), id(), [tvar()]} % Only for error msgs
|
| {type_decl, ann(), id(), [tvar()]} % Only for error msgs
|
||||||
| {type_def, ann(), id(), [tvar()], typedef()}
|
| {type_def, ann(), id(), [tvar()], typedef()}
|
||||||
| {fun_decl, ann(), id(), type()}
|
| {fun_clauses, ann(), id(), type(), [letfun() | fundecl()]}
|
||||||
| {fun_clauses, ann(), id(), type(), [letbind()]}
|
|
||||||
| {block, ann(), [decl()]}
|
| {block, ann(), [decl()]}
|
||||||
|
| fundecl()
|
||||||
| letfun()
|
| letfun()
|
||||||
| letval(). % Only for error msgs
|
| letval(). % Only for error msgs
|
||||||
|
|
||||||
@ -50,8 +50,10 @@
|
|||||||
-type pragma() :: {compiler, '==' | '<' | '>' | '=<' | '>=', compiler_version()}.
|
-type pragma() :: {compiler, '==' | '<' | '>' | '=<' | '>=', compiler_version()}.
|
||||||
|
|
||||||
|
|
||||||
-type letval() :: {letval, ann(), pat(), expr()}.
|
-type letval() :: {letval, ann(), pat(), expr()}.
|
||||||
-type letfun() :: {letfun, ann(), id(), [pat()], type(), expr()}.
|
-type letfun() :: {letfun, ann(), id(), [pat()], type(), expr()}.
|
||||||
|
-type fundecl() :: {fun_decl, ann(), id(), type()}.
|
||||||
|
|
||||||
-type letbind()
|
-type letbind()
|
||||||
:: letfun()
|
:: letfun()
|
||||||
| letval().
|
| letval().
|
||||||
|
@ -665,6 +665,16 @@ failing_contracts() ->
|
|||||||
"Empty record/map update\n"
|
"Empty record/map update\n"
|
||||||
" r {}">>
|
" r {}">>
|
||||||
])
|
])
|
||||||
|
, ?TYPE_ERROR(bad_function_block,
|
||||||
|
[<<?Pos(4, 5)
|
||||||
|
"Mismatch in the function block. Expected implementation/type declaration of g function">>,
|
||||||
|
<<?Pos(5, 5)
|
||||||
|
"Mismatch in the function block. Expected implementation/type declaration of g function">>
|
||||||
|
])
|
||||||
|
, ?TYPE_ERROR(just_an_empty_file,
|
||||||
|
[<<?Pos(0, 0)
|
||||||
|
"Empty contract">>
|
||||||
|
])
|
||||||
, ?TYPE_ERROR(bad_number_of_args,
|
, ?TYPE_ERROR(bad_number_of_args,
|
||||||
[<<?Pos(3, 39)
|
[<<?Pos(3, 39)
|
||||||
"Cannot unify () => unit\n"
|
"Cannot unify () => unit\n"
|
||||||
|
5
test/contracts/bad_function_block.aes
Normal file
5
test/contracts/bad_function_block.aes
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
contract C =
|
||||||
|
function
|
||||||
|
g(1) = 2
|
||||||
|
f(2) = 3
|
||||||
|
h(1) = 123
|
0
test/contracts/just_an_empty_file.aes
Normal file
0
test/contracts/just_an_empty_file.aes
Normal file
Loading…
x
Reference in New Issue
Block a user