Remove let rec from Sophia

This commit is contained in:
Ulf Norell 2019-05-10 12:36:08 +02:00
parent a542612c9f
commit f2951d5bd7
9 changed files with 11 additions and 39 deletions

View File

@ -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}, _}} =

View File

@ -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);

View File

@ -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()).

View File

@ -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, []).

View File

@ -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 =

View File

@ -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()}.

View File

@ -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);

View File

@ -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 */*/"}] ++

View File

@ -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