diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 482bd16..5a07a9f 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -767,7 +767,9 @@ check_type(Env, Type = {fun_t, Ann, NamedArgs, Args, Ret}, Arity) -> {fun_t, Ann, NamedArgs1, Args1, Ret1}; check_type(_Env, Type = {uvar, _, _}, Arity) -> ensure_base_type(Type, Arity), - Type. + Type; +check_type(_Env, {args_t, Ann, Ts}, _) -> + type_error({new_tuple_syntax, Ann, Ts}). ensure_base_type(Type, Arity) -> [ type_error({wrong_type_arguments, Type, Arity, 0}) || Arity /= 0 ], @@ -2222,6 +2224,9 @@ pp_error({contract_has_no_entrypoints, Con}) -> "'function'.\n", [pp_expr("", Con), pp_loc(Con)]); pp_error({unbound_type, Type}) -> io_lib:format("Unbound type ~s (at ~s).\n", [pp_type("", Type), pp_loc(Type)]); +pp_error({new_tuple_syntax, Ann, Ts}) -> + io_lib:format("Invalid type\n~s (at ~s)\nThe syntax of tuple types changed in Sophia version 4.0. Did you mean\n~s\n", + [pp_type(" ", {args_t, Ann, Ts}), pp_loc(Ann), pp_type(" ", {tuple_t, Ann, Ts})]); pp_error(Err) -> io_lib:format("Unknown error: ~p\n", [Err]). diff --git a/src/aeso_parser.erl b/src/aeso_parser.erl index b3d184f..38e6d64 100644 --- a/src/aeso_parser.erl +++ b/src/aeso_parser.erl @@ -150,7 +150,7 @@ type() -> ?LAZY_P(type100()). type100() -> type200(). type200() -> - ?RULE(many({fun_domain(), keyword('=>')}), type300(), fun_t(_1, _2)). + ?RULE(many({type300(), keyword('=>')}), type300(), fun_t(_1, _2)). type300() -> ?RULE(sep1(type400(), tok('*')), tuple_t(get_ann(lists:nth(1, _1)), _1)). @@ -169,16 +169,15 @@ type400() -> typeAtom() -> ?LAZY_P(choice( [ parens(type()) + , args_t() , id(), token(con), token(qcon), token(qid), tvar() ])). -fun_domain() -> ?LAZY_P(choice( - [ ?RULE(tok('('), tok(')'), []) - %% Note avoidance of ambiguity: `(int)` can be treated as: - %% - literally `int` - %% - list of arguments with just one element – int. This approach is dropped. - , ?RULE(tok('('), type(), tok(','), sep1(type(), tok(',')), tok(')'), [_2|_4]) - , ?RULE(type300(), [_1]) +args_t() -> + ?LAZY_P(choice( + [ ?RULE(tok('('), tok(')'), {args_t, get_ann(_1), []}) + %% Singleton case handled separately + , ?RULE(tok('('), type(), tok(','), sep1(type(), tok(',')), tok(')'), {args_t, get_ann(_1), [_2|_4]}) ])). %% -- Statements ------------------------------------------------------------- @@ -501,7 +500,8 @@ tuple_t(_Ann, [Type]) -> Type; %% Not a tuple tuple_t(Ann, Types) -> {tuple_t, Ann, Types}. fun_t(Domains, Type) -> - lists:foldr(fun({Dom, Ann}, T) -> {fun_t, Ann, [], Dom, T} end, + lists:foldr(fun({{args_t, _, Dom}, Ann}, T) -> {fun_t, Ann, [], Dom, T}; + ({Dom, Ann}, T) -> {fun_t, Ann, [], [Dom], T} end, Type, Domains). tuple_e(_Ann, [Expr]) -> Expr; %% Not a tuple diff --git a/src/aeso_pretty.erl b/src/aeso_pretty.erl index e368354..dc36374 100644 --- a/src/aeso_pretty.erl +++ b/src/aeso_pretty.erl @@ -243,6 +243,8 @@ type({app_t, _, Type, Args}) -> beside(type(Type), args_type(Args)); type({tuple_t, _, Args}) -> tuple_type(Args); +type({args_t, _, Args}) -> + args_type(Args); type({bytes_t, _, any}) -> text("bytes(_)"); type({bytes_t, _, Len}) -> text(lists:concat(["bytes(", Len, ")"]));