Add failing test for stateful pattern guards
This commit is contained in:
parent
15ddec00bd
commit
36fa3d1d2b
@ -132,6 +132,7 @@
|
|||||||
, namespace = [] :: qname()
|
, namespace = [] :: qname()
|
||||||
, used_namespaces = [] :: used_namespaces()
|
, used_namespaces = [] :: used_namespaces()
|
||||||
, in_pattern = false :: boolean()
|
, in_pattern = false :: boolean()
|
||||||
|
, in_guard = false :: boolean()
|
||||||
, stateful = false :: boolean()
|
, stateful = false :: boolean()
|
||||||
, current_function = none :: none | aeso_syntax:id()
|
, current_function = none :: none | aeso_syntax:id()
|
||||||
, what = top :: top | namespace | contract | contract_interface
|
, what = top :: top | namespace | contract | contract_interface
|
||||||
@ -1396,7 +1397,7 @@ infer_letfun1(Env0, {letfun, Attrib, Fun = {id, NameAttrib, Name}, Args, What, G
|
|||||||
Env = Env0#env{ stateful = aeso_syntax:get_ann(stateful, Attrib, false),
|
Env = Env0#env{ stateful = aeso_syntax:get_ann(stateful, Attrib, false),
|
||||||
current_function = Fun },
|
current_function = Fun },
|
||||||
{NewEnv, {typed, _, {tuple, _, TypedArgs}, {tuple_t, _, ArgTypes}}} = infer_pattern(Env, {tuple, [{origin, system} | NameAttrib], Args}),
|
{NewEnv, {typed, _, {tuple, _, TypedArgs}, {tuple_t, _, ArgTypes}}} = infer_pattern(Env, {tuple, [{origin, system} | NameAttrib], Args}),
|
||||||
NewGuard = check_expr(NewEnv#env{ stateful = false }, Guard, {id, Attrib, "bool"}),
|
NewGuard = check_expr(NewEnv#env{ in_guard = true }, Guard, {id, Attrib, "bool"}),
|
||||||
ExpectedType = check_type(Env, arg_type(NameAttrib, What)),
|
ExpectedType = check_type(Env, arg_type(NameAttrib, What)),
|
||||||
NewBody={typed, _, _, ResultType} = check_expr(NewEnv, Body, ExpectedType),
|
NewBody={typed, _, _, ResultType} = check_expr(NewEnv, Body, ExpectedType),
|
||||||
NamedArgs = [],
|
NamedArgs = [],
|
||||||
@ -1465,6 +1466,12 @@ lookup_name(Env, As, Id, Options) ->
|
|||||||
{set_qname(QId, Id), Ty1}
|
{set_qname(QId, Id), Ty1}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
check_stateful(#env{ in_guard = true }, Id, Type = {type_sig, _, _, _, _, _}) ->
|
||||||
|
case aeso_syntax:get_ann(stateful, Type, false) of
|
||||||
|
false -> ok;
|
||||||
|
true ->
|
||||||
|
type_error({stateful_not_allowed_in_guards, Id})
|
||||||
|
end;
|
||||||
check_stateful(#env{ stateful = false, current_function = Fun }, Id, Type = {type_sig, _, _, _, _, _}) ->
|
check_stateful(#env{ stateful = false, current_function = Fun }, Id, Type = {type_sig, _, _, _, _, _}) ->
|
||||||
case aeso_syntax:get_ann(stateful, Type, false) of
|
case aeso_syntax:get_ann(stateful, Type, false) of
|
||||||
false -> ok;
|
false -> ok;
|
||||||
@ -1913,7 +1920,7 @@ infer_case(Env, Attrs, Pattern, Guard, ExprType, Branch, SwitchType) ->
|
|||||||
none ->
|
none ->
|
||||||
{'case', Attrs, NewPattern, NewBranch};
|
{'case', Attrs, NewPattern, NewBranch};
|
||||||
_ ->
|
_ ->
|
||||||
NewGuard = check_expr(NewEnv#env{ stateful = false }, Guard, {id, Attrs, "bool"}),
|
NewGuard = check_expr(NewEnv#env{ in_guard = true }, Guard, {id, Attrs, "bool"}),
|
||||||
{'case', Attrs, NewPattern, NewGuard, NewBranch}
|
{'case', Attrs, NewPattern, NewGuard, NewBranch}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -3008,6 +3015,10 @@ mk_error({stateful_not_allowed, Id, Fun}) ->
|
|||||||
Msg = io_lib:format("Cannot reference stateful function ~s (at ~s)\nin the definition of non-stateful function ~s.\n",
|
Msg = io_lib:format("Cannot reference stateful function ~s (at ~s)\nin the definition of non-stateful function ~s.\n",
|
||||||
[pp(Id), pp_loc(Id), pp(Fun)]),
|
[pp(Id), pp_loc(Id), pp(Fun)]),
|
||||||
mk_t_err(pos(Id), Msg);
|
mk_t_err(pos(Id), Msg);
|
||||||
|
mk_error({stateful_not_allowed_in_guards, Id}) ->
|
||||||
|
Msg = io_lib:format("Cannot reference stateful function ~s (at ~s) in a pattern guard.\n",
|
||||||
|
[pp(Id), pp_loc(Id)]),
|
||||||
|
mk_t_err(pos(Id), Msg);
|
||||||
mk_error({value_arg_not_allowed, Value, Fun}) ->
|
mk_error({value_arg_not_allowed, Value, Fun}) ->
|
||||||
Msg = io_lib:format("Cannot pass non-zero value argument ~s (at ~s)\nin the definition of non-stateful function ~s.\n",
|
Msg = io_lib:format("Cannot pass non-zero value argument ~s (at ~s)\nin the definition of non-stateful function ~s.\n",
|
||||||
[pp_expr("", Value), pp_loc(Value), pp(Fun)]),
|
[pp_expr("", Value), pp_loc(Value), pp(Fun)]),
|
||||||
|
@ -809,6 +809,10 @@ failing_contracts() ->
|
|||||||
[<<?Pos(8,23)
|
[<<?Pos(8,23)
|
||||||
"Unbound variable g at line 8, column 23">>
|
"Unbound variable g at line 8, column 23">>
|
||||||
])
|
])
|
||||||
|
, ?TYPE_ERROR(stateful_pattern_guard,
|
||||||
|
[<<?Pos(10,12)
|
||||||
|
"Cannot reference stateful function g (at line 10, column 12) in a pattern guard.">>
|
||||||
|
])
|
||||||
].
|
].
|
||||||
|
|
||||||
-define(Path(File), "code_errors/" ??File).
|
-define(Path(File), "code_errors/" ??File).
|
||||||
|
12
test/contracts/stateful_pattern_guard.aes
Normal file
12
test/contracts/stateful_pattern_guard.aes
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
include "List.aes"
|
||||||
|
|
||||||
|
contract C =
|
||||||
|
type state = int
|
||||||
|
|
||||||
|
entrypoint init() = f(4)
|
||||||
|
|
||||||
|
function
|
||||||
|
f(x) | x > 0 = 1
|
||||||
|
f(x) | g(x) = 2
|
||||||
|
|
||||||
|
stateful function g(x) = x < 0
|
Loading…
x
Reference in New Issue
Block a user