From f2951d5bd7f53f1650f80eac3495bcfd97587058 Mon Sep 17 00:00:00 2001 From: Ulf Norell Date: Fri, 10 May 2019 12:36:08 +0200 Subject: [PATCH] Remove let rec from Sophia --- src/aeso_ast_infer_types.erl | 9 +++------ src/aeso_ast_to_icode.erl | 7 ------- src/aeso_parser.erl | 6 ++---- src/aeso_pretty.erl | 8 ++------ src/aeso_scan.erl | 4 ++-- src/aeso_syntax.erl | 3 +-- src/aeso_syntax_utils.erl | 6 ------ test/aeso_scan_tests.erl | 2 +- test/contracts/all_syntax.aes | 5 ----- 9 files changed, 11 insertions(+), 39 deletions(-) diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index c88349b..f4eaf63 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -798,7 +798,7 @@ check_sccs(Env = #env{}, Funs, [{acyclic, X} | SCCs], Acc) -> end; check_sccs(Env = #env{}, Funs, [{cyclic, Xs} | SCCs], Acc) -> Defs = [ maps:get(X, Funs) || X <- Xs ], - {TypeSigs, {letrec, _, Defs1}} = infer_letrec(Env, {letrec, [], Defs}), + {TypeSigs, Defs1} = infer_letrec(Env, Defs), Env1 = bind_funs(TypeSigs, Env), check_sccs(Env1, Funs, SCCs, Defs1 ++ Acc). @@ -840,7 +840,7 @@ check_special_funs(_, _) -> ok. typesig_to_fun_t({type_sig, Ann, Named, Args, Res}) -> {fun_t, Ann, Named, Args, Res}. -infer_letrec(Env, {letrec, Attrs, Defs}) -> +infer_letrec(Env, Defs) -> create_constraints(), Funs = [{Name, fresh_uvar(A)} || {letfun, _, {id, A, Name}, _, _, _} <- Defs], @@ -860,7 +860,7 @@ infer_letrec(Env, {letrec, Attrs, Defs}) -> TypeSigs = instantiate([Sig || {Sig, _} <- Inferred]), NewDefs = instantiate([D || {_, D} <- Inferred]), [print_typesig(S) || S <- TypeSigs], - {TypeSigs, {letrec, Attrs, NewDefs}}. + {TypeSigs, NewDefs}. infer_letfun(Env, {letfun, Attrib, {id, NameAttrib, Name}, Args, What, Body}) -> ArgTypes = [{ArgName, check_type(Env, arg_type(T))} || {arg, _, ArgName, T} <- Args], @@ -1138,9 +1138,6 @@ infer_block(Env, Attrs, [Def={letfun, Ann, _, _, _, _}|Rest], BlockType) -> FunT = freshen_type(typesig_to_fun_t(TypeSig)), NewE = bind_var({id, Ann, Name}, FunT, Env), [LetFun|infer_block(NewE, Attrs, Rest, BlockType)]; -infer_block(Env, Attrs, [Def={letrec, _, _}|Rest], BlockType) -> - NewDef = infer_letrec(Env, Def), - [NewDef|infer_block(Env, Attrs, Rest, BlockType)]; infer_block(Env, _, [{letval, Attrs, Pattern, Type, E}|Rest], BlockType) -> NewE = {typed, _, _, PatType} = infer_expr(Env, {typed, Attrs, E, arg_type(Type)}), {'case', _, NewPattern, {typed, _, {block, _, NewRest}, _}} = diff --git a/src/aeso_ast_to_icode.erl b/src/aeso_ast_to_icode.erl index ca71d04..b1bddc2 100644 --- a/src/aeso_ast_to_icode.erl +++ b/src/aeso_ast_to_icode.erl @@ -102,13 +102,6 @@ contract_to_icode([{letfun, Attrib, Name, Args, _What, Body={typed,_,_,T}}|Rest] QName = aeso_icode:qualify(Name, Icode), NewIcode = ast_fun_to_icode(ast_id(QName), FunAttrs, FunArgs, FunBody, TypeRep, Icode), contract_to_icode(Rest, NewIcode); -contract_to_icode([{letrec,_,Defs}|Rest], Icode) -> - %% OBS! This code ignores the letrec structure of the source, - %% because the back end treats ALL declarations as recursive! We - %% need to decide whether to (a) modify the back end to respect - %% the letrec structure, or (b) (preferably) modify the front end - %% just to parse a list of (mutually recursive) definitions. - contract_to_icode(Defs++Rest, Icode); contract_to_icode([], Icode) -> Icode; contract_to_icode([{fun_decl, _, _, _} | Code], Icode) -> contract_to_icode(Code, Icode); diff --git a/src/aeso_parser.erl b/src/aeso_parser.erl index ba9e8b9..f96505d 100644 --- a/src/aeso_parser.erl +++ b/src/aeso_parser.erl @@ -87,7 +87,7 @@ constructors() -> sep1(constructor(), tok('|')). constructor() -> %% TODO: format for Con() vs Con - choice(?RULE(con(), {constr_t, get_ann(_1), _1, []}), + choice(?RULE(con(), {constr_t, get_ann(_1), _1, []}), ?RULE(con(), con_args(), {constr_t, get_ann(_1), _1, _2})). con_args() -> paren_list(con_arg()). @@ -99,9 +99,7 @@ con_arg() -> choice(type(), ?RULE(keyword(indexed), type(), set_ann(indexed, %% -- Let declarations ------------------------------------------------------- letdecl() -> - choice( - ?RULE(keyword('let'), letdef(), set_pos(get_pos(_1), _2)), - ?RULE(keyword('let'), tok(rec), sep1(letdef(), tok('and')), {letrec, _1, _3})). + ?RULE(keyword('let'), letdef(), set_pos(get_pos(_1), _2)). letdef() -> choice(valdef(), fundef()). diff --git a/src/aeso_pretty.erl b/src/aeso_pretty.erl index 3177e60..094138d 100644 --- a/src/aeso_pretty.erl +++ b/src/aeso_pretty.erl @@ -160,8 +160,7 @@ decl(D = {letfun, Attrs, _, _, _, _}) -> text(atom_to_list(Mod)); (_) -> empty() end, hsep(lists:map(Mod, Attrs) ++ [letdecl("function", D)]); -decl(D = {letval, _, _, _, _}) -> letdecl("let", D); -decl(D = {letrec, _, _}) -> letdecl("let", D). +decl(D = {letval, _, _, _, _}) -> letdecl("let", D). -spec expr(aeso_syntax:expr(), options()) -> doc(). expr(E, Options) -> @@ -184,9 +183,7 @@ name({typed, _, Name, _}) -> name(Name). letdecl(Let, {letval, _, F, T, E}) -> block_expr(0, hsep([text(Let), typed(name(F), T), text("=")]), E); letdecl(Let, {letfun, _, F, Args, T, E}) -> - block_expr(0, hsep([text(Let), typed(beside(name(F), args(Args)), T), text("=")]), E); -letdecl(Let, {letrec, _, [D | Ds]}) -> - hsep(text(Let), above([ letdecl("rec", D) | [ letdecl("and", D1) || D1 <- Ds ] ])). + block_expr(0, hsep([text(Let), typed(beside(name(F), args(Args)), T), text("=")]), E). -spec args([aeso_syntax:arg()]) -> doc(). args(Args) -> @@ -435,7 +432,6 @@ statements(Stmts) -> statement(S = {letval, _, _, _, _}) -> letdecl("let", S); statement(S = {letfun, _, _, _, _, _}) -> letdecl("let", S); -statement(S = {letrec, _, _}) -> letdecl("let", S); statement(E) -> expr(E). get_elifs(Expr) -> get_elifs(Expr, []). diff --git a/src/aeso_scan.erl b/src/aeso_scan.erl index e377438..e8dc7e1 100644 --- a/src/aeso_scan.erl +++ b/src/aeso_scan.erl @@ -36,8 +36,8 @@ lexer() -> , {"\\*/", pop(skip())} , {"[^/*]+|[/*]", skip()} ], - Keywords = ["contract", "include", "let", "rec", "switch", "type", "record", "datatype", "if", "elif", "else", "function", - "stateful", "true", "false", "and", "mod", "public", "private", "indexed", "internal", "namespace"], + Keywords = ["contract", "include", "let", "switch", "type", "record", "datatype", "if", "elif", "else", "function", + "stateful", "true", "false", "mod", "public", "private", "indexed", "internal", "namespace"], KW = string:join(Keywords, "|"), Rules = diff --git a/src/aeso_syntax.erl b/src/aeso_syntax.erl index 63f192d..b3cc3ce 100644 --- a/src/aeso_syntax.erl +++ b/src/aeso_syntax.erl @@ -43,8 +43,7 @@ -type letbind() :: {letval, ann(), id(), type(), expr()} - | {letfun, ann(), id(), [arg()], type(), expr()} - | {letrec, ann(), [letbind()]}. + | {letfun, ann(), id(), [arg()], type(), expr()}. -type arg() :: {arg, ann(), id(), type()}. diff --git a/src/aeso_syntax_utils.erl b/src/aeso_syntax_utils.erl index a8aceea..8a7f374 100644 --- a/src/aeso_syntax_utils.erl +++ b/src/aeso_syntax_utils.erl @@ -39,11 +39,6 @@ fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) -> BindExpr = fun(P) -> fold(Alg, Fun, bind_expr, P) end, BindType = fun(T) -> fold(Alg, Fun, bind_type, T) end, Top = Fun(K, X), - Bound = fun LB ({letval, _, Y, _, _}) -> BindExpr(Y); - LB ({letfun, _, F, _, _, _}) -> BindExpr(F); - LB ({letrec, _, Ds}) -> Sum(lists:map(LB, Ds)); - LB (_) -> Zero - end, Rec = case X of %% lists (bound things in head scope over tail) [A | As] -> Scoped(Same(A), Same(As)); @@ -55,7 +50,6 @@ fold(Alg = #alg{zero = Zero, plus = Plus, scoped = Scoped}, Fun, K, X) -> {fun_decl, _, _, T} -> Type(T); {letval, _, F, T, E} -> Sum([BindExpr(F), Type(T), Expr(E)]); {letfun, _, F, Xs, T, E} -> Sum([BindExpr(F), Type(T), Scoped(BindExpr(Xs), Expr(E))]); - {letrec, _, Ds} -> Plus(Bound(Ds), Decl(Ds)); %% typedef() {alias_t, T} -> Type(T); {record_t, Fs} -> Type(Fs); diff --git a/test/aeso_scan_tests.erl b/test/aeso_scan_tests.erl index 32b8456..685d3ac 100644 --- a/test/aeso_scan_tests.erl +++ b/test/aeso_scan_tests.erl @@ -41,7 +41,7 @@ all_tokens() -> %% Operators lists:map(Lit, ['=', '==', '!=', '>', '<', '>=', '=<', '-', '+', '++', '*', '/', mod, ':', '::', '->', '=>', '||', '&&', '!']) ++ %% Keywords - lists:map(Lit, [contract, type, 'let', switch, rec, 'and']) ++ + lists:map(Lit, [contract, type, 'let', switch]) ++ %% Comment token (not an actual token), just for tests [{comment, 0, "// *Comment!\"\n"}, {comment, 0, "/* bla /* bla bla */*/"}] ++ diff --git a/test/contracts/all_syntax.aes b/test/contracts/all_syntax.aes index 4b80311..1b3b7c1 100644 --- a/test/contracts/all_syntax.aes +++ b/test/contracts/all_syntax.aes @@ -36,11 +36,6 @@ contract AllSyntax = (x, [y, z]) => bar({x = z, y = -y + - -z * (-1)}) (x, y :: _) => () - function mutual() = - let rec recFun(x : int) = mutFun(x) - and mutFun(x) = if(x =< 0) 1 else x * recFun(x - 1) - recFun(0) - let hash : address = #01ab0fff11 let b = false let qcon = Mod.Con